Fixing the axis-scale range that is presented - d3.js

I have an value that is the count of total minutes that I am presenting within my time series. While the minutes are used for plotting, I would like to change the axis tick labels to present the hours that this data fits closest to. The way I approached this was to add a .tickFormat() that converts the minutes to hours and then return d3.timeFormat() with the hour format and a new date set to 0 that is set with the hours. While the axis tick labels are close, they aren't correct. There seems to be a slight offset, duplication of values and the scale not starting at 0 (Starts at 12). Should I use a different function call to correct the scale?.
This is the code in question:
svg.append("g")
.call(d3.axisLeft()
.scale(y)
.tickFormat((d, i) => {
var hours = Math.floor(d / 60);
console.log(hours)
console.log(new Date(0).setMinutes(hours))
return d3.timeFormat("%I")( new Date(0).setHours(hours))
}));
<meta charset="utf-8">
<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>
<style>
div.tooltip {
position: absolute;
text-align: center;
width: 100px;
height: 30px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
</style>
<script>
var data = [
{ "x": "2020-04-26", "y": 461.0, "label": "7:41" },
{ "x": "2020-04-27", "y": 421.0, "label": "7:01" },
{ "x": "2020-04-28", "y": 519.0, "label": "8:39" },
{ "x": "2020-04-29", "y": 502.0, "label": "8:22" },
{ "x": "2020-04-30", "y": 511.0, "label": "8:31" },
{ "x": "2020-05-01", "y": 513.0, "label": "8:33" },
{ "x": "2020-05-02", "y": 496.0, "label": "8:16" },
{ "x": "2020-05-03", "y": 480.0, "label": "8:00" },
{ "x": "2020-05-04", "y": 364.0, "label": "6:04" },
{ "x": "2020-05-05", "y": 498.0, "label": "8:18" },
{ "x": "2020-05-06", "y": 467.0, "label": "7:47" },
{ "x": "2020-05-07", "y": 477.0, "label": "7:57" },
{ "x": "2020-05-08", "y": 431.0, "label": "7:11" },
{ "x": "2020-05-09", "y": 419.0, "label": "6:59" },
{ "x": "2020-05-10", "y": 471.0, "label": "7:51" },
{ "x": "2020-05-11", "y": 391.0, "label": "6:31" },
{ "x": "2020-05-12", "y": 481.0, "label": "8:01" },
{ "x": "2020-05-13", "y": 494.0, "label": "8:14" },
{ "x": "2020-05-14", "y": 506.0, "label": "8:26" },
{ "x": "2020-05-15", "y": 464.0, "label": "7:44" },
{ "x": "2020-05-16", "y": 474.0, "label": "7:54" },
{ "x": "2020-05-17", "y": 383.0, "label": "6:23" },
{ "x": "2020-05-18", "y": 385.0, "label": "6:25" },
{ "x": "2020-05-19", "y": 470.0, "label": "7:50" },
{ "x": "2020-05-20", "y": 465.0, "label": "7:45" },
{ "x": "2020-05-21", "y": 574.0, "label": "9:34" },
{ "x": "2020-05-22", "y": 473.0, "label": "7:53" },
{ "x": "2020-05-23", "y": 431.0, "label": "7:11" },
{ "x": "2020-05-24", "y": 497.0, "label": "8:17" },
{ "x": "2020-05-26", "y": 482.0, "label": "8:02" },
{ "x": "2020-05-27", "y": 492.0, "label": "8:12" },
{ "x": "2020-05-28", "y": 494.0, "label": "8:14" },
{ "x": "2020-05-29", "y": 469.0, "label": "7:49" },
{ "x": "2020-05-30", "y": 395.0, "label": "6:35" },
{ "x": "2020-05-31", "y": 427.0, "label": "7:07" },
{ "x": "2020-06-01", "y": 346.0, "label": "5:46" },
{ "x": "2020-06-02", "y": 416.0, "label": "6:56" },
{ "x": "2020-06-03", "y": 461.0, "label": "7:41" },
{ "x": "2020-06-04", "y": 486.0, "label": "8:06" },
{ "x": "2020-06-05", "y": 451.0, "label": "7:31" },
{ "x": "2020-06-06", "y": 533.0, "label": "8:53" },
{ "x": "2020-06-08", "y": 462.0, "label": "7:42" },
{ "x": "2020-06-09", "y": 461.0, "label": "7:41" },
{ "x": "2020-06-10", "y": 477.0, "label": "7:57" },
{ "x": "2020-06-11", "y": 458.0, "label": "7:38" },
{ "x": "2020-06-12", "y": 484.0, "label": "8:04" },
{ "x": "2020-06-13", "y": 389.0, "label": "6:29" },
{ "x": "2020-06-15", "y": 472.0, "label": "7:52" },
{ "x": "2020-06-16", "y": 462.0, "label": "7:42" },
{ "x": "2020-06-17", "y": 486.0, "label": "8:06" },
{ "x": "2020-06-18", "y": 489.0, "label": "8:09" },
{ "x": "2020-06-19", "y": 483.0, "label": "8:03" },
{ "x": "2020-06-20", "y": 426.0, "label": "7:06" },
{ "x": "2020-06-21", "y": 453.0, "label": "7:33" },
{ "x": "2020-06-22", "y": 489.0, "label": "8:09" },
{ "x": "2020-06-23", "y": 467.0, "label": "7:47" },
{ "x": "2020-06-24", "y": 474.0, "label": "7:54" },
{ "x": "2020-06-25", "y": 451.0, "label": "7:31" },
{ "x": "2020-06-26", "y": 450.0, "label": "7:30" },
{ "x": "2020-06-27", "y": 470.0, "label": "7:50" },
{ "x": "2020-06-29", "y": 247.0, "label": "4:07" },
{ "x": "2020-06-30", "y": 502.0, "label": "8:22" },
{ "x": "2020-07-01", "y": 464.0, "label": "7:44" }
]
// D3 date parser
for (var i=0; i < data.length; i++){
var parser = d3.timeParse("%Y-%m-%d")
data[i].date = parser(data[i].x);
}
var margin = { top: 10, right: 30, bottom: 30, left: 60 }
var width = 800 - margin.left - margin.right;
var height = 800 - margin.top - margin.bottom;
// Define the div for the tooltip
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var svg = d3.select("#my_dataviz")
.append("svg")
.attr( 'preserveAspectRatio',"xMinYMin meet")
.attr("viewBox", "0 0 " + (width + margin.left + margin.right) + " " + (height + margin.top + margin.bottom))
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // translate(margin left, margin top)
var x = d3.scaleTime()
.domain([d3.min(data, function(d) { return d.date }), d3.max(data, function(d) { return d.date })])
.range([0, width]);
svg.append("g")
.attr("transform", "translate(" + 0 + "," + height + ")")
.call(d3.axisBottom(x));
// text label for the x axis
svg.append("text")
.attr("transform",
"translate(" + (width/2) + " ," + (height + margin.top + 20) + ")")
.style("text-anchor", "middle")
.text("Date");
var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d){ return +d.y })])
.range([height, 0]);
svg.append("g")
.call(d3.axisLeft()
.scale(y)
.tickFormat((d, i) => {
var hours = Math.floor(d / 60);
console.log(hours)
console.log(new Date(0).setMinutes(hours))
return d3.timeFormat("%I")( new Date(0).setHours(hours))
}));
// text label for the y axis
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x",0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Time Asleep (Minutes)");
// Add line path
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 1.5)
.attr("d", d3.line()
.x(function(d) { return x(d.date) })
.y(function(d) { return y(d.y) })
);
// Add the scatterplot (data points)
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 3)
// Add tooltip on hover
.on("mouseover", function(d) {
div.transition()
.duration(200)
.style("opacity", .9);
div.html(d.x + "<br/>" + d.label)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 30) + "px")
})
// Remove tooltip after hover
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
})
.transition()
.delay(function(d,i){ return (i*3)})
.duration(2000)
.attr("cx", function(d){ return x(d.date) })
.attr("cy", function(d){ return y(d.y) });
</script>

