Counting distinct values from JSON using D3.nest() - d3.js

I have a following JSON:
{
"ReturnCode":0,
"ReturnMessage":"Success",
"List":[{
"Client":"Ad",
"Department":"DP",
"ProjectId":"12355",
"ProjectName":"4940"
}, {
"Client":"Ad",
"Department":"SP",
"ProjectId":"12355",
"ProjectName":"4940"
}, {
"Client":"Ad",
"Department":"Co",
"ProjectId":"12355",
"ProjectName":"asdf"
}, {
"Client":"Ad",
"Department":"Co",
"ProjectId":"212355",
"ProjectName":"45ed"
}, {
"Client":"Ad",
"Department":"Co",
"ProjectId":"212355",
"ProjectName":"45ed "
}, {
"Client":"we",
"Department":" SP ",
"ProjectId":"123455",
"ProjectName":"asdf"
}, {
"Client":"we",
"Department":"Co",
"ProjectId":"123455",
"ProjectName":"asdf"
}, {
"Client":"oc",
"Department":"Co",
"ProjectId":"24355",
"ProjectName":"qwe"
}]
}
I just need to count the number of projects to each client like below using d3.nest:
[{Key:”Ad”, value:2}, {Key:”we”, value:1}, {Key:”oc”, value:1}]

look at d3.nest() link it has many examples for rolling up for d3.nest() function. For your case you can do something like code written below.
d3.json("json/data.json", function(data) {
console.log(data);
var nested_data = d3.nest()
.key(function(d) { return d.Client; })
.key(function(d) { return d.ProjectId; })
.rollup(function(leaves) { return leaves.length; })
.entries(data.List);
console.log(nested_data);
console.log(nested_data[0].values.length) //length of key 'AD'
})

Try this way.
var obj = {
"ReturnCode":0,
"ReturnMessage":"Success",
"List":[{
"Client":"Ad",
"Department":"DP",
"ProjectId":"12355",
"ProjectName":"4940"
}, {
"Client":"Ad",
"Department":"SP",
"ProjectId":"12355",
"ProjectName":"4940"
}, {
"Client":"Ad",
"Department":"Co",
"ProjectId":"12355",
"ProjectName":"asdf"
}, {
"Client":"Ad",
"Department":"Co",
"ProjectId":"212355",
"ProjectName":"45ed"
}, {
"Client":"Ad",
"Department":"Co",
"ProjectId":"212355",
"ProjectName":"45ed "
}, {
"Client":"we",
"Department":" SP ",
"ProjectId":"123455",
"ProjectName":"asdf"
}, {
"Client":"we",
"Department":"Co",
"ProjectId":"123455",
"ProjectName":"asdf"
}, {
"Client":"oc",
"Department":"Co",
"ProjectId":"24355",
"ProjectName":"qwe"
}]
};
var nested_data = d3.nest()
.key(function(d) { return d.Client; })
.key(function(d) { return d.ProjectId; })
.rollup(function(leaves) { return leaves.length; })
.entries(obj.List)
.map(function(d){
var ob = {};
ob.Key = d.key;
ob.value = d.values.length;
return ob;
});
alert(JSON.stringify(nested_data));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
Output:
[{
"Key": "Ad",
"value": 2
}, {
"Key": "we",
"value": 1
}, {
"Key": "oc",
"value": 1
}]

for the last part i would simply use ----
for (var item in nested_data) {
console.log(nested_data[item].key+'--'+ Object.keys(nested_data[item].values).length);
}

Related

How to Edit a row in Datatable .net core