While your data is a time, it's not a date. Forcing it to be a date will give you many nasty complications. I just surpassed the d3 and Date logic, leading to a simpler solution:
var data = [{
"x": "2020-04-26",
"y": 461.0,
"label": "7:41"
},
{
"x": "2020-04-27",
"y": 421.0,
"label": "7:01"
},
{
"x": "2020-04-28",
"y": 519.0,
"label": "8:39"
},
{
"x": "2020-04-29",
"y": 502.0,
"label": "8:22"
},
{
"x": "2020-04-30",
"y": 511.0,
"label": "8:31"
},
{
"x": "2020-05-01",
"y": 513.0,
"label": "8:33"
},
{
"x": "2020-05-02",
"y": 496.0,
"label": "8:16"
},
{
"x": "2020-05-03",
"y": 480.0,
"label": "8:00"
},
{
"x": "2020-05-04",
"y": 364.0,
"label": "6:04"
},
{
"x": "2020-05-05",
"y": 498.0,
"label": "8:18"
},
{
"x": "2020-05-06",
"y": 467.0,
"label": "7:47"
},
{
"x": "2020-05-07",
"y": 477.0,
"label": "7:57"
},
{
"x": "2020-05-08",
"y": 431.0,
"label": "7:11"
},
{
"x": "2020-05-09",
"y": 419.0,
"label": "6:59"
},
{
"x": "2020-05-10",
"y": 471.0,
"label": "7:51"
},
{
"x": "2020-05-11",
"y": 391.0,
"label": "6:31"
},
{
"x": "2020-05-12",
"y": 481.0,
"label": "8:01"
},
{
"x": "2020-05-13",
"y": 494.0,
"label": "8:14"
},
{
"x": "2020-05-14",
"y": 506.0,
"label": "8:26"
},
{
"x": "2020-05-15",
"y": 464.0,
"label": "7:44"
},
{
"x": "2020-05-16",
"y": 474.0,
"label": "7:54"
},
{
"x": "2020-05-17",
"y": 383.0,
"label": "6:23"
},
{
"x": "2020-05-18",
"y": 385.0,
"label": "6:25"
},
{
"x": "2020-05-19",
"y": 470.0,
"label": "7:50"
},
{
"x": "2020-05-20",
"y": 465.0,
"label": "7:45"
},
{
"x": "2020-05-21",
"y": 574.0,
"label": "9:34"
},
{
"x": "2020-05-22",
"y": 473.0,
"label": "7:53"
},
{
"x": "2020-05-23",
"y": 431.0,
"label": "7:11"
},
{
"x": "2020-05-24",
"y": 497.0,
"label": "8:17"
},
{
"x": "2020-05-26",
"y": 482.0,
"label": "8:02"
},
{
"x": "2020-05-27",
"y": 492.0,
"label": "8:12"
},
{
"x": "2020-05-28",
"y": 494.0,
"label": "8:14"
},
{
"x": "2020-05-29",
"y": 469.0,
"label": "7:49"
},
{
"x": "2020-05-30",
"y": 395.0,
"label": "6:35"
},
{
"x": "2020-05-31",
"y": 427.0,
"label": "7:07"
},
{
"x": "2020-06-01",
"y": 346.0,
"label": "5:46"
},
{
"x": "2020-06-02",
"y": 416.0,
"label": "6:56"
},
{
"x": "2020-06-03",
"y": 461.0,
"label": "7:41"
},
{
"x": "2020-06-04",
"y": 486.0,
"label": "8:06"
},
{
"x": "2020-06-05",
"y": 451.0,
"label": "7:31"
},
{
"x": "2020-06-06",
"y": 533.0,
"label": "8:53"
},
{
"x": "2020-06-08",
"y": 462.0,
"label": "7:42"
},
{
"x": "2020-06-09",
"y": 461.0,
"label": "7:41"
},
{
"x": "2020-06-10",
"y": 477.0,
"label": "7:57"
},
{
"x": "2020-06-11",
"y": 458.0,
"label": "7:38"
},
{
"x": "2020-06-12",
"y": 484.0,
"label": "8:04"
},
{
"x": "2020-06-13",
"y": 389.0,
"label": "6:29"
},
{
"x": "2020-06-15",
"y": 472.0,
"label": "7:52"
},
{
"x": "2020-06-16",
"y": 462.0,
"label": "7:42"
},
{
"x": "2020-06-17",
"y": 486.0,
"label": "8:06"
},
{
"x": "2020-06-18",
"y": 489.0,
"label": "8:09"
},
{
"x": "2020-06-19",
"y": 483.0,
"label": "8:03"
},
{
"x": "2020-06-20",
"y": 426.0,
"label": "7:06"
},
{
"x": "2020-06-21",
"y": 453.0,
"label": "7:33"
},
{
"x": "2020-06-22",
"y": 489.0,
"label": "8:09"
},
{
"x": "2020-06-23",
"y": 467.0,
"label": "7:47"
},
{
"x": "2020-06-24",
"y": 474.0,
"label": "7:54"
},
{
"x": "2020-06-25",
"y": 451.0,
"label": "7:31"
},
{
"x": "2020-06-26",
"y": 450.0,
"label": "7:30"
},
{
"x": "2020-06-27",
"y": 470.0,
"label": "7:50"
},
{
"x": "2020-06-29",
"y": 247.0,
"label": "4:07"
},
{
"x": "2020-06-30",
"y": 502.0,
"label": "8:22"
},
{
"x": "2020-07-01",
"y": 464.0,
"label": "7:44"
}
]
// D3 date parser
for (var i = 0; i < data.length; i++) {
var parser = d3.timeParse("%Y-%m-%d")
data[i].date = parser(data[i].x);
}
var margin = {
top: 10,
right: 30,
bottom: 30,
left: 60
}
var width = 800 - margin.left - margin.right;
var height = 800 - margin.top - margin.bottom;
// Define the div for the tooltip
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var svg = d3.select("#my_dataviz")
.append("svg")
.attr('preserveAspectRatio', "xMinYMin meet")
.attr("viewBox", "0 0 " + (width + margin.left + margin.right) + " " + (height + margin.top + margin.bottom))
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // translate(margin left, margin top)
var x = d3.scaleTime()
.domain([d3.min(data, function(d) {
return d.date
}), d3.max(data, function(d) {
return d.date
})])
.range([0, width]);
svg.append("g")
.attr("transform", "translate(" + 0 + "," + height + ")")
.call(d3.axisBottom(x));
// text label for the x axis
svg.append("text")
.attr("transform",
"translate(" + (width / 2) + " ," + (height + margin.top + 20) + ")")
.style("text-anchor", "middle")
.text("Date");
var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return +d.y
})])
.range([height, 0]);
svg.append("g")
.call(d3.axisLeft()
.scale(y)
.tickFormat((d, i) => {
var hours = Math.floor(d / 60);
var minutes = d - hours * 60;
return hours.toString().padStart(2, 0) + ":" + minutes.toString().padStart(2, 0).padStart(2, 0);
}));
// text label for the y axis
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x", 0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Time Asleep (Minutes)");
// Add line path
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 1.5)
.attr("d", d3.line()
.x(function(d) {
return x(d.date)
})
.y(function(d) {
return y(d.y)
})
);
// Add the scatterplot (data points)
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 3)
// Add tooltip on hover
.on("mouseover", function(d) {
div.transition()
.duration(200)
.style("opacity", .9);
div.html(d.x + "<br/>" + d.label)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 30) + "px")
})
// Remove tooltip after hover
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
})
.transition()
.delay(function(d, i) {
return (i * 3)
})
.duration(2000)
.attr("cx", function(d) {
return x(d.date)
})
.attr("cy", function(d) {
return y(d.y)
});
div.tooltip {
position: absolute;
text-align: center;
width: 100px;
height: 30px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
<meta charset="utf-8">
<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>

Related

SVG viewBox Attribute Makes D3Js Line chart disappear

I am trying to make my d3.js scatter plot/line graph visualization responsive and have followed information that has mentioned the only way to scale an svg with your window is by using the viewBox attribute, but it appears when I switch out the with and height attributes in my svg to the viewBox attribute the chart disappears without any error. Is there something that I am doing wrong with applying this attribute to my chart?
Attribute switched from:
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
To this:
.attr( 'preserveAspectRatio',"xMinYMin meet")
.attr("viewBox", "0 0 " + width + margin.left + margin.right + " " + height + margin.top + margin.bottom)
Here is the visualization with the new change:
<meta charset="utf-8">
<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>
<script>
var data = [
{ "x": "2020-04-26", "y": 461.0, "label": "7:41" },
{ "x": "2020-04-27", "y": 421.0, "label": "7:01" },
{ "x": "2020-04-28", "y": 519.0, "label": "8:39" },
{ "x": "2020-04-29", "y": 502.0, "label": "8:22" },
{ "x": "2020-04-30", "y": 511.0, "label": "8:31" },
{ "x": "2020-05-01", "y": 513.0, "label": "8:33" },
{ "x": "2020-05-02", "y": 496.0, "label": "8:16" },
{ "x": "2020-05-03", "y": 480.0, "label": "8:00" },
{ "x": "2020-05-04", "y": 364.0, "label": "6:04" },
{ "x": "2020-05-05", "y": 498.0, "label": "8:18" },
{ "x": "2020-05-06", "y": 467.0, "label": "7:47" },
{ "x": "2020-05-07", "y": 477.0, "label": "7:57" },
{ "x": "2020-05-08", "y": 431.0, "label": "7:11" },
{ "x": "2020-05-09", "y": 419.0, "label": "6:59" },
{ "x": "2020-05-10", "y": 471.0, "label": "7:51" },
{ "x": "2020-05-11", "y": 391.0, "label": "6:31" },
{ "x": "2020-05-12", "y": 481.0, "label": "8:01" },
{ "x": "2020-05-13", "y": 494.0, "label": "8:14" },
{ "x": "2020-05-14", "y": 506.0, "label": "8:26" },
{ "x": "2020-05-15", "y": 464.0, "label": "7:44" },
{ "x": "2020-05-16", "y": 474.0, "label": "7:54" },
{ "x": "2020-05-17", "y": 383.0, "label": "6:23" },
{ "x": "2020-05-18", "y": 385.0, "label": "6:25" },
{ "x": "2020-05-19", "y": 470.0, "label": "7:50" },
{ "x": "2020-05-20", "y": 465.0, "label": "7:45" },
{ "x": "2020-05-21", "y": 574.0, "label": "9:34" },
{ "x": "2020-05-22", "y": 473.0, "label": "7:53" },
{ "x": "2020-05-23", "y": 431.0, "label": "7:11" },
{ "x": "2020-05-24", "y": 497.0, "label": "8:17" },
{ "x": "2020-05-26", "y": 482.0, "label": "8:02" },
{ "x": "2020-05-27", "y": 492.0, "label": "8:12" },
{ "x": "2020-05-28", "y": 494.0, "label": "8:14" },
{ "x": "2020-05-29", "y": 469.0, "label": "7:49" },
{ "x": "2020-05-30", "y": 395.0, "label": "6:35" },
{ "x": "2020-05-31", "y": 427.0, "label": "7:07" },
{ "x": "2020-06-01", "y": 346.0, "label": "5:46" },
{ "x": "2020-06-02", "y": 416.0, "label": "6:56" },
{ "x": "2020-06-03", "y": 461.0, "label": "7:41" },
{ "x": "2020-06-04", "y": 486.0, "label": "8:06" },
{ "x": "2020-06-05", "y": 451.0, "label": "7:31" },
{ "x": "2020-06-06", "y": 533.0, "label": "8:53" },
{ "x": "2020-06-08", "y": 462.0, "label": "7:42" },
{ "x": "2020-06-09", "y": 461.0, "label": "7:41" }
]
// D3 date parser
for (var i=0; i < data.length; i++){
var parser = d3.timeParse("%Y-%m-%d")
data[i].date = parser(data[i].x);
}
console.log(data)
var margin = { top: 10, right: 30, bottom: 30, left: 60 }
var width = 800 - margin.left - margin.right;
var height = 800 - margin.top - margin.bottom;
// Define the div for the tooltip
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var svg = d3.select("#my_dataviz")
.append("svg")
// .attr("width", width + margin.left + margin.right)
// .attr("height", height + margin.top + margin.bottom)
.attr( 'preserveAspectRatio',"xMinYMin meet")
.attr("viewBox", "0 0 " + width + margin.left + margin.right + " " + height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // translate(margin left, margin top)
var x = d3.scaleTime()
.domain([d3.min(data, function(d) { return d.date }), d3.max(data, function(d) { return d.date })])
.range([0, width]);
svg.append("g")
.attr("transform", "translate(" + 0 + "," + height + ")")
.call(d3.axisBottom(x));
// text label for the x axis
svg.append("text")
.attr("transform",
"translate(" + (width/2) + " ," + (height + margin.top + 20) + ")")
.style("text-anchor", "middle")
.text("Date");
var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d){ return +d.y })])
.range([height, 0]);
svg.append("g")
.call(d3.axisLeft(y));
// text label for the y axis
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x",0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Time Asleep (Minutes)");
// Add line path
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 1.5)
.attr("d", d3.line()
.x(function(d) { return x(d.date) })
.y(function(d) { return y(d.y) })
);
// Add the scatterplot (data points)
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 3)
.attr("cx", function(d){ return x(d.date) })
.attr("cy", function(d){ return y(d.y) })
</script>
Here is the chart with the height and width attribute:
<meta charset="utf-8">
<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>
<script>
var data = [
{ "x": "2020-04-26", "y": 461.0, "label": "7:41" },
{ "x": "2020-04-27", "y": 421.0, "label": "7:01" },
{ "x": "2020-04-28", "y": 519.0, "label": "8:39" },
{ "x": "2020-04-29", "y": 502.0, "label": "8:22" },
{ "x": "2020-04-30", "y": 511.0, "label": "8:31" },
{ "x": "2020-05-01", "y": 513.0, "label": "8:33" },
{ "x": "2020-05-02", "y": 496.0, "label": "8:16" },
{ "x": "2020-05-03", "y": 480.0, "label": "8:00" },
{ "x": "2020-05-04", "y": 364.0, "label": "6:04" },
{ "x": "2020-05-05", "y": 498.0, "label": "8:18" },
{ "x": "2020-05-06", "y": 467.0, "label": "7:47" },
{ "x": "2020-05-07", "y": 477.0, "label": "7:57" },
{ "x": "2020-05-08", "y": 431.0, "label": "7:11" },
{ "x": "2020-05-09", "y": 419.0, "label": "6:59" },
{ "x": "2020-05-10", "y": 471.0, "label": "7:51" },
{ "x": "2020-05-11", "y": 391.0, "label": "6:31" },
{ "x": "2020-05-12", "y": 481.0, "label": "8:01" },
{ "x": "2020-05-13", "y": 494.0, "label": "8:14" },
{ "x": "2020-05-14", "y": 506.0, "label": "8:26" },
{ "x": "2020-05-15", "y": 464.0, "label": "7:44" },
{ "x": "2020-05-16", "y": 474.0, "label": "7:54" },
{ "x": "2020-05-17", "y": 383.0, "label": "6:23" },
{ "x": "2020-05-18", "y": 385.0, "label": "6:25" },
{ "x": "2020-05-19", "y": 470.0, "label": "7:50" },
{ "x": "2020-05-20", "y": 465.0, "label": "7:45" },
{ "x": "2020-05-21", "y": 574.0, "label": "9:34" },
{ "x": "2020-05-22", "y": 473.0, "label": "7:53" },
{ "x": "2020-05-23", "y": 431.0, "label": "7:11" },
{ "x": "2020-05-24", "y": 497.0, "label": "8:17" },
{ "x": "2020-05-26", "y": 482.0, "label": "8:02" },
{ "x": "2020-05-27", "y": 492.0, "label": "8:12" },
{ "x": "2020-05-28", "y": 494.0, "label": "8:14" },
{ "x": "2020-05-29", "y": 469.0, "label": "7:49" },
{ "x": "2020-05-30", "y": 395.0, "label": "6:35" },
{ "x": "2020-05-31", "y": 427.0, "label": "7:07" },
{ "x": "2020-06-01", "y": 346.0, "label": "5:46" },
{ "x": "2020-06-02", "y": 416.0, "label": "6:56" },
{ "x": "2020-06-03", "y": 461.0, "label": "7:41" },
{ "x": "2020-06-04", "y": 486.0, "label": "8:06" },
{ "x": "2020-06-05", "y": 451.0, "label": "7:31" },
{ "x": "2020-06-06", "y": 533.0, "label": "8:53" },
{ "x": "2020-06-08", "y": 462.0, "label": "7:42" },
{ "x": "2020-06-09", "y": 461.0, "label": "7:41" }
]
// D3 date parser
for (var i=0; i < data.length; i++){
var parser = d3.timeParse("%Y-%m-%d")
data[i].date = parser(data[i].x);
}
console.log(data)
var margin = { top: 10, right: 30, bottom: 30, left: 60 }
var width = 800 - margin.left - margin.right;
var height = 800 - margin.top - margin.bottom;
// Define the div for the tooltip
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var svg = d3.select("#my_dataviz")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
// .attr( 'preserveAspectRatio',"xMinYMin meet")
// .attr("viewBox", "0 0 " + width + margin.left + margin.right + " " + height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // translate(margin left, margin top)
var x = d3.scaleTime()
.domain([d3.min(data, function(d) { return d.date }), d3.max(data, function(d) { return d.date })])
.range([0, width]);
svg.append("g")
.attr("transform", "translate(" + 0 + "," + height + ")")
.call(d3.axisBottom(x));
// text label for the x axis
svg.append("text")
.attr("transform",
"translate(" + (width/2) + " ," + (height + margin.top + 20) + ")")
.style("text-anchor", "middle")
.text("Date");
var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d){ return +d.y })])
.range([height, 0]);
svg.append("g")
.call(d3.axisLeft(y));
// text label for the y axis
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x",0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Time Asleep (Minutes)");
// Add line path
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 1.5)
.attr("d", d3.line()
.x(function(d) { return x(d.date) })
.y(function(d) { return y(d.y) })
);
// Add the scatterplot (data points)
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 3)
.attr("cx", function(d){ return x(d.date) })
.attr("cy", function(d){ return y(d.y) })
</script>
This is not adding, it's coercing the numbers to strings then concatenating:
.attr("viewBox", "0 0 " + width + margin.left + margin.right + " " + height + margin.top + margin.bottom)
This will add, then coerce and concatenate:
.attr("viewBox", "0 0 " + (width + margin.left + margin.right) + " " + (height + margin.top + margin.bottom))

Generated drawing gives unexpected output

I'm trying to generate a drawing based on mouse events and I'm noticing some interesting rendering behavior that I can't explain why it's happening that way. Here's a jsbin that shows this example: https://jsbin.com/qiqetoy/edit?html,output
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/konva#4.2.0/konva.min.js"></script>
<meta charset="utf-8" />
<title>Konva Free Drawing Demo</title>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #f0f0f0;
}
</style>
</head>
<body>
Tool:
<select id="tool">
<option value="brush">Brush</option>
<option value="eraser">Eraser</option>
</select>
<div id="container"></div>
<script>
var width = window.innerWidth;
var height = window.innerHeight - 25;
// first we need Konva core things: stage and layer
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height
});
var layer = new Konva.Layer();
stage.add(layer);
var isPaint = false;
var mode = 'brush';
var lastLine;
stage.on('mousedown touchstart', function(e) {
isPaint = true;
var pos = e.pos;
lastLine = new Konva.Line({
stroke: '#df4b26',
strokeWidth: 5,
globalCompositeOperation:
mode === 'brush' ? 'source-over' : 'destination-out',
points: [pos.x, pos.y]
});
layer.add(lastLine);
});
stage.on('mouseup touchend', function() {
isPaint = false;
});
// and core function - drawing
stage.on('mousemove touchmove', function(e) {
if (!isPaint) {
return;
}
const pos = e.pos;
var newPoints = lastLine.points().concat([pos.x, pos.y]);
lastLine.points(newPoints);
layer.batchDraw();
});
var select = document.getElementById('tool');
select.addEventListener('change', function() {
mode = select.value;
});
const line = [{
"et": "md",
"x": 109,
"y": 94
}, {
"et": "mm",
"x": 110,
"y": 98
}, {
"et": "mm",
"x": 110,
"y": 103
}, {
"et": "mm",
"x": 110,
"y": 111
}, {
"et": "mm",
"x": 110,
"y": 116
}, {
"et": "mm",
"x": 110,
"y": 123
}, {
"et": "mm",
"x": 110,
"y": 129
}, {
"et": "mm",
"x": 110,
"y": 135
}, {
"et": "mm",
"x": 110,
"y": 141
}, {
"et": "mm",
"x": 110,
"y": 143
}, {
"et": "mm",
"x": 110,
"y": 147
}, {
"et": "mm",
"x": 110,
"y": 150
}, {
"et": "mm",
"x": 111,
"y": 152
}, {
"et": "mm",
"x": 114,
"y": 155
}, {
"et": "mm",
"x": 112,
"y": 154
}, {
"et": "mm",
"x": 117,
"y": 155
}, {
"et": "mm",
"x": 120,
"y": 155
}, {
"et": "mm",
"x": 123,
"y": 154
}, {
"et": "mm",
"x": 127,
"y": 151
}, {
"et": "mm",
"x": 131,
"y": 148
}, {
"et": "mm",
"x": 135,
"y": 145
}, {
"et": "mm",
"x": 139,
"y": 140
}, {
"et": "mm",
"x": 142,
"y": 137
}, {
"et": "mu"
}, ];
line.forEach(point => {
if (point.et === 'mm') {
stage.fire('mousemove', {
pos: {
x: point.x,
y: point.y
}
});
} else if (point.et == 'md') {
stage.fire('mousedown', {
pos: {
x: point.x,
y: point.y
}
});
} else if (point.et === 'mu') {
stage.fire('mouseup', {
pos: {
x: point.x,
y: point.y
}
});
}
});
</script>
</body>
</html>
Here's the interesting part of that drawing:
You can see above that there're a couple of sharp edges/lines that're drawn at the curve. I can't explain how this is happening. You can also clearly see that it's not 5px wide (the stroke width is set at 5px).
Can someone who's got more experience with canvas/konvajs drawing help explain what's happening here and what should I do to get rid of this behavior?
Thanks,
K
I think I figured out what the issue here is. The data seems to have an issue. Here's the JSBin that isolates the data in question. https://jsbin.com/nayado/edit?html,output
{
"et": "md",
"x": 110,
"y": 147
}, {
"et": "mm",
"x": 110,
"y": 150
}, {
"et": "mm",
"x": 111,
"y": 152
}, {
"et": "mm",
"x": 114,
"y": 155
}, {
"et": "mm",
"x": 112,
"y": 154
}, {
"et": "mm",
"x": 117,
"y": 155
}, {
"et": "mu"
},
The data seems to be out of order which is probably what's causing the issue. I need to now figure out how's the canvas generating touch events that seem to be out of order.