I try to update a row in my datatable with .net core. Datatable show data and have a new/delete button that works. But when I try to edit a row, I can't get it to work.
Here is mi index.cshtml. Thanks
"ajax": {
"url": "../LoadIntervaloTrabajo",
"type": "POST",
"data": { "codigo": #Model.codigo},
"datatype": "json"
},
"columns": [
{ "data": "horario", "autowidth": true },
{ "data": "codigo", "autowidth": true },
{ "data": "descripcion", "autowidth": true },
{ "data": "horainicio", "autowidth": true },
{ "data": "duracion", "autowidth": true },
{ "data": "cortentrada", "autowidth": true },
{ "data": "cortintermedia", "autowidth": true },
{ "data": "cortsalida", "autowidth": true },
{ "render": function (data, type, row) {
return "<a href='#' class='btn btn-info' onclick=EditData('" + row.codigo + "'); >Editar</a>";
}
},
function EditData(codigo) {
var table = $("#customerDatatable").DataTable();
var r = table.rows(".selected").nodes()[0];
if ($(table.buttons(".editButton")[0].node).find("span").text() == "Cancel") {
$(r).children("td").each(function (i, it) {
if (i > 0) {
var od = table.cells(it).data()[0];
$(it).html(od);
}
});
setButtons('cancel');
} else {
$(r).children("td").each(function (i, it) {
if (i > 0) {
var h = $("<input type='text'>");
h.val(it.innerText);
$(it).html(h);
}
});
setButtons('edit');
}
I try to update a row in my datatable with .net core.
To implement updating row functionality, you can refer to the following code snippet.
Render two buttons for updating row within the last column
"columns": [
{
"data": "horario", "autowidth": true
},
{ "data": "codigo", "autowidth": true },
{ "data": "descripcion", "autowidth": true },
{ "data": "horainicio", "autowidth": true },
{ "data": "duracion", "autowidth": true },
{ "data": "cortentrada", "autowidth": true },
{ "data": "cortintermedia", "autowidth": true },
{ "data": "cortsalida", "autowidth": true },
{
"render": function (data, type, row) { return "<a href='#' class='btn btn-info' onclick = EditData(this); >Editar</a><a href='#' class='btn btn-info btn-hidden' onclick = UpdateData(this); >Updatear</a>"; }
}
]
JS function
function EditData(btnedit) {
//find current row
var $row = $(btnedit).parent().parent();
var $tds = $row.find("td").not(':nth-child(2)').not(':last');
$.each($tds, function (i, el) {
var txt = $(this).text();
$(this).html("").append("<input type='text' value=\"" + txt + "\">");
});
$(btnedit).siblings("a").removeClass("btn-hidden");
$(btnedit).addClass("btn-hidden");
}
function UpdateData(btnupdate) {
var $row = $(btnupdate).parent().parent();
var horario = $row.find("td:nth-child(1)").find("input").val();
var codigo = $row.find("td:nth-child(2)").text();
var descripcion = $row.find("td:nth-child(3)").find("input").val();
var horainicio = $row.find("td:nth-child(4)").find("input").val();
var duracion = $row.find("td:nth-child(5)").find("input").val();
var cortentrada = $row.find("td:nth-child(6)").find("input").val();
var cortintermedia = $row.find("td:nth-child(7)").find("input").val();
var cortsalida = $row.find("td:nth-child(8)").find("input").val();
var data_for_update = { "horario": horario, "codigo": codigo, "descripcion": descripcion, "horainicio": horainicio, "duracion": duracion, "cortentrada": cortentrada, "cortintermedia": cortintermedia, "cortsalida": cortsalida };
//console.log(data_for_update);
//make request to update data
$.ajax({
type: 'POST',
contentType: 'application/json; charset=utf-8',
url: "/{controller_name_here}/Update",
data: JSON.stringify(data_for_update),
success: function (json) {
console.log(json);
var $tds = $row.find("td").not(':nth-child(2)').not(':last');
$.each($tds, function (i, el) {
var txt = $(this).find("input").val()
$(this).html(txt);
});
$(btnupdate).siblings("a").removeClass("btn-hidden");
$(btnupdate).addClass("btn-hidden");
},
//...
});
}
CSS style
.btn-hidden{
display:none;
}
Test Result

Random horizontal line showing in d3 line chart?

I'm plotting data as a line chart and for some reason there are random horizontal lines going across one part of the graph:
I'm plotting my data like this:
const timeConv = d3.timeParse("%Y-%m-%dT%H:%M:%S.%f");
const width = 960;
const height = 500;
const margin = 5;
const padding = 5;
const adj = 30;
/* adding svg */
const svg = d3.select("#chart").append("svg")
.attr("preserveAspectRatio", "none")
.attr("viewBox", "-"
+ adj + " -"
+ adj + " "
+ (width + adj * 3) + " "
+ (height + adj * 3))
.attr("height", "100%")
.style("padding", padding)
.style("margin", margin)
/* sanitizing data */
const dataset = d3.json("formattedStats.json")
dataset.then(function(data) {
/* scaling */
const xScale = d3.scaleTime().range([0, width]);
const yScale = d3.scaleLinear().rangeRound([height, 0]);
xScale.domain(d3.extent(data, d => timeConv(d.dateCreated)));
yScale.domain([
0,
d3.max(data, d => d.balance)
]);
const yaxis = d3.axisLeft()
.ticks(20)
.scale(yScale);
const xaxis = d3.axisBottom()
.ticks(d3.timeDay.filter(d => d3.timeDay.count(0, d) % 3 === 0))
.tickFormat(d3.timeFormat('%b %d'))
.scale(xScale);
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + height + ")")
.call(xaxis);
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0, 0)")
.call(yaxis);
const line = d3.line()
.x((d) => xScale(timeConv(d.dateCreated)))
.y((d) => yScale(d.balance));
svg.append("path")
.attr("d", line(data))
.attr("stroke", "black")
});
And my data looks like this:
[
{
"balance":1433,
"dateCreated":"2020-07-23T19:03:38.627"
},
{
"balance":1426,
"dateCreated":"2020-07-23T19:01:50.766"
},
{
"balance":1449,
"dateCreated":"2020-07-23T06:58:56.856"
},
{
"balance":1465,
"dateCreated":"2020-07-23T06:45:02.957"
},
{
"balance":1476,
"dateCreated":"2020-07-23T06:38:27.707"
},
{
"balance":1483,
"dateCreated":"2020-07-23T06:09:21.723"
},
{
"balance":1489,
"dateCreated":"2020-07-23T06:07:10.662"
},
{
"balance":1506,
"dateCreated":"2020-07-23T06:07:01.501"
},
{
"balance":1515,
"dateCreated":"2020-07-23T04:06:49.871"
},
{
"balance":1531,
"dateCreated":"2020-07-23T03:47:41.251"
},
{
"balance":1542,
"dateCreated":"2020-07-23T03:04:08.571"
},
{
"balance":1558,
"dateCreated":"2020-07-23T02:27:07.284"
},
{
"balance":1575,
"dateCreated":"2020-07-23T02:21:03.609"
},
{
"balance":1591,
"dateCreated":"2020-07-23T02:14:47.54"
},
{
"balance":1596,
"dateCreated":"2020-07-23T02:13:51.064"
},
{
"balance":1612,
"dateCreated":"2020-07-23T02:13:35.578"
},
{
"balance":1620,
"dateCreated":"2020-07-23T01:49:01.64"
},
{
"balance":1606,
"dateCreated":"2020-07-23T01:05:31.986"
},
{
"balance":1639,
"dateCreated":"2020-07-23T00:13:31.93"
},
{
"balance":1656,
"dateCreated":"2020-07-23T00:05:29.045"
},
{
"balance":1672,
"dateCreated":"2020-07-22T23:53:33.355"
},
{
"balance":1679,
"dateCreated":"2020-07-22T23:45:19.324"
},
{
"balance":1702,
"dateCreated":"2020-07-22T08:06:04.961"
},
{
"balance":1709,
"dateCreated":"2020-07-22T07:41:31.159"
},
{
"balance":949,
"dateCreated":"2020-07-22T06:11:06.519"
},
{
"balance":915,
"dateCreated":"2020-07-22T04:11:45.495"
},
{
"balance":932,
"dateCreated":"2020-07-22T03:31:21.528"
},
{
"balance":981,
"dateCreated":"2020-07-22T02:09:29.896"
},
{
"balance":965,
"dateCreated":"2020-07-22T02:08:44.348"
},
{
"balance":859,
"dateCreated":"2020-07-21T23:16:21.725"
},
{
"balance":837,
"dateCreated":"2020-07-21T22:11:51.734"
},
{
"balance":853,
"dateCreated":"2020-07-21T21:51:33.269"
},
{
"balance":869,
"dateCreated":"2020-07-21T21:25:00.833"
},
{
"balance":862,
"dateCreated":"2020-07-21T21:17:35.604"
},
{
"balance":839,
"dateCreated":"2020-07-21T20:30:21.715"
},
{
"balance":856,
"dateCreated":"2020-07-21T07:51:15.532"
},
{
"balance":899,
"dateCreated":"2020-07-21T07:10:07.262"
},
{
"balance":915,
"dateCreated":"2020-07-21T05:37:19.123"
},
{
"balance":910,
"dateCreated":"2020-07-21T05:33:59.065"
},
{
"balance":883,
"dateCreated":"2020-07-21T05:24:11.467"
},
{
"balance":871,
"dateCreated":"2020-07-21T03:21:38.474"
},
{
"balance":888,
"dateCreated":"2020-07-21T03:10:32.186"
},
{
"balance":891,
"dateCreated":"2020-07-21T03:05:09.042"
},
{
"balance":861,
"dateCreated":"2020-07-21T02:05:56.146"
},
{
"balance":878,
"dateCreated":"2020-07-21T01:43:27.761"
},
{
"balance":901,
"dateCreated":"2020-07-21T01:34:25.554"
},
{
"balance":907,
"dateCreated":"2020-07-20T23:18:39.558"
},
{
"balance":924,
"dateCreated":"2020-07-20T22:59:25.504"
},
{
"balance":940,
"dateCreated":"2020-07-20T21:01:51.96"
},
{
"balance":879,
"dateCreated":"2020-07-20T20:48:54.406"
},
{
"balance":857,
"dateCreated":"2020-07-20T19:56:13.648"
},
{
"balance":890,
"dateCreated":"2020-07-20T19:50:26.716"
},
{
"balance":906,
"dateCreated":"2020-07-20T19:00:18.921"
},
{
"balance":882,
"dateCreated":"2020-07-20T07:46:33.574"
},
{
"balance":896,
"dateCreated":"2020-07-20T07:07:40.55"
},
{
"balance":879,
"dateCreated":"2020-07-20T07:04:25.858"
},
{
"balance":906,
"dateCreated":"2020-07-20T06:52:07.748"
},
{
"balance":922,
"dateCreated":"2020-07-20T06:42:51.575"
},
{
"balance":927,
"dateCreated":"2020-07-20T06:42:31.973"
},
{
"balance":934.26,
"dateCreated":"2020-07-20T06:16:09.036"
},
{
"balance":902,
"dateCreated":"2020-07-20T05:31:56.692"
},
{
"balance":923,
"dateCreated":"2020-07-20T05:31:47.108"
},
{
"balance":894,
"dateCreated":"2020-07-20T05:22:20.871"
},
{
"balance":867,
"dateCreated":"2020-07-20T04:00:32.576"
},
{
"balance":883,
"dateCreated":"2020-07-20T04:00:26.06"
},
{
"balance":900,
"dateCreated":"2020-07-20T02:14:11.529"
},
{
"balance":916,
"dateCreated":"2020-07-20T01:38:55.908"
},
{
"balance":933,
"dateCreated":"2020-07-20T01:23:53.772"
},
{
"balance":949,
"dateCreated":"2020-07-20T01:23:45.458"
},
{
"balance":956,
"dateCreated":"2020-07-19T23:33:45.224"
},
{
"balance":962,
"dateCreated":"2020-07-19T23:08:56.22"
},
{
"balance":979,
"dateCreated":"2020-07-19T23:08:38.623"
},
{
"balance":880,
"dateCreated":"2020-07-19T23:06:48.195"
},
{
"balance":894,
"dateCreated":"2020-07-19T22:12:00.778"
},
{
"balance":877,
"dateCreated":"2020-07-19T21:57:13.62"
},
{
"balance":910,
"dateCreated":"2020-07-19T21:33:02.45"
},
{
"balance":925,
"dateCreated":"2020-07-19T21:25:22.116"
},
{
"balance":949,
"dateCreated":"2020-07-19T21:20:51.796"
},
{
"balance":965,
"dateCreated":"2020-07-19T20:59:27.897"
},
{
"balance":982,
"dateCreated":"2020-07-19T07:47:45.451"
},
{
"balance":822,
"dateCreated":"2020-07-19T07:44:31.419"
},
{
"balance":879,
"dateCreated":"2020-07-19T07:34:22.508"
},
{
"balance":797,
"dateCreated":"2020-07-19T06:46:47.993"
},
{
"balance":814,
"dateCreated":"2020-07-19T06:46:07.785"
},
{
"balance":820,
"dateCreated":"2020-07-19T06:36:24.427"
},
{
"balance":827,
"dateCreated":"2020-07-19T06:20:59.223"
},
{
"balance":861,
"dateCreated":"2020-07-19T06:19:46.962"
},
{
"balance":823,
"dateCreated":"2020-07-19T06:08:21.955"
},
{
"balance":840,
"dateCreated":"2020-07-19T06:07:30.056"
},
{
"balance":851,
"dateCreated":"2020-07-19T06:05:20.705"
},
{
"balance":849,
"dateCreated":"2020-07-19T05:39:32.269"
},
{
"balance":866.29,
"dateCreated":"2020-07-19T05:26:06.534"
},
{
"balance":825,
"dateCreated":"2020-07-19T05:13:44.842"
},
{
"balance":836,
"dateCreated":"2020-07-19T05:11:43.612"
},
{
"balance":852,
"dateCreated":"2020-07-19T05:04:52.876"
},
{
"balance":858,
"dateCreated":"2020-07-19T05:04:27.291"
},
{
"balance":874.54,
"dateCreated":"2020-07-19T05:04:12.409"
},
{
"balance":843,
"dateCreated":"2020-07-19T04:57:22.911"
},
{
"balance":859,
"dateCreated":"2020-07-19T04:52:21.601"
},
{
"balance":875.24,
"dateCreated":"2020-07-19T04:50:29"
},
{
"balance":847,
"dateCreated":"2020-07-19T04:45:57.354"
},
{
"balance":880,
"dateCreated":"2020-07-19T04:28:35.598"
},
{
"balance":897,
"dateCreated":"2020-07-19T04:17:26.469"
},
{
"balance":913,
"dateCreated":"2020-07-18T07:16:47.016"
},
{
"balance":947,
"dateCreated":"2020-07-18T06:37:00.094"
},
{
"balance":930,
"dateCreated":"2020-07-18T06:31:42.495"
},
{
"balance":952,
"dateCreated":"2020-07-17T09:08:22.177"
},
{
"balance":939.94,
"dateCreated":"2020-07-17T08:49:21.978"
},
{
"balance":918,
"dateCreated":"2020-07-17T08:34:31.417"
},
{
"balance":929,
"dateCreated":"2020-07-17T08:34:01.094"
},
{
"balance":935,
"dateCreated":"2020-07-16T07:08:20.004"
},
{
"balance":951,
"dateCreated":"2020-07-16T07:07:46.132"
},
{
"balance":968,
"dateCreated":"2020-07-14T04:39:32.887"
},
{
"balance":984,
"dateCreated":"2020-07-14T04:39:15.779"
},
{
"balance":1000,
"dateCreated":"2020-07-14T02:03:00.87"
},
{
"balance":1017,
"dateCreated":"2020-07-14T01:31:32.207"
},
{
"balance":1033,
"dateCreated":"2020-07-14T01:31:19.978"
},
{
"balance":1040,
"dateCreated":"2020-07-13T23:23:29.921"
},
{
"balance":1095.59,
"dateCreated":"2020-07-13T23:18:21.912"
},
{
"balance":1072,
"dateCreated":"2020-07-13T22:37:24.883"
},
{
"balance":1088,
"dateCreated":"2020-07-13T21:00:57.88"
},
{
"balance":1091,
"dateCreated":"2020-07-13T20:10:58.344"
},
{
"balance":1093.04,
"dateCreated":"2020-07-13T20:10:39.9"
},
{
"balance":1055,
"dateCreated":"2020-07-13T19:20:51.553"
},
{
"balance":1071,
"dateCreated":"2020-07-13T19:09:34.993"
},
{
"balance":1071,
"dateCreated":"2020-07-13T19:09:12.291"
},
{
"balance":1088.47,
"dateCreated":"2020-07-13T08:34:06.731"
},
{
"balance":1020.97,
"dateCreated":"2020-07-13T08:24:09.093"
},
{
"balance":999,
"dateCreated":"2020-07-13T08:12:13.226"
},
{
"balance":1015,
"dateCreated":"2020-07-13T07:49:26.818"
},
{
"balance":1032,
"dateCreated":"2020-07-13T07:40:00.178"
},
{
"balance":1114,
"dateCreated":"2020-07-12T23:23:32.335"
},
{
"balance":1154,
"dateCreated":"2020-07-12T21:01:59.128"
},
{
"balance":1169.97,
"dateCreated":"2020-07-12T14:39:57.463"
},
{
"balance":1156,
"dateCreated":"2020-07-12T14:01:02.792"
},
{
"balance":1172,
"dateCreated":"2020-07-12T13:55:36.566"
},
{
"balance":1177,
"dateCreated":"2020-07-12T13:55:19.394"
},
{
"balance":1156,
"dateCreated":"2020-07-12T08:24:33.968"
},
{
"balance":1121,
"dateCreated":"2020-07-12T08:08:41.735"
},
{
"balance":1089,
"dateCreated":"2020-07-12T06:48:28.84"
},
{
"balance":1106,
"dateCreated":"2020-07-12T05:40:55.865"
},
{
"balance":1036,
"dateCreated":"2020-07-11T22:45:14.995"
},
{
"balance":1012,
"dateCreated":"2020-07-11T21:52:56.498"
},
{
"balance":1028,
"dateCreated":"2020-07-11T21:36:53.419"
},
{
"balance":1043,
"dateCreated":"2020-07-11T09:20:19.116"
},
{
"balance":1037,
"dateCreated":"2020-07-11T08:27:01.816"
},
{
"balance":1043,
"dateCreated":"2020-07-11T08:26:45.696"
},
{
"balance":1066,
"dateCreated":"2020-07-11T08:26:30.808"
},
{
"balance":1070,
"dateCreated":"2020-07-11T08:08:32.191"
},
{
"balance":1081.18,
"dateCreated":"2020-07-11T08:04:44.88"
},
{
"balance":1049,
"dateCreated":"2020-07-11T06:59:57.157"
},
{
"balance":1066,
"dateCreated":"2020-07-11T06:29:55.306"
},
{
"balance":1082,
"dateCreated":"2020-07-11T06:29:37.378"
},
{
"balance":1089,
"dateCreated":"2020-07-10T07:20:38.373"
},
{
"balance":1120,
"dateCreated":"2020-07-10T07:04:02.663"
},
{
"balance":1131,
"dateCreated":"2020-07-10T07:02:00.364"
},
{
"balance":1148,
"dateCreated":"2020-07-10T05:50:07.739"
},
{
"balance":1164,
"dateCreated":"2020-07-10T05:24:33.478"
},
{
"balance":1108,
"dateCreated":"2020-07-10T05:23:31.012"
},
{
"balance":1083,
"dateCreated":"2020-07-10T04:10:02.153"
},
{
"balance":1099,
"dateCreated":"2020-07-10T04:09:37.055"
},
{
"balance":1114,
"dateCreated":"2020-07-10T02:40:05.837"
},
{
"balance":1095,
"dateCreated":"2020-07-10T02:13:02.745"
},
{
"balance":1106.16,
"dateCreated":"2020-07-10T02:10:33.916668"
},
{
"balance":1108,
"dateCreated":"2020-07-10T01:43:12.406"
},
{
"balance":1092,
"dateCreated":"2020-07-10T01:39:59.102"
},
{
"balance":1113,
"dateCreated":"2020-07-10T01:35:38.467"
},
{
"balance":1087,
"dateCreated":"2020-07-10T01:14:38.311"
},
{
"balance":1103,
"dateCreated":"2020-07-10T00:50:09.294"
},
{
"balance":1153,
"dateCreated":"2020-07-10T00:35:48.635"
},
{
"balance":1136,
"dateCreated":"2020-07-10T00:13:15.698"
},
{
"balance":1169,
"dateCreated":"2020-07-09T23:42:45.742"
},
{
"balance":1180,
"dateCreated":"2020-07-09T23:41:51.207"
},
{
"balance":1186,
"dateCreated":"2020-07-09T20:29:33.056"
},
{
"balance":1219,
"dateCreated":"2020-07-09T19:34:09.69"
},
{
"balance":1235,
"dateCreated":"2020-07-09T19:18:24.581"
},
{
"balance":1236,
"dateCreated":"2020-07-09T19:11:14.349"
},
{
"balance":1252,
"dateCreated":"2020-07-09T17:13:40.924"
},
{
"balance":1268,
"dateCreated":"2020-07-09T06:47:22.183"
},
{
"balance":1284,
"dateCreated":"2020-07-08T17:42:38.056"
},
{
"balance":1301,
"dateCreated":"2020-07-08T17:42:28.833"
},
{
"balance":1306.58,
"dateCreated":"2020-07-08T08:49:25.341"
},
{
"balance":1285.58,
"dateCreated":"2020-07-08T08:32:08.722"
},
{
"balance":1275,
"dateCreated":"2020-07-08T08:29:17.285"
},
{
"balance":1282,
"dateCreated":"2020-07-08T08:29:09.891"
},
{
"balance":1285,
"dateCreated":"2020-07-08T08:22:57.768"
},
{
"balance":1290,
"dateCreated":"2020-07-08T08:20:55.432"
},
{
"balance":1294,
"dateCreated":"2020-07-08T07:06:29.286"
},
{
"balance":1300,
"dateCreated":"2020-07-08T06:47:13.151"
},
{
"balance":1291,
"dateCreated":"2020-07-08T06:44:23.775"
},
{
"balance":1270,
"dateCreated":"2020-07-08T05:46:22.013"
},
{
"balance":1287,
"dateCreated":"2020-07-08T05:45:47.899"
},
{
"balance":1149,
"dateCreated":"2020-07-07T11:19:38.463"
},
{
"balance":1129.93,
"dateCreated":"2020-07-07T08:29:41.744"
},
{
"balance":1107,
"dateCreated":"2020-07-07T07:48:21.005"
},
{
"balance":1116,
"dateCreated":"2020-07-07T07:48:04.45"
},
{
"balance":1134,
"dateCreated":"2020-07-07T06:07:27.17"
},
{
"balance":1101,
"dateCreated":"2020-07-06T18:13:04.993"
},
{
"balance":1075,
"dateCreated":"2020-07-06T16:50:49.551"
},
{
"balance":1098,
"dateCreated":"2020-07-06T16:41:05.869"
},
{
"balance":1105,
"dateCreated":"2020-07-06T04:53:57.638"
},
{
"balance":1121,
"dateCreated":"2020-07-06T04:53:47.715"
},
{
"balance":1128,
"dateCreated":"2020-07-06T03:52:28.386"
},
{
"balance":1194,
"dateCreated":"2020-07-06T03:33:55.42"
},
{
"balance":1177,
"dateCreated":"2020-07-06T03:19:55.119"
},
{
"balance":1210,
"dateCreated":"2020-07-06T02:53:50.235"
},
{
"balance":1227,
"dateCreated":"2020-07-06T02:40:53.788"
},
{
"balance":1243,
"dateCreated":"2020-07-06T02:40:39.762"
},
{
"balance":1252,
"dateCreated":"2020-07-06T02:19:43.451"
},
{
"balance":1269,
"dateCreated":"2020-07-05T21:41:31.196"
},
{
"balance":1275,
"dateCreated":"2020-07-05T21:34:16.157"
},
{
"balance":1219,
"dateCreated":"2020-07-05T19:53:26.309"
},
{
"balance":1192,
"dateCreated":"2020-07-05T19:04:36.269"
},
{
"balance":1198,
"dateCreated":"2020-07-05T19:04:10.751"
},
{
"balance":1249,
"dateCreated":"2020-07-04T05:38:08.098"
},
{
"balance":1228,
"dateCreated":"2020-07-04T05:23:06.225"
},
{
"balance":1271,
"dateCreated":"2020-07-04T03:26:17.131"
},
{
"balance":1304,
"dateCreated":"2020-07-04T03:12:01.939"
},
{
"balance":1327,
"dateCreated":"2020-07-04T03:09:45.315"
},
{
"balance":1334,
"dateCreated":"2020-07-04T02:45:19.182"
},
{
"balance":1343,
"dateCreated":"2020-07-03T20:49:14.146"
},
{
"balance":1353.8,
"dateCreated":"2020-07-03T08:00:24.059"
},
{
"balance":1290,
"dateCreated":"2020-07-03T07:39:10.192"
},
{
"balance":1322,
"dateCreated":"2020-07-03T07:28:01.269"
},
{
"balance":1322.65,
"dateCreated":"2020-07-02T08:16:47.869"
},
{
"balance":1287,
"dateCreated":"2020-07-02T06:46:09.676"
},
{
"balance":1304,
"dateCreated":"2020-07-02T06:40:26.221"
},
{
"balance":1310,
"dateCreated":"2020-07-02T06:30:15.057"
},
{
"balance":1328,
"dateCreated":"2020-07-01T06:40:06.844"
},
{
"balance":1345,
"dateCreated":"2020-07-01T06:23:22.739"
},
{
"balance":1348,
"dateCreated":"2020-06-30T08:09:53.259"
},
{
"balance":1318,
"dateCreated":"2020-06-30T06:43:08.339"
},
{
"balance":1334,
"dateCreated":"2020-06-30T06:42:51.645"
}
]
Does anyone know why this might be happening? Thanks!
This sort of error (where the graph/chart line/rect/path/circle is largely correct but with one or two errant points) can generally be traced to one of two issues:
Errors in data
Errors in parsing the data
In your case, the data is fine but your parsing of it does not account for an edge case, when your time does not have milliseconds, compare:
const timeConv = d3.timeParse("%Y-%m-%dT%H:%M:%S.%f");
console.log(timeConv("2020-07-19T04:50:29"));
console.log(timeConv("2020-07-19T04:52:21.601"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
In your case, for one data point, d3.timeParse returns a null value in your case for one data point, causing a badly scaled x value for the path.
Two solutions come to mind, fix the data so this point is formatted as expected, or create a second time parser to account for this edge case:
.x((d) => xScale(timeConv(d.dateCreated) || timeConvEdgeCase(d.dateCreated)))
This seems hackier than ensuring consistently formatted data, but depending on your data source, this might need to be done inline or in loading the data in the browser anyways.
const data=[{"balance":1433,"dateCreated":"2020-07-23T19:03:38.627"},{"balance":1426,"dateCreated":"2020-07-23T19:01:50.766"},{"balance":1449,"dateCreated":"2020-07-23T06:58:56.856"},{"balance":1465,"dateCreated":"2020-07-23T06:45:02.957"},{"balance":1476,"dateCreated":"2020-07-23T06:38:27.707"},{"balance":1483,"dateCreated":"2020-07-23T06:09:21.723"},{"balance":1489,"dateCreated":"2020-07-23T06:07:10.662"},{"balance":1506,"dateCreated":"2020-07-23T06:07:01.501"},{"balance":1515,"dateCreated":"2020-07-23T04:06:49.871"},{"balance":1531,"dateCreated":"2020-07-23T03:47:41.251"},{"balance":1542,"dateCreated":"2020-07-23T03:04:08.571"},{"balance":1558,"dateCreated":"2020-07-23T02:27:07.284"},{"balance":1575,"dateCreated":"2020-07-23T02:21:03.609"},{"balance":1591,"dateCreated":"2020-07-23T02:14:47.54"},{"balance":1596,"dateCreated":"2020-07-23T02:13:51.064"},{"balance":1612,"dateCreated":"2020-07-23T02:13:35.578"},{"balance":1620,"dateCreated":"2020-07-23T01:49:01.64"},{"balance":1606,"dateCreated":"2020-07-23T01:05:31.986"},{"balance":1639,"dateCreated":"2020-07-23T00:13:31.93"},{"balance":1656,"dateCreated":"2020-07-23T00:05:29.045"},{"balance":1672,"dateCreated":"2020-07-22T23:53:33.355"},{"balance":1679,"dateCreated":"2020-07-22T23:45:19.324"},{"balance":1702,"dateCreated":"2020-07-22T08:06:04.961"},{"balance":1709,"dateCreated":"2020-07-22T07:41:31.159"},{"balance":949,"dateCreated":"2020-07-22T06:11:06.519"},{"balance":915,"dateCreated":"2020-07-22T04:11:45.495"},{"balance":932,"dateCreated":"2020-07-22T03:31:21.528"},{"balance":981,"dateCreated":"2020-07-22T02:09:29.896"},{"balance":965,"dateCreated":"2020-07-22T02:08:44.348"},{"balance":859,"dateCreated":"2020-07-21T23:16:21.725"},{"balance":837,"dateCreated":"2020-07-21T22:11:51.734"},{"balance":853,"dateCreated":"2020-07-21T21:51:33.269"},{"balance":869,"dateCreated":"2020-07-21T21:25:00.833"},{"balance":862,"dateCreated":"2020-07-21T21:17:35.604"},{"balance":839,"dateCreated":"2020-07-21T20:30:21.715"},{"balance":856,"dateCreated":"2020-07-21T07:51:15.532"},{"balance":899,"dateCreated":"2020-07-21T07:10:07.262"},{"balance":915,"dateCreated":"2020-07-21T05:37:19.123"},{"balance":910,"dateCreated":"2020-07-21T05:33:59.065"},{"balance":883,"dateCreated":"2020-07-21T05:24:11.467"},{"balance":871,"dateCreated":"2020-07-21T03:21:38.474"},{"balance":888,"dateCreated":"2020-07-21T03:10:32.186"},{"balance":891,"dateCreated":"2020-07-21T03:05:09.042"},{"balance":861,"dateCreated":"2020-07-21T02:05:56.146"},{"balance":878,"dateCreated":"2020-07-21T01:43:27.761"},{"balance":901,"dateCreated":"2020-07-21T01:34:25.554"},{"balance":907,"dateCreated":"2020-07-20T23:18:39.558"},{"balance":924,"dateCreated":"2020-07-20T22:59:25.504"},{"balance":940,"dateCreated":"2020-07-20T21:01:51.96"},{"balance":879,"dateCreated":"2020-07-20T20:48:54.406"},{"balance":857,"dateCreated":"2020-07-20T19:56:13.648"},{"balance":890,"dateCreated":"2020-07-20T19:50:26.716"},{"balance":906,"dateCreated":"2020-07-20T19:00:18.921"},{"balance":882,"dateCreated":"2020-07-20T07:46:33.574"},{"balance":896,"dateCreated":"2020-07-20T07:07:40.55"},{"balance":879,"dateCreated":"2020-07-20T07:04:25.858"},{"balance":906,"dateCreated":"2020-07-20T06:52:07.748"},{"balance":922,"dateCreated":"2020-07-20T06:42:51.575"},{"balance":927,"dateCreated":"2020-07-20T06:42:31.973"},{"balance":934.26,"dateCreated":"2020-07-20T06:16:09.036"},{"balance":902,"dateCreated":"2020-07-20T05:31:56.692"},{"balance":923,"dateCreated":"2020-07-20T05:31:47.108"},{"balance":894,"dateCreated":"2020-07-20T05:22:20.871"},{"balance":867,"dateCreated":"2020-07-20T04:00:32.576"},{"balance":883,"dateCreated":"2020-07-20T04:00:26.06"},{"balance":900,"dateCreated":"2020-07-20T02:14:11.529"},{"balance":916,"dateCreated":"2020-07-20T01:38:55.908"},{"balance":933,"dateCreated":"2020-07-20T01:23:53.772"},{"balance":949,"dateCreated":"2020-07-20T01:23:45.458"},{"balance":956,"dateCreated":"2020-07-19T23:33:45.224"},{"balance":962,"dateCreated":"2020-07-19T23:08:56.22"},{"balance":979,"dateCreated":"2020-07-19T23:08:38.623"},{"balance":880,"dateCreated":"2020-07-19T23:06:48.195"},{"balance":894,"dateCreated":"2020-07-19T22:12:00.778"},{"balance":877,"dateCreated":"2020-07-19T21:57:13.62"},{"balance":910,"dateCreated":"2020-07-19T21:33:02.45"},{"balance":925,"dateCreated":"2020-07-19T21:25:22.116"},{"balance":949,"dateCreated":"2020-07-19T21:20:51.796"},{"balance":965,"dateCreated":"2020-07-19T20:59:27.897"},{"balance":982,"dateCreated":"2020-07-19T07:47:45.451"},{"balance":822,"dateCreated":"2020-07-19T07:44:31.419"},{"balance":879,"dateCreated":"2020-07-19T07:34:22.508"},{"balance":797,"dateCreated":"2020-07-19T06:46:47.993"},{"balance":814,"dateCreated":"2020-07-19T06:46:07.785"},{"balance":820,"dateCreated":"2020-07-19T06:36:24.427"},{"balance":827,"dateCreated":"2020-07-19T06:20:59.223"},{"balance":861,"dateCreated":"2020-07-19T06:19:46.962"},{"balance":823,"dateCreated":"2020-07-19T06:08:21.955"},{"balance":840,"dateCreated":"2020-07-19T06:07:30.056"},{"balance":851,"dateCreated":"2020-07-19T06:05:20.705"},{"balance":849,"dateCreated":"2020-07-19T05:39:32.269"},{"balance":866.29,"dateCreated":"2020-07-19T05:26:06.534"},{"balance":825,"dateCreated":"2020-07-19T05:13:44.842"},{"balance":836,"dateCreated":"2020-07-19T05:11:43.612"},{"balance":852,"dateCreated":"2020-07-19T05:04:52.876"},{"balance":858,"dateCreated":"2020-07-19T05:04:27.291"},{"balance":874.54,"dateCreated":"2020-07-19T05:04:12.409"},{"balance":843,"dateCreated":"2020-07-19T04:57:22.911"},{"balance":859,"dateCreated":"2020-07-19T04:52:21.601"},{"balance":875.24,"dateCreated":"2020-07-19T04:50:29"},{"balance":847,"dateCreated":"2020-07-19T04:45:57.354"},{"balance":880,"dateCreated":"2020-07-19T04:28:35.598"},{"balance":897,"dateCreated":"2020-07-19T04:17:26.469"},{"balance":913,"dateCreated":"2020-07-18T07:16:47.016"},{"balance":947,"dateCreated":"2020-07-18T06:37:00.094"},{"balance":930,"dateCreated":"2020-07-18T06:31:42.495"},{"balance":952,"dateCreated":"2020-07-17T09:08:22.177"},{"balance":939.94,"dateCreated":"2020-07-17T08:49:21.978"},{"balance":918,"dateCreated":"2020-07-17T08:34:31.417"},{"balance":929,"dateCreated":"2020-07-17T08:34:01.094"},{"balance":935,"dateCreated":"2020-07-16T07:08:20.004"},{"balance":951,"dateCreated":"2020-07-16T07:07:46.132"},{"balance":968,"dateCreated":"2020-07-14T04:39:32.887"},{"balance":984,"dateCreated":"2020-07-14T04:39:15.779"},{"balance":1000,"dateCreated":"2020-07-14T02:03:00.87"},{"balance":1017,"dateCreated":"2020-07-14T01:31:32.207"},{"balance":1033,"dateCreated":"2020-07-14T01:31:19.978"},{"balance":1040,"dateCreated":"2020-07-13T23:23:29.921"},{"balance":1095.59,"dateCreated":"2020-07-13T23:18:21.912"},{"balance":1072,"dateCreated":"2020-07-13T22:37:24.883"},{"balance":1088,"dateCreated":"2020-07-13T21:00:57.88"},{"balance":1091,"dateCreated":"2020-07-13T20:10:58.344"},{"balance":1093.04,"dateCreated":"2020-07-13T20:10:39.9"},{"balance":1055,"dateCreated":"2020-07-13T19:20:51.553"},{"balance":1071,"dateCreated":"2020-07-13T19:09:34.993"},{"balance":1071,"dateCreated":"2020-07-13T19:09:12.291"},{"balance":1088.47,"dateCreated":"2020-07-13T08:34:06.731"},{"balance":1020.97,"dateCreated":"2020-07-13T08:24:09.093"},{"balance":999,"dateCreated":"2020-07-13T08:12:13.226"},{"balance":1015,"dateCreated":"2020-07-13T07:49:26.818"},{"balance":1032,"dateCreated":"2020-07-13T07:40:00.178"},{"balance":1114,"dateCreated":"2020-07-12T23:23:32.335"},{"balance":1154,"dateCreated":"2020-07-12T21:01:59.128"},{"balance":1169.97,"dateCreated":"2020-07-12T14:39:57.463"},{"balance":1156,"dateCreated":"2020-07-12T14:01:02.792"},{"balance":1172,"dateCreated":"2020-07-12T13:55:36.566"},{"balance":1177,"dateCreated":"2020-07-12T13:55:19.394"},{"balance":1156,"dateCreated":"2020-07-12T08:24:33.968"},{"balance":1121,"dateCreated":"2020-07-12T08:08:41.735"},{"balance":1089,"dateCreated":"2020-07-12T06:48:28.84"},{"balance":1106,"dateCreated":"2020-07-12T05:40:55.865"},{"balance":1036,"dateCreated":"2020-07-11T22:45:14.995"},{"balance":1012,"dateCreated":"2020-07-11T21:52:56.498"},{"balance":1028,"dateCreated":"2020-07-11T21:36:53.419"},{"balance":1043,"dateCreated":"2020-07-11T09:20:19.116"},{"balance":1037,"dateCreated":"2020-07-11T08:27:01.816"},{"balance":1043,"dateCreated":"2020-07-11T08:26:45.696"},{"balance":1066,"dateCreated":"2020-07-11T08:26:30.808"},{"balance":1070,"dateCreated":"2020-07-11T08:08:32.191"},{"balance":1081.18,"dateCreated":"2020-07-11T08:04:44.88"},{"balance":1049,"dateCreated":"2020-07-11T06:59:57.157"},{"balance":1066,"dateCreated":"2020-07-11T06:29:55.306"},{"balance":1082,"dateCreated":"2020-07-11T06:29:37.378"},{"balance":1089,"dateCreated":"2020-07-10T07:20:38.373"},{"balance":1120,"dateCreated":"2020-07-10T07:04:02.663"},{"balance":1131,"dateCreated":"2020-07-10T07:02:00.364"},{"balance":1148,"dateCreated":"2020-07-10T05:50:07.739"},{"balance":1164,"dateCreated":"2020-07-10T05:24:33.478"},{"balance":1108,"dateCreated":"2020-07-10T05:23:31.012"},{"balance":1083,"dateCreated":"2020-07-10T04:10:02.153"},{"balance":1099,"dateCreated":"2020-07-10T04:09:37.055"},{"balance":1114,"dateCreated":"2020-07-10T02:40:05.837"},{"balance":1095,"dateCreated":"2020-07-10T02:13:02.745"},{"balance":1106.16,"dateCreated":"2020-07-10T02:10:33.916668"},{"balance":1108,"dateCreated":"2020-07-10T01:43:12.406"},{"balance":1092,"dateCreated":"2020-07-10T01:39:59.102"},{"balance":1113,"dateCreated":"2020-07-10T01:35:38.467"},{"balance":1087,"dateCreated":"2020-07-10T01:14:38.311"},{"balance":1103,"dateCreated":"2020-07-10T00:50:09.294"},{"balance":1153,"dateCreated":"2020-07-10T00:35:48.635"},{"balance":1136,"dateCreated":"2020-07-10T00:13:15.698"},{"balance":1169,"dateCreated":"2020-07-09T23:42:45.742"},{"balance":1180,"dateCreated":"2020-07-09T23:41:51.207"},{"balance":1186,"dateCreated":"2020-07-09T20:29:33.056"},{"balance":1219,"dateCreated":"2020-07-09T19:34:09.69"},{"balance":1235,"dateCreated":"2020-07-09T19:18:24.581"},{"balance":1236,"dateCreated":"2020-07-09T19:11:14.349"},{"balance":1252,"dateCreated":"2020-07-09T17:13:40.924"},{"balance":1268,"dateCreated":"2020-07-09T06:47:22.183"},{"balance":1284,"dateCreated":"2020-07-08T17:42:38.056"},{"balance":1301,"dateCreated":"2020-07-08T17:42:28.833"},{"balance":1306.58,"dateCreated":"2020-07-08T08:49:25.341"},{"balance":1285.58,"dateCreated":"2020-07-08T08:32:08.722"},{"balance":1275,"dateCreated":"2020-07-08T08:29:17.285"},{"balance":1282,"dateCreated":"2020-07-08T08:29:09.891"},{"balance":1285,"dateCreated":"2020-07-08T08:22:57.768"},{"balance":1290,"dateCreated":"2020-07-08T08:20:55.432"},{"balance":1294,"dateCreated":"2020-07-08T07:06:29.286"},{"balance":1300,"dateCreated":"2020-07-08T06:47:13.151"},{"balance":1291,"dateCreated":"2020-07-08T06:44:23.775"},{"balance":1270,"dateCreated":"2020-07-08T05:46:22.013"},{"balance":1287,"dateCreated":"2020-07-08T05:45:47.899"},{"balance":1149,"dateCreated":"2020-07-07T11:19:38.463"},{"balance":1129.93,"dateCreated":"2020-07-07T08:29:41.744"},{"balance":1107,"dateCreated":"2020-07-07T07:48:21.005"},{"balance":1116,"dateCreated":"2020-07-07T07:48:04.45"},{"balance":1134,"dateCreated":"2020-07-07T06:07:27.17"},{"balance":1101,"dateCreated":"2020-07-06T18:13:04.993"},{"balance":1075,"dateCreated":"2020-07-06T16:50:49.551"},{"balance":1098,"dateCreated":"2020-07-06T16:41:05.869"},{"balance":1105,"dateCreated":"2020-07-06T04:53:57.638"},{"balance":1121,"dateCreated":"2020-07-06T04:53:47.715"},{"balance":1128,"dateCreated":"2020-07-06T03:52:28.386"},{"balance":1194,"dateCreated":"2020-07-06T03:33:55.42"},{"balance":1177,"dateCreated":"2020-07-06T03:19:55.119"},{"balance":1210,"dateCreated":"2020-07-06T02:53:50.235"},{"balance":1227,"dateCreated":"2020-07-06T02:40:53.788"},{"balance":1243,"dateCreated":"2020-07-06T02:40:39.762"},{"balance":1252,"dateCreated":"2020-07-06T02:19:43.451"},{"balance":1269,"dateCreated":"2020-07-05T21:41:31.196"},{"balance":1275,"dateCreated":"2020-07-05T21:34:16.157"},{"balance":1219,"dateCreated":"2020-07-05T19:53:26.309"},{"balance":1192,"dateCreated":"2020-07-05T19:04:36.269"},{"balance":1198,"dateCreated":"2020-07-05T19:04:10.751"},{"balance":1249,"dateCreated":"2020-07-04T05:38:08.098"},{"balance":1228,"dateCreated":"2020-07-04T05:23:06.225"},{"balance":1271,"dateCreated":"2020-07-04T03:26:17.131"},{"balance":1304,"dateCreated":"2020-07-04T03:12:01.939"},{"balance":1327,"dateCreated":"2020-07-04T03:09:45.315"},{"balance":1334,"dateCreated":"2020-07-04T02:45:19.182"},{"balance":1343,"dateCreated":"2020-07-03T20:49:14.146"},{"balance":1353.8,"dateCreated":"2020-07-03T08:00:24.059"},{"balance":1290,"dateCreated":"2020-07-03T07:39:10.192"},{"balance":1322,"dateCreated":"2020-07-03T07:28:01.269"},{"balance":1322.65,"dateCreated":"2020-07-02T08:16:47.869"},{"balance":1287,"dateCreated":"2020-07-02T06:46:09.676"},{"balance":1304,"dateCreated":"2020-07-02T06:40:26.221"},{"balance":1310,"dateCreated":"2020-07-02T06:30:15.057"},{"balance":1328,"dateCreated":"2020-07-01T06:40:06.844"},{"balance":1345,"dateCreated":"2020-07-01T06:23:22.739"},{"balance":1348,"dateCreated":"2020-06-30T08:09:53.259"},{"balance":1318,"dateCreated":"2020-06-30T06:43:08.339"},{"balance":1334,"dateCreated":"2020-06-30T06:42:51.645"}]
const timeConv = d3.timeParse("%Y-%m-%dT%H:%M:%S.%f");
const timeConvEdge = d3.timeParse("%Y-%m-%dT%H:%M:%S");
const width = 960;
const height = 500;
const margin = 5;
const padding = 5;
const adj = 30;
/* adding svg */
const svg = d3.select("#chart").append("svg")
.attr("preserveAspectRatio", "none")
.attr("viewBox", "-"
+ adj + " -"
+ adj + " "
+ (width + adj * 3) + " "
+ (height + adj * 3))
.attr("height", "100%")
.style("padding", padding)
.style("margin", margin)
/* scaling */
const xScale = d3.scaleTime().range([0, width]);
const yScale = d3.scaleLinear().rangeRound([height, 0]);
xScale.domain(d3.extent(data, d => timeConv(d.dateCreated) || timeConvEdge(d.dateCreated)));
yScale.domain([
0,
d3.max(data, d => d.balance)
]);
const yaxis = d3.axisLeft()
.ticks(20)
.scale(yScale);
const xaxis = d3.axisBottom()
.ticks(d3.timeDay.filter(d => d3.timeDay.count(0, d) % 3 === 0))
.tickFormat(d3.timeFormat('%b %d'))
.scale(xScale);
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + height + ")")
.call(xaxis);
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0, 0)")
.call(yaxis);
const line = d3.line()
.x((d) => xScale(timeConv(d.dateCreated) || timeConvEdge(d.dateCreated)))
.y((d) => yScale(d.balance));
svg.append("path")
.attr("d", line(data))
.attr("stroke", "black")
path {
fill: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="chart">

Creating Legend for a power BI custom visual

I'm trying to create a power BI custom visual.I'm currently working on creating a pie chart.
The pie chart visual is being displayed.
I have defined Legend as a boolean property and currently trying to render a legend for the piechart when show property of Legend value is set totrue .
But even when settings.Legend.show is true, No Legend is being shown.
I'm using d3.js to create the visuals.
Can someone help?
Here's my visual.ts
module powerbi.extensibility.visual {
"use strict";
interface Data
{
quantity: number;
category: string;
color:string;
selectionId:ISelectionId;
}
interface PieChartArc {
datapoints:Data[];
setting:pieChartSettings;
dataview:DataView[];
}
interface pieChartSettings
{
Legend :
{
show:boolean;
};
}
interface LegendValues
{
category:string;
color:string;
selection:ISelectionId;
}
function visualTransform(options:VisualUpdateOptions,host:IVisualHost) : PieChartArc
{
let dataViews=options.dataViews;
let defaultSetting :pieChartSettings = {
Legend:{
show:false,
}
};
let viewModel:PieChartArc=
{
datapoints:[],
setting : defaultSetting,
dataview: dataViews
};
if (!dataViews
|| !dataViews[0]
|| !dataViews[0].categorical
|| !dataViews[0].categorical.categories
|| !dataViews[0].categorical.categories[0].source
|| !dataViews[0].categorical.values)
return viewModel;
let categorical=dataViews[0].categorical;
let category=categorical.categories[0];
let dataValue=categorical.values[0];
let pieChartData:Data[]=[];
let colorPalette:IColorPalette=host.colorPalette;
let objects=dataViews[0].metadata.objects
let pieChartSetting:pieChartSettings={
Legend:{
show: getValue<boolean>(objects,'Legend','show',defaultSetting.Legend.show)
}
}
for(let i=0;i<Math.max(category.values.length,dataValue.values.length);i++)
{
pieChartData.push({
quantity:<number>dataValue.values[i],
category:<string>category.values[i],
color:colorPalette.getColor(<string>category.values[i]).value,
selectionId:host.createSelectionIdBuilder()
.withCategory(category, i)
.createSelectionId()
});
console.log(pieChartData[i].color);
}
return {
datapoints:pieChartData,
setting:pieChartSetting,
dataview:dataViews
};
}
export class PieChart implements IVisual {
private target: HTMLElement;
private settings: VisualSettings;
private textNode: Text;
private pieChartContainer: d3.Selection<SVGElement>;
private arc: any;
private host: IVisualHost;
private selectionManager:ISelectionManager;
private svg: d3.Selection<SVGElement>;
private legend:d3.Selection<SVGElement>;
private g: any;
private pie: any;
private color: string;
private tooltipServiceWrapper: ITooltipServiceWrapper;
private pieSettings:pieChartSettings;
static data:DataView[];
static config=
{
solidOpacity:1,
transparentOpacity:0.5,
};
constructor(options: VisualConstructorOptions) {
console.log('Visual constructor', options);
this.target = options.element;
this.host=options.host;
this.selectionManager=options.host.createSelectionManager();
this.legend=d3.select(options.element);
let svg=this.svg=d3.select(options.element)
.append('svg')
.classed("pieChart",true)
;
this.pieChartContainer=svg.append('g').classed('pieChartContainer',true);//.attr('transform','translate('+100+',' +100+')');
this.tooltipServiceWrapper = createTooltipServiceWrapper(this.host.tooltipService, options.element);
}
public update(options: VisualUpdateOptions) {
// let legendModel : LegendValues[] = legendTransform(options,this.host);
let viewModel: PieChartArc = visualTransform(options, this.host);
let settings=this.pieSettings=viewModel.setting;
let category=options.dataViews[0].categorical.categories[0];
let dataValue=options.dataViews[0].categorical.values[0];
let legend=this.legend;
let legendEnumerate:LegendValues[];
// shows legend
if(settings.Legend.show)
{ //this.svg.append("text").text("Hello");
for(let i=0;i<category.values.length;++i)
{
legendEnumerate.push({
category:<string>category.values[i],
color:<string>dataValue.values[i],
selection:this.host.createSelectionIdBuilder()
.withCategory(category, i)
.createSelectionId()
});
}
let leg=this.legend.append('svg');
for(let i=0;i<Math.max(category.values.length,dataValue.values.length);++i)
{
// this.legend.html(legendEnumerate[i].category).attr("transform","translate(" + i*20 +",0)")
// leg.a
leg.append('circle')
.attr('cx',20)
.attr('cy',20)
.attr('r',8)
.attr('fill',legendEnumerate[i].color)
.attr("transform","translate(" + i*20 +",0)")
;
leg.append('text')
.text(legendEnumerate[i].category)
.attr("transform","translate(" + i*30 +",0)")
;
}
}
PieChart.data=options.dataViews;
let width=options.viewport.width;
let height=options.viewport.height;
let radius=Math.min(width,height)/2;
this.svg.attr({
width: width-20,
height: height-20,
});
this.arc=d3.svg.arc()
.innerRadius(0)
.outerRadius(radius-20);
this.pie = d3.layout.pie<Data>().value((d: Data):number => d.quantity).sort(null);
let fill = ((d):string=> d.data.color);
let tf = (d: Data) => `translate(${this.arc.centroid(d)})`;
let text = d => d.data.category;
this.svg.append('g');
this.g=this.svg.selectAll('.arc')
.data(this.pie(viewModel.datapoints))
.enter()
.append('g')
.attr('class', 'arc')
.data(this.pie(viewModel.datapoints))
// .attr("fill",fill)
;
let path= this.g.append('path')
.attr('d', this.arc)
.attr('fill',fill)
.attr('fill-opacity',1)
//.style("stroke","black")
.attr("stroke-width","0.8");
this.g.append('text').attr('transform', tf).text(text).attr('fill',"white");
this.tooltipServiceWrapper.addTooltip(path,
(tooltipEvent: TooltipEventArgs<number>) => PieChart.getTooltipData(tooltipEvent.data),
(tooltipEvent: TooltipEventArgs<number>) => null);
let selectionManager = this.selectionManager;
path.on("click",function(d)
{
// path.attr('fill','blue');
selectionManager.select(d.data.selectionId).then((ids: ISelectionId[])=>
{
path.attr('fill-opacity',ids.length>0? PieChart.config.transparentOpacity:PieChart.config.solidOpacity);
d3.select(this).attr('fill-opacity',PieChart.config.solidOpacity);
(<Event>d3.event).stopPropagation;
});
});
path.exit()
.remove();
}
private static parseSettings(dataView: DataView): VisualSettings {
return VisualSettings.parse(dataView) as VisualSettings;
}
/**
* This function gets called for each of the objects defined in the capabilities files and allows you to select which of the
* objects and properties you want to expose to the users in the property pane.
*
*/
public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstance[] | VisualObjectInstanceEnumerationObject {
// return VisualSettings.enumerateObjectInstances(this.settings || VisualSettings.getDefault(), options);
let objectName=options.objectName;
let objectEnumeration:VisualObjectInstance[]=[];
switch(objectName)
{
case 'Legend':
objectEnumeration.push({
objectName:objectName,
properties:{
show:this.pieSettings.Legend.show,
},
selector:null
});
};
return objectEnumeration;
}
private static getTooltipData(value: any): VisualTooltipDataItem[] {
return [{
displayName:PieChart.data[0].metadata.columns[1].displayName,
value: value.value.toString(),
color: value.data.color,
header:value.data.category
}];
}
}
}
here's my capabilities.json
{
"dataRoles": [
{
"displayName": "Category",
"name": "category",
"kind": "Grouping"
},
{
"displayName": "Measure",
"name": "measure",
"kind": "Measure"
}
],
"objects": {
"dataPoint": {
"displayName": "Data colors",
"properties": {
"defaultColor": {
"displayName": "Default color",
"type": {
"fill": {
"solid": {
"color": true
}
}
}
},
"showAllDataPoints": {
"displayName": "Show all",
"type": {
"bool": true
}
},
"fill": {
"displayName": "Fill",
"type": {
"fill": {
"solid": {
"color": true
}
}
}
},
"fillRule": {
"displayName": "Color saturation",
"type": {
"fill": {}
}
},
"fontSize": {
"displayName": "Text Size",
"type": {
"formatting": {
"fontSize": true
}
}
}
}
},
"Legend":{
"displayName": "Legend",
"properties": {
"show" :{
"displayName": "Legend",
"type": {
"bool": true
}
}
}
}
},
"dataViewMappings": [
{
"categorical": {
"categories": {
"for": {
"in": "category"
},
"dataReductionAlgorithm": {
"top": {}
}
},
"values": {
"select": [
{
"bind": {
"to": "measure"
}
}
]
}
},
"conditions":[
{ "category":{
"max":1
},
"measure":{
"max":1
}
}
]
}
]
}

d3 v4 how to limit left/right panning on an x zoom line-graph

I am trying to display data in a line graph within a 24 hr period.
I have created a d3 v4 line graph, and have successfully:
Applied an x Axis only zoom, and redraw of all elements
Used clippath to keep my data from showing left/below of my axis lines
My issue is now trying to apply translateExtent to my d3.zoom. It seems to keep me from panning left/right before zooming, but when I zoom, it seems to cut off or add on a half hour or so to the end and beginning of my data set.
I think all I need to do is maybe add some code to my d3.zoom declaration, and maybe also add something into my zoom function.
I have tried adding .translateExtent([[0,0],[w,h]]) to my d3.zoom code and so many other variations that included subtracting/adding my margins, etc.
It looks like adding the w"2*margin like below takes away the jumping on initial click. (which confuses me because I would assume the first coordinate group should affect the left panning of my graph) but once I zoom in, it keeps me from panning left beyond the beginning of the day (yay) but allows me to pan a little past the end of the day (boo).
var zoomCall = d3.zoom()
.scaleExtent([1, 24]) // no zooming out (1x), only zoom to 1hr (24x)
.translateExtent([[0,0],[w+2*margin,h]])
.on("zoom", zoom);
I am also thinking in my zoom function of multiplying my width extent by d3.event.transform.k which should be the zoom level i believe, but it is not giving me what I want either:
function zoom() {
zoomCall.translateExtent([[0,0],[w+margin*2*d3.event.transform.k, h]]);
There also sometimes is a translation of my data left or right 20px just when clicking on the graph once after the translateExtent code is added.
window.onload = function() {
// parse the date / time functions
var formatTime = d3.timeFormat("%H:%M"),
formatMinutes = function(d) {
return formatTime(new Date(2012, 0, 1, 0, d));
};
// Get and Prepare Data for gap_array and range_array
var count_data = [
{
"date_time":"\/Date(1494864780000)\/",
"count":14
},
{
"date_time":"\/Date(1494864780000)\/",
"count":11
},
{
"date_time":"\/Date(1494864780000)\/",
"count":25
},
{
"date_time":"\/Date(1494864840000)\/",
"count":31
},
{
"date_time":"\/Date(1494864840000)\/",
"count":53
},
{
"date_time":"\/Date(1494864840000)\/",
"count":56
},
{
"date_time":"\/Date(1494864900000)\/",
"count":57
},
{
"date_time":"\/Date(1494864960000)\/",
"count":68
},
{
"date_time":"\/Date(1494865020000)\/",
"count":69
},
{
"date_time":"\/Date(1494865020000)\/",
"count":70
},
{
"date_time":"\/Date(1494865140000)\/",
"count":65
},
{
"date_time":"\/Date(1494865200000)\/",
"count":68
},
{
"date_time":"\/Date(1494865320000)\/",
"count":68
},
{
"date_time":"\/Date(1494865380000)\/",
"count":68
},
{
"date_time":"\/Date(1494865500000)\/",
"count":70
},
{
"date_time":"\/Date(1494865560000)\/",
"count":67
},
{
"date_time":"\/Date(1494865680000)\/",
"count":61
},
{
"date_time":"\/Date(1494865740000)\/",
"count":61
},
{
"date_time":"\/Date(1494865860000)\/",
"count":67
},
{
"date_time":"\/Date(1494865920000)\/",
"count":67
},
{
"date_time":"\/Date(1494866040000)\/",
"count":67
},
{
"date_time":"\/Date(1494866100000)\/",
"count":67
},
{
"date_time":"\/Date(1494866220000)\/",
"count":68
},
{
"date_time":"\/Date(1494866280000)\/",
"count":66
},
{
"date_time":"\/Date(1494866400000)\/",
"count":67
},
{
"date_time":"\/Date(1494866460000)\/",
"count":67
},
{
"date_time":"\/Date(1494866580000)\/",
"count":68
},
{
"date_time":"\/Date(1494866640000)\/",
"count":66
},
{
"date_time":"\/Date(1494866760000)\/",
"count":67
},
{
"date_time":"\/Date(1494866820000)\/",
"count":67
},
{
"date_time":"\/Date(1494866940000)\/",
"count":67
},
{
"date_time":"\/Date(1494867000000)\/",
"count":67
},
{
"date_time":"\/Date(1494867120000)\/",
"count":53
},
{
"date_time":"\/Date(1494867180000)\/",
"count":66
},
{
"date_time":"\/Date(1494867300000)\/",
"count":72
},
{
"date_time":"\/Date(1494867360000)\/",
"count":67
},
{
"date_time":"\/Date(1494867480000)\/",
"count":69
},
{
"date_time":"\/Date(1494867540000)\/",
"count":70
},
{
"date_time":"\/Date(1494867660000)\/",
"count":61
},
{
"date_time":"\/Date(1494867720000)\/",
"count":28
},
{
"date_time":"\/Date(1494867720000)\/",
"count":10
},
{
"date_time":"\/Date(1494867840000)\/",
"count":60
},
{
"date_time":"\/Date(1494867900000)\/",
"count":60
},
{
"date_time":"\/Date(1494868020000)\/",
"count":50
},
{
"date_time":"\/Date(1494868020000)\/",
"count":42
},
{
"date_time":"\/Date(1494868140000)\/",
"count":63
},
{
"date_time":"\/Date(1494868200000)\/",
"count":63
},
{
"date_time":"\/Date(1494868320000)\/",
"count":63
},
{
"date_time":"\/Date(1494868380000)\/",
"count":61
},
{
"date_time":"\/Date(1494868500000)\/",
"count":63
},
{
"date_time":"\/Date(1494868560000)\/",
"count":44
},
{
"date_time":"\/Date(1494868560000)\/",
"count":14
},
{
"date_time":"\/Date(1494868680000)\/",
"count":35
},
{
"date_time":"\/Date(1494868740000)\/",
"count":73
},
{
"date_time":"\/Date(1494868860000)\/",
"count":63
},
{
"date_time":"\/Date(1494868920000)\/",
"count":63
},
{
"date_time":"\/Date(1494869040000)\/",
"count":58
},
{
"date_time":"\/Date(1494869100000)\/",
"count":63
},
{
"date_time":"\/Date(1494869220000)\/",
"count":63
},
{
"date_time":"\/Date(1494869280000)\/",
"count":62
},
{
"date_time":"\/Date(1494869400000)\/",
"count":62
},
{
"date_time":"\/Date(1494869460000)\/",
"count":63
},
{
"date_time":"\/Date(1494869580000)\/",
"count":63
},
{
"date_time":"\/Date(1494869640000)\/",
"count":55
},
{
"date_time":"\/Date(1494869700000)\/",
"count":63
},
{
"date_time":"\/Date(1494869820000)\/",
"count":63
},
{
"date_time":"\/Date(1494869880000)\/",
"count":58
},
{
"date_time":"\/Date(1494869880000)\/",
"count":58
},
{
"date_time":"\/Date(1494869880000)\/",
"count":58
},
{
"date_time":"\/Date(1494870000000)\/",
"count":35
},
{
"date_time":"\/Date(1494870060000)\/",
"count":43
},
{
"date_time":"\/Date(1494870120000)\/",
"count":53
},
{
"date_time":"\/Date(1494870180000)\/",
"count":0
},
{
"date_time":"\/Date(1494870180000)\/",
"count":6
},
{
"date_time":"\/Date(1494870180000)\/",
"count":8
},
{
"date_time":"\/Date(1494870240000)\/",
"count":0
},
{
"date_time":"\/Date(1494870240000)\/",
"count":4
},
{
"date_time":"\/Date(1494870240000)\/",
"count":0
},
{
"date_time":"\/Date(1494870240000)\/",
"count":6
},
{
"date_time":"\/Date(1494870300000)\/",
"count":0
},
{
"date_time":"\/Date(1494870300000)\/",
"count":6
},
{
"date_time":"\/Date(1494870300000)\/",
"count":15
},
{
"date_time":"\/Date(1494870300000)\/",
"count":14
},
{
"date_time":"\/Date(1494870300000)\/",
"count":22
},
{
"date_time":"\/Date(1494870360000)\/",
"count":27
},
{
"date_time":"\/Date(1494870420000)\/",
"count":63
},
{
"date_time":"\/Date(1494870540000)\/",
"count":63
},
{
"date_time":"\/Date(1494870600000)\/",
"count":67
},
{
"date_time":"\/Date(1494870720000)\/",
"count":63
},
{
"date_time":"\/Date(1494870780000)\/",
"count":63
},
{
"date_time":"\/Date(1494870900000)\/",
"count":54
},
{
"date_time":"\/Date(1494870900000)\/",
"count":0
},
{
"date_time":"\/Date(1494870900000)\/",
"count":6
},
{
"date_time":"\/Date(1494870960000)\/",
"count":15
},
{
"date_time":"\/Date(1494871020000)\/",
"count":13
},
{
"date_time":"\/Date(1494871020000)\/",
"count":0
},
{
"date_time":"\/Date(1494871080000)\/",
"count":0
},
{
"date_time":"\/Date(1494871200000)\/",
"count":0
},
{
"date_time":"\/Date(1494871260000)\/",
"count":0
},
{
"date_time":"\/Date(1494871380000)\/",
"count":0
},
{
"date_time":"\/Date(1494871440000)\/",
"count":0
},
{
"date_time":"\/Date(1494871560000)\/",
"count":0
},
{
"date_time":"\/Date(1494871620000)\/",
"count":0
},
{
"date_time":"\/Date(1494888600000)\/",
"count":6
},
{
"date_time":"\/Date(1494888600000)\/",
"count":6
},
{
"date_time":"\/Date(1494888720000)\/",
"count":0
},
{
"date_time":"\/Date(1494888780000)\/",
"count":0
},
{
"date_time":"\/Date(1494888900000)\/",
"count":0
},
{
"date_time":"\/Date(1494888960000)\/",
"count":0
},
{
"date_time":"\/Date(1494889080000)\/",
"count":0
},
{
"date_time":"\/Date(1494889140000)\/",
"count":0
},
{
"date_time":"\/Date(1494889260000)\/",
"count":0
},
{
"date_time":"\/Date(1494889320000)\/",
"count":0
},
{
"date_time":"\/Date(1494889380000)\/",
"count":4
},
{
"date_time":"\/Date(1494889380000)\/",
"count":4
},
{
"date_time":"\/Date(1494889380000)\/",
"count":0
},
{
"date_time":"\/Date(1494889380000)\/",
"count":5
},
{
"date_time":"\/Date(1494889380000)\/",
"count":0
},
{
"date_time":"\/Date(1494889500000)\/",
"count":0
},
{
"date_time":"\/Date(1494889560000)\/",
"count":0
},
{
"date_time":"\/Date(1494889680000)\/",
"count":0
},
{
"date_time":"\/Date(1494889740000)\/",
"count":4
},
{
"date_time":"\/Date(1494889740000)\/",
"count":0
},
{
"date_time":"\/Date(1494889860000)\/",
"count":0
},
{
"date_time":"\/Date(1494889920000)\/",
"count":0
},
{
"date_time":"\/Date(1494889920000)\/",
"count":4
},
{
"date_time":"\/Date(1494889980000)\/",
"count":0
},
{
"date_time":"\/Date(1494889980000)\/",
"count":0
},
{
"date_time":"\/Date(1494890220000)\/",
"count":5
},
{
"date_time":"\/Date(1494890220000)\/",
"count":5
},
{
"date_time":"\/Date(1494890280000)\/",
"count":6
},
{
"date_time":"\/Date(1494890340000)\/",
"count":0
},
{
"date_time":"\/Date(1494890400000)\/",
"count":0
},
{
"date_time":"\/Date(1494890520000)\/",
"count":0
},
{
"date_time":"\/Date(1494890580000)\/",
"count":0
},
{
"date_time":"\/Date(1494890700000)\/",
"count":0
},
{
"date_time":"\/Date(1494890760000)\/",
"count":0
},
{
"date_time":"\/Date(1494890880000)\/",
"count":0
},
];
count_data.forEach(function(d) {
d.date_time = new Date(parseInt(d.date_time.replace(/\/Date\((-?\d+)\)\//gi, "$1")));
//d.date_time = formatTime(d.date_time);
});
var maxY = d3.max(count_data, function(d) {
return d.count;
});
var minY = 0;
var minX = new Date(count_data[0].date_time).setHours(0, 0, 0, 0);
var maxX = new Date(count_data[0].date_time).setHours(23, 59, 59, 999);
var gap_array = [];
var range_array = [];
var range_start = moment(new Date(firstDateTime)),
range_end,
range_start_position = 0,
range_end_position,
in_range = true;
var gap_start,
gap_end,
gap_start_position,
gap_end_position,
in_gap = false,
gap_min = 2;
var firstDateTime = count_data[0].date_time;
var lastDateTime = count_data[count_data.length - 1].date_time;
var date_previous = moment(new Date(firstDateTime));
for (i = 0; i < count_data.length; i++) {
var current = moment(new Date(count_data[i].date_time));
if (current.diff(date_previous, "m") > gap_min && !in_gap) {
range_end = date_previous;
range_end_position = i - 1;
in_range = !in_range;
range_array.push({
start: range_start.toDate(),
end: range_end.toDate(),
start_position: range_start_position,
end_position: range_end_position
});
gap_start = date_previous;
gap_start_position = i;
in_gap = !in_gap;
} else if (current.diff(date_previous, "m") <= gap_min && in_gap) {
range_start_position = i;
range_start = current;
in_range = !in_range;
gap_end_position = i;
gap_end = current;
in_gap = !in_gap;
gap_array.push({
start: gap_start.toDate(),
end: gap_end.toDate(),
start_position: gap_start_position,
end_position: gap_end_position
});
} else if (i == count_data.length - 1) {
if (in_gap) {
gap_end_position = i;
gap_end = current;
in_gap = !in_gap;
gap_array.push({
start: gap_start.toDate(),
end: gap_end.toDate(),
start_position: gap_start_position,
end_position: gap_end_position
});
} else {
range_end = current;
range_end_position = i;
in_range = !in_range;
range_array.push({
start: range_start.toDate(),
end: range_end.toDate(),
start_position: range_start_position,
end_position: range_end_position
});
}
}
date_previous = current;
}
gap_array.push({
start: minX,
end: firstDateTime,
start_position: null,
end_position: 0
}); // push initial gap
gap_array.push({
start: lastDateTime,
end: maxX,
start_position: count_data.length - 1,
end_position: null
}); // push final gap
var count_data_array = [];
for (i = 0; i < range_array.length; i++) {
count_data_array.push(count_data.slice(range_array[i].start_position, range_array[i].end_position + (range_array[i].end_position < count_data.length - 1 ? 1 : 0)));
}
//
var margin = 40;
var w = document.getElementById("d3-chart").offsetWidth - margin - margin,
h = 250 - margin - margin;
var x = d3.scaleTime().range([0, w]).domain([minX, maxX]);
var y = d3.scaleLinear().range([h, 0]).domain([minY, maxY]);
var zoomCall = d3.zoom()
.scaleExtent([1, 24]) // no zooming out (1x), only zoom to 1hr (24x)
.on("zoom", zoom);
var container = d3.select("#d3-chart");
var svg = container.append("svg")
.attr("width", w + margin + margin)
.attr("height", h + margin + margin);
var g = svg.append("g")
.attr("transform",
"translate(" + margin + "," + margin + ")")
.call(zoomCall);
g.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", w)
.attr("height", h);
var xAxis = d3.axisBottom(x).ticks(20); //.tickFormat(formatMinutes);
var yAxis = d3.axisLeft(y);
function zoom() {
// re-scale y axis during zoom;
xAxisCall.transition()
.duration(50)
.call(xAxis.scale(d3.event.transform.rescaleX(x)));
// re-draw circles using new y-axis scale;
var new_xScale = d3.event.transform.rescaleX(x);
var new_valueline = d3.line()
.x(function(d) {
return new_xScale(d.date_time);
})
.y(function(d) {
return y(d.count);
});
gaps.attr("x", d => new_xScale(d.start)).attr("width", d => new_xScale(d.end) - new_xScale(d.start)).attr("clip-path", "url(#clip)");
for (i = 0; i < paths.length; i++) {
paths[i]
.attr("d", new_valueline).attr("clip-path", "url(#clip)");
}
}
var gaps = g.selectAll('.gap')
.data(gap_array)
.enter().append('rect')
.attr("class", "gap")
.attr("x", d => x(d.start))
.attr("y", 0)
.attr("width", d => x(d.end) - x(d.start))
.attr("height", h)
.attr("fill", "#efefef");
var xAxisCall = g.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + h + ")")
.call(xAxis);
var yAxisCall = g.append("g")
.attr("class", "axis")
.call(yAxis);
// define the line
var valueline = d3.line()
.x(function(d) {
return x(d.date_time);
})
.y(function(d) {
return y(d.count);
});
var paths = [];
// Add the valueline path.
for (i = 0; i < count_data_array.length; i++) {
paths.push(
g.append("path")
.data([count_data_array[i]])
.attr("class", "line")
.attr("d", valueline)
);
}
g.append("rect")
.attr("class", "overlay")
.attr("width", w)
.attr("height", h)
};
#d3-chart {
position: relative;
}
.axis {
font: 14px sans-serif;
}
.line {
fill: none;
stroke: #3988ff;
stroke-width: 2px;
}
.overlay {
fill: none;
pointer-events: all;;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.js"></script>
<h3>D3 Test</h3>
<div id="d3-chart"></div>
Not sure logically why, but the margin offset needs to be divided by the zoom factor.
function zoom() {
var zoomFactor = (d3.event != null ? d3.event.transform.k : 1);
zoomCall.translateExtent([[0,0],[w+((2*margin)/zoomFactor), h]]);

Using multiple values for a Crossfilter dimension

I am working with JSON like the following:
[
{
"source": "Google",
"date": "2014-02-01",
"spend": 21,
"clicks": 1000
},
{
"source": "Bing",
"date": "2014-02-01",
"spend": 5,
"clicks": 541
},
{
"source": "Google",
"date": "2014-02-02",
"spend": 24,
"clicks": 1029
},
{
"source": "Bing",
"date": "2014-02-02",
"spend": 12,
"clicks": 754
}
]
And want to feed it into Crossfilter to create a line chart with NVD3. I don't know where to start, but I want the line chart to use the following:
X Axis - Date
Y Axis - Clicks
1 line per source
This is what I've been able to build without Crossfilter:
(function () {
var ymdFormat = d3.time.format('%Y-%m-%d');
d3.json('./data.json', function (err, json) {
nv.addGraph(function () {
var chart = nv.models.lineChart()
chart.margin({ left: 100 })
.useInteractiveGuideline(true)
.transitionDuration(350)
.showLegend(true)
.showYAxis(true).showXAxis(true);
chart.xAxis
.axisLabel('Date')
.tickFormat(function (d) {
return d3.time.format('%b %Y')(new Date(d));
});
chart.yAxis
.axisLabel('Clicks')
.tickFormat(d3.format(','));
data = parseData(json);
d3.select('#graph').append('svg')
.datum(data).call(chart);
});
})
function parseData(json) {
var data, result, key;
data = {};
json.forEach(function (elmt) {
if (!(elmt.source in data)) {
data[elmt.source] = { values: [] }
}
data[elmt.source].values.push({ x: ymdFormat.parse(elmt.date), y: elmt.clicks })
});
result = [];
for (key in data) {
if (data.hasOwnProperty(key)) {
result.push({
key: key,
values: data[key].values
});
}
}
console.log(result);
return result;
}
})()
I have this problem. I have a solution for this, not very nice, however.
var filterByMonthSource = filter.dimension(function(d) { return d.date + ':' + d.source });
var clicksGroup = filterByMonth.group().reduceSum(function(d) { return d.clicks });
var clicksData = clicksGroup.all();
clicksData will have [{key: "2014-02-01:Google", value: ...}, ...]
I then have to break clicksData into array of 3 fields.

Resources