Multichart krispo showing curved lines instead of straight lines

In my angular application I have used Krispo Multichart graph. Where I am getting some weird graph points.
See below screen shot:
UPDATE
Screen shot 1 :
Screen shot 2:
Screen shot 3:
In above screen shots, the data are coming in every minutes (i;e expected). Data seems correct.
Here is my Options:
$scope.options_line = {
chart: {
type: 'multiChart',
yDomain1: [0, 250],
yDomain2: [0, 0],
height: 260,
width: 550,
margin: {
top: 10,
right: 50,
bottom: 50,
left: 60
},
x: function (d) {
return d.x;
},
y: function (d) {
return d.y;
},
text: function (d) {
return d.x;
},
color: d3.scale.category10().range(),
showValues: true,
valueFormat: function (d) {
return d3.format('f')(d);
},
duration: 500,
xAxis: {
axisLabel: 'Time',
tickFormat: function (d) {
return d3.time.format('%H:%M')(new Date(d));
}
},
yAxis1: {
axisLabelDistance: 0,
axisLabel: 'Voltage [ V ]',
tickFormat: function (d) {
return d3.format('f')(d);
}
},
yAxis2: {
axisLabelDistance: 0,
axisLabel: 'Current [ A ]',
tickFormat: function (d) {
return d3.format('f')(d);
},
width: 50,
},
interactive: true,
tooltip: {
contentGenerator: function (e) {
//return html content
//console.log(e);
//console.log($scope.tooltip_format);
var data = e;
console.log(data.point.y);
var series = e.series[0];
if($scope.set_offset_val) { $scope.xtime = data.point.x - $scope.set_offset_val} else {
$scope.xtime = data.point.x;
}
return '<h3>' + series.key + '</h3>' +
'<p>' + parseFloat(data.point.y).toFixed(2) + ' at ' + $filter('date')($scope.xtime, $scope.tooltip_format) + '</p>'
}
}
}
};
And JSON data:
[{
"yAxis": 1,
"values": [{
"x": "1487939640000",
"y": "150"
}, {
"x": "1487939700000",
"y": "150"
}, {
"x": "1487939760000",
"y": "150"
}, {
"x": "1487939820000",
"y": "151"
}, {
"x": "1487939880000",
"y": "151"
}, {
"x": "1487939940000",
"y": "151"
}, {
"x": "1487940000000",
"y": "151"
}, {
"x": "1487940060000",
"y": "151"
}, {
"x": "1487940660000",
"y": "168"
}, {
"x": "1487940720000",
"y": "169"
}, {
"x": "1487940840000",
"y": "165"
}, {
"x": "1487942100000",
"y": "165"
}, {
"x": "1487942160000",
"y": "165"
}, {
"x": "1487942220000",
"y": "154"
}, {
"x": "1487942280000",
"y": "165"
}, {
"x": "1487942340000",
"y": "165"
}, {
"x": "1487942400000",
"y": "165"
}, {
"x": "1487942460000",
"y": "165"
}, {
"x": "1487942520000",
"y": "165"
}, {
"x": "1487942580000",
"y": "165"
}, {
"x": "1487942640000",
"y": "165"
}, {
"x": "1487942700000",
"y": "165"
}],
"type": "line",
"key": "PVVoltage"
}, {
"yAxis": 2,
"values": [{
"x": "1487939640000",
"y": "4"
}, {
"x": "1487939700000",
"y": "4"
}, {
"x": "1487939760000",
"y": "2.3"
}, {
"x": "1487939820000",
"y": "2.1"
}, {
"x": "1487939880000",
"y": "1.6"
}, {
"x": "1487939940000",
"y": "1"
}, {
"x": "1487940000000",
"y": "1.5"
}, {
"x": "1487940060000",
"y": "0.1"
}, {
"x": "1487940660000",
"y": "3.5"
}, {
"x": "1487940720000",
"y": "0.1"
}, {
"x": "1487940840000",
"y": "0.5"
}, {
"x": "1487942100000",
"y": "2"
}, {
"x": "1487942160000",
"y": "0.2"
}, {
"x": "1487942220000",
"y": "3.2"
}, {
"x": "1487942280000",
"y": "0"
}, {
"x": "1487942340000",
"y": "0"
}, {
"x": "1487942400000",
"y": "0"
}, {
"x": "1487942460000",
"y": "0"
}, {
"x": "1487942520000",
"y": "0.1"
}, {
"x": "1487942580000",
"y": "0.1"
}, {
"x": "1487942640000",
"y": "0"
}, {
"x": "1487942700000",
"y": "0"
}],
"type": "line",
"key": "PVCurrent"
}]
Expected graph should not have the curve in it as this is a line graph. I my case point has went right and again left and then up.
Anyone have any idea why this is happening? and how can I fix this.

Combine force directed graph with donut chart D3JS

i want to combine two charts together.
First force directed graph with donut chart. Every node in force directed graph after clik will show context menu by donut chart. I prepared two charts, but I do not know how to combine them.
Code for force directed:
// Graph 2 - context menu donut chart
var dataset = [
{
size: 2,
label: "Item 1"
},
{
size: 1,
label: "Item 2"
},
{
size: 65,
label: "Item 3"
},
{
size: 45,
label: "Item 4"
},
{
size: 50,
label: "Item 5"
}
];
var width = 460,
height = 300,
radius = Math.min(width, height) / 2;
var color = d3.scale.category20();
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return Object.keys(dataset).length; }); // zde je nutné zadat celkovou populaci - početz prvků v
// Menu
// Arc setting
var arc = d3.svg.arc()
.innerRadius(radius - 100)
.outerRadius(radius - 50);
// Graph space
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
// Prepare graph and load data
var g = svg.selectAll(".arc")
.data(pie(dataset))
.enter().append("g")
.attr("class", "arc");
// Add colors
var path = g.append("path")
.attr("d", arc)
.attr("fill", function (d) { return color(d.data.size);})
// Add labels
var asdfd = g.append("text")
.attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; })
.attr("dy", ".35em")
.style("text-anchor", "middle")
.text(function(d) { return d.data.label; });
var oldColor;
// Add hover action
path.on("mouseenter", function(d,i) {
console.log("mousein"+ d.data.label)
var thisPath = d3.select(this);
oldColor = thisPath.attr("fill"); // save old color
thisPath
.attr("fill", "blue")
.attr("cursor", "pointer")
.attr("class", "on");
})
path.on("mouseout", function(d) {
d3.select(this)
.attr("fill", oldColor)
.attr("class", "off");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
Result of combination should be like on this picture:
Thank you for yor ideas!
EDIT: I maybe solve this, buth there is some small performace problem, can anyone help me how to finish this, graph is lagging, and I have problem with arrow between nodes. Thnaks for help !
var json = {
"nodes": [{
"id": -1146034065,
"name": "/",
"group": 0
}, {
"id": -990073683,
"name": "/blog/",
"group": 0
}, {
"id": -1724280020,
"name": "/menu/",
"group": 0
}, {
"id": 1176095248,
"name": "/napojovy-listek/",
"group": 0
}, {
"id": -2085082741,
"name": "/fotogalerie/",
"group": 0
}, {
"id": 883542796,
"name": "/rezervace/",
"group": 0
}, {
"id": 369131020,
"name": "/kontakt/",
"group": 0
}, {
"id": -1276353015,
"name": "/en/",
"group": 0
}, {
"id": -1557747058,
"name": "/o-nas/",
"group": 404
}, {
"id": 890427810,
"name": "/en/about-us/",
"group": 0
}, {
"id": -978700858,
"name": "/en/menu-2/",
"group": 0
}, {
"id": 1436673749,
"name": "/en/napojovy-listek/",
"group": 0
}, {
"id": -489730654,
"name": "/en/photograph/",
"group": 0
}, {
"id": -1461616187,
"name": "/en/reservation/",
"group": 0
}, {
"id": 1520755615,
"name": "/en/contact/",
"group": 0
}, {
"id": 37644686,
"name": "/en//kontakt/",
"group": 0
}, {
"id": 1131720527,
"name": "/en//o-nas/",
"group": 404
}],
"links": [{
"source": -990073683,
"target": -1146034065,
"value": 1
}, {
"source": -1724280020,
"target": -1146034065,
"value": 1
}, {
"source": 1176095248,
"target": -1146034065,
"value": 1
}, {
"source": -2085082741,
"target": -1146034065,
"value": 1
}, {
"source": 883542796,
"target": -1146034065,
"value": 1
}, {
"source": 369131020,
"target": -1146034065,
"value": 1
}, {
"source": -1276353015,
"target": -1146034065,
"value": 1
}, {
"source": -1557747058,
"target": -1146034065,
"value": 1
}, {
"source": 890427810,
"target": -990073683,
"value": 1
}, {
"source": -978700858,
"target": -1724280020,
"value": 1
}, {
"source": 1436673749,
"target": 1176095248,
"value": 1
}, {
"source": -489730654,
"target": -2085082741,
"value": 1
}, {
"source": -1461616187,
"target": 883542796,
"value": 1
}, {
"source": 1520755615,
"target": 369131020,
"value": 1
}, {
"source": 37644686,
"target": -1276353015,
"value": 1
}, {
"source": 1131720527,
"target": -1276353015,
"value": 1
}, {
"source": -1146034065,
"target": -1146034065,
"count": 1,
"value": 1
}, {
"source": -1146034065,
"target": -990073683,
"count": 1,
"value": 1
}, {
"source": -1146034065,
"target": -1724280020,
"count": 3,
"value": 1
}, {
"source": -1146034065,
"target": 1176095248,
"count": 3,
"value": 1
}, {
"source": -1146034065,
"target": -2085082741,
"count": 3,
"value": 1
}, {
"source": -1146034065,
"target": 883542796,
"count": 3,
"value": 1
}, {
"source": -1146034065,
"target": 369131020,
"count": 3,
"value": 1
}, {
"source": -1146034065,
"target": -1276353015,
"count": 1,
"value": 1
}, {
"source": -1146034065,
"target": -1557747058,
"count": 2,
"value": 1
}, {
"source": -990073683,
"target": -1146034065,
"count": 1,
"value": 1
}, {
"source": -990073683,
"target": -990073683,
"count": 1,
"value": 1
}, {
"source": -990073683,
"target": -1724280020,
"count": 1,
"value": 1
}, {
"source": -990073683,
"target": 1176095248,
"count": 1,
"value": 1
}, {
"source": -990073683,
"target": -2085082741,
"count": 1,
"value": 1
}, {
"source": -990073683,
"target": 883542796,
"count": 1,
"value": 1
}, {
"source": -990073683,
"target": 369131020,
"count": 1,
"value": 1
}, {
"source": -990073683,
"target": 890427810,
"count": 1,
"value": 1
}, {
"source": -1724280020,
"target": -1146034065,
"count": 1,
"value": 1
}, {
"source": -1724280020,
"target": -990073683,
"count": 1,
"value": 1
}, {
"source": -1724280020,
"target": -1724280020,
"count": 1,
"value": 1
}, {
"source": -1724280020,
"target": 1176095248,
"count": 1,
"value": 1
}, {
"source": -1724280020,
"target": -2085082741,
"count": 1,
"value": 1
}, {
"source": -1724280020,
"target": 883542796,
"count": 1,
"value": 1
}, {
"source": -1724280020,
"target": 369131020,
"count": 1,
"value": 1
}, {
"source": -1724280020,
"target": -978700858,
"count": 1,
"value": 1
}, {
"source": 1176095248,
"target": -1146034065,
"count": 1,
"value": 1
}, {
"source": 1176095248,
"target": -990073683,
"count": 1,
"value": 1
}, {
"source": 1176095248,
"target": -1724280020,
"count": 1,
"value": 1
}, {
"source": 1176095248,
"target": 1176095248,
"count": 1,
"value": 1
}, {
"source": 1176095248,
"target": -2085082741,
"count": 1,
"value": 1
}, {
"source": 1176095248,
"target": 883542796,
"count": 1,
"value": 1
}, {
"source": 1176095248,
"target": 369131020,
"count": 1,
"value": 1
}, {
"source": 1176095248,
"target": 1436673749,
"count": 1,
"value": 1
}, {
"source": -2085082741,
"target": -1146034065,
"count": 1,
"value": 1
}, {
"source": -2085082741,
"target": -990073683,
"count": 1,
"value": 1
}, {
"source": -2085082741,
"target": -1724280020,
"count": 1,
"value": 1
}, {
"source": -2085082741,
"target": 1176095248,
"count": 1,
"value": 1
}, {
"source": -2085082741,
"target": -2085082741,
"count": 1,
"value": 1
}, {
"source": -2085082741,
"target": 883542796,
"count": 1,
"value": 1
}, {
"source": -2085082741,
"target": 369131020,
"count": 1,
"value": 1
}, {
"source": -2085082741,
"target": -489730654,
"count": 1,
"value": 1
}, {
"source": 883542796,
"target": -1146034065,
"count": 1,
"value": 1
}, {
"source": 883542796,
"target": -990073683,
"count": 1,
"value": 1
}, {
"source": 883542796,
"target": -1724280020,
"count": 1,
"value": 1
}, {
"source": 883542796,
"target": 1176095248,
"count": 1,
"value": 1
}, {
"source": 883542796,
"target": -2085082741,
"count": 1,
"value": 1
}, {
"source": 883542796,
"target": 883542796,
"count": 1,
"value": 1
}, {
"source": 883542796,
"target": 369131020,
"count": 1,
"value": 1
}, {
"source": 883542796,
"target": -1461616187,
"count": 1,
"value": 1
}, {
"source": 369131020,
"target": -1146034065,
"count": 1,
"value": 1
}, {
"source": 369131020,
"target": -990073683,
"count": 1,
"value": 1
}, {
"source": 369131020,
"target": -1724280020,
"count": 1,
"value": 1
}, {
"source": 369131020,
"target": 1176095248,
"count": 1,
"value": 1
}, {
"source": 369131020,
"target": -2085082741,
"count": 1,
"value": 1
}
]
}
var width = 960,
height = 700
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
// Per-type markers, as they don't inherit styles.
svg.append("defs").selectAll("marker")
.data(["a"])
.enter().append("marker")
.attr("id", function(d) { return d; })
.attr("viewBox", "0 -5 10 10")
.attr("refX", 15)
.attr("refY", -1.5)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "auto")
.append("path")
.attr("d", "M0,-5L10,0L0,5");
var edges = [];
var fill = d3.scale.category10();
json.links.forEach(function (e) {
// Get the source and target nodes
var sourceNode = json.nodes.filter(function (n) {
return n.id === e.source;
})[0],
targetNode = json.nodes.filter(function (n) {
return n.id === e.target;
})[0],
count = e.count;
// Add the edge to the array
edges.push({
source: sourceNode,
target: targetNode,
count: count,
type: "a"
});
});
var force = d3.layout.force()
.gravity(0.01)
.distance(500)
.charge(-300)
.linkDistance(300)
.size([width, height])
.nodes(json.nodes)
.links(edges)
.start();
var link = svg.append("g").selectAll("link")
.data(edges)
.enter().append("path")
.attr("class", "link")
//.attr("marker-end", function(d) { return "url(#" + d.targetNode + ")"; })
.style("stroke-width", function (d) {
return Math.sqrt(d.count * 1, 5);
});
// Přidáme k uzlu kontextové menu a zvýrazníme sousedy
var node = svg.selectAll("node")
.data(json.nodes)
.enter().append("g")
.attr("class", "node")
.style("fill", function (d) {
return fill(d.group);
})
.call(force.drag).on("mouseover", fade(.1)).on("mouseout", fade(1))
.on("click", function (d, i) {
svg.selectAll(".node").style("fill", function (d) { return fill(d.group);});
d3.select(".menu").remove();
var thisNode = d3.select(this);
thisNode.attr('r', 25).style("fill", "lightcoral");
var menuDataSet = [{
size: 2,
label: "Item 1"
}, {
size: 1,
label: "Item 2"
}, {
size: 65,
label: "Item 3"
}, {
size: 45,
label: "Item 4"
}, {
size: 50,
label: "Item 5"
}];
// Barvy menu
var color = d3.scale.category20();
var pie = d3.layout.pie()
.sort(null)
.value(function (d) {
return Object.keys(menuDataSet).length;
}); // zde je nutné zadat celkovou populaci - početz prvků v
// Menu
var widthMenu = 180,
heightMenu = 180,
radiusMenu = Math.min(widthMenu, heightMenu) / 2;
// Arc setting
var arc = d3.svg.arc()
.innerRadius(radiusMenu - 70)
.outerRadius(radiusMenu - 25);
// Graph space
var svgMenu = thisNode.append("svg")
.attr("width", widthMenu)
.attr("height", heightMenu)
.attr("class","menu")
.attr("x", -90)
.attr("y", -90)
.append("g")
.attr("transform", "translate(" + widthMenu / 2 + "," + heightMenu / 2 + ")");
// Prepare graph and load data
var g = svgMenu.selectAll(".arc")
.data(pie(menuDataSet))
.enter().append("g")
.attr("class", "arc");
// Add colors
var path = g.append("path")
.attr("d", arc)
.attr("fill", function (d) {
return color(d.data.size);
})
// Add labels
var asdfd = g.append("text")
.attr("transform", function (d) {
return "translate(" + arc.centroid(d) + ")";
})
.attr("dy", ".35em")
.style("text-anchor", "middle")
.text(function (d) {
return d.data.label;
});
// Add hover action
path.on("mouseenter", function (d, i) {
var thisPath = d3.select(this);
thisPath.attr("fill", "blue")
.attr("cursor", "pointer")
.attr("class", "on");
})
path.on("mouseout", function (d) {
d3.select(this)
.attr("fill", function (d) {
return color(d.data.size);
})
.attr("class", "off");
});
});
/*
node.append("image")
.attr("xlink:href", "https://github.com/favicon.ico")
.attr("x", -8)
.attr("y", -8)
.attr("width", 16)
.attr("height", 16);
*/
node.append("circle").attr("r", 10);
node.append("text")
.attr("dx", 12)
.attr("dy", ".35em")
.text(function (d) {
return d.name
});
// přidá popisky k hranám
var labels = svg.selectAll('text')
.data(edges)
.enter().append('text')
.attr("x", function (d) {
return (d.source.y + d.target.y) / 2;
})
.attr("y", function (d) {
return (d.source.x + d.target.x) / 2;
})
.attr("text-anchor", "middle")
.text(function (d) {
return d.count;
});
force.on("tick", function () {
link.attr("d", function linkArc(d) {
var dx = d.target.x - d.source.x,
dy = d.target.y - d.source.y,
dr = Math.sqrt(dx * dx + dy * dy);
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
}
);
node.attr("transform", function (d) {
return "translate(" + d.x + "," + d.y + ")";
});
labels.attr("x", function (d) {
return (d.source.x + d.target.x + 10) / 2;
})
.attr("y", function (d) {
return (d.source.y + d.target.y + 10) / 2;
})
});
function transform(d) {
return "translate(" + d.x + "," + d.y + ")";
}
var linkedByIndex = {};
edges.forEach(function (d) {
linkedByIndex[d.source.index + "," + d.target.index] = 1;
});
function isConnected(a, b) {
return linkedByIndex[a.index + "," + b.index] || linkedByIndex[b.index + "," + a.index] || a.index == b.index;
}
function fade(opacity) {
return function (d) {
// přidá popisky k hranám
var labels = svg.selectAll('text')
.data(edges)
.enter().append('text')
.attr("x", function (o) {
return (o.source.y + o.target.y) / 2;
})
.attr("y", function (o) {
return (o.source.x + o.target.x) / 2;
})
.attr("text-anchor", "middle")
.text(function (o) {
return o.count;
});
node.style("stroke-opacity", function (o) {
thisOpacity = isConnected(d, o) ? 1 : opacity;
this.setAttribute('fill-opacity', thisOpacity);
return thisOpacity;
});
link.style("stroke-opacity", function (o) {
return o.source === d || o.target === d ? 1 : opacity;
});
};
}
body {
font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;
margin: auto;
position: relative;
width: 960px;
}
.link {
fill: none;
stroke: #666;
stroke-width: 1.5px;
stroke-dasharray: 0,4 1;
}
text {
font: 10px sans-serif;
}
form {
position: absolute;
right: 10px;
top: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

nvd3 multibarchart xAxis sorted by key

I can't set a NVD3 multibarchart able to sort the bars by dates in the xAxis.
I'm aware the input data must be grouped by key before displaying it into a multibarchart.
Here a jsfiddle illustrating what I'm talking about: http://jsfiddle.net/fontanon/z4aZ4/54/
As you can see in the data variable, I've added three groups of bars (key1, key2 and key3). Each group has the x values sorted ascendently. The first bar of key2 should be the first (as for having the minimum x value), then the first bar of key1 followed by the second bar of key2, etc. But this is not how the bars are being displayed.
What is exactly happening?
Below the data.
var data = [
{
"key": "Key1",
"values": [
{
"x": 2393337532000,
"y": 1401431
},
{
"x": 4394337660000,
"y": 26188
},
{
"x": 7395510769000,
"y": 865575
},
]
},
{
"key": "Key2",
"values": [
{
"x": 1396337532000,
"y": 1401431
},
{
"x": 3397337660000,
"y": 26188
},
{
"x": 6398510769000,
"y": 865575
}
]
},
{
"key": "Key3",
"values": [
{
"x": 5399337532000,
"y": 1401431
},
{
"x": 8400337660000,
"y": 26188
},
{
"x": 9401510769000,
"y": 865575
}
]
}
]
Your data should be look like this
var data = [
{
"key": "Key1",
"values": [
{
"x": 7393337532000,
"y": 1401431
},
{
"x": 8394337660000,
"y": 26188
},
{
"x": 3398510769000,
"y": 865575
}
]
},
{
"key": "Key2",
"values": [
{
"x": 7393337532000,
"y": 1401431
},
{
"x": 8394337660000,
"y": 26188
},
{
"x": 3398510769000,
"y": 865575
}
]
},
{
"key": "Key3",
"values": [
{
"x": 7393337532000,
"y": 1401431
},
{
"x": 8394337660000,
"y": 26188
},
{
"x": 3398510769000,
"y": 865575
}
]
}
]

Resources