SVG viewBox Attribute Makes D3Js Line chart disappear - d3.js

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))

Related

d3.js - force layout not show nodes and links

Below example converted from this v3 version, it try to use force layout to draw some nodes and links, but it can not show the nodes or links!
console.log("--------")
console.clear();
var w = 600,
h = 600,
nodeCircles,
linkLines,
root;
var force = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) { return d.id; }))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(w / 2, h / 2))
.on('tick',tick)
var zoomer = d3.zoom()
.scaleExtent([0.9,3])
.on("zoom", zoom);
function zoom(event) {
vis.attr("transform",
"translate(" + event.translate + ")"
+ " scale(" + event.scale + ")" );
}
var graph = d3.select("body").append("svg:svg")
.attr("width", w)
.attr("height", h)
.append("g")
.attr("class", "graph")
.call(zoomer);
var rect = graph.append("rect")
.attr("width", w)
.attr("height", h)
.attr('fill','none')
.attr('stroke','black')
.style("pointer-events", "all");
var vis = graph.append("svg:g")
.attr("class", "plotting-area");
function update() {
var nodes = d3.hierarchy(root)
const links = d3.tree()
.size([h, w])(nodes)
.links();
nodes = flatten(root)
force
.nodes(nodes)
.on("tick", tick);
force.force("link")
.links(links);
// Update the links…
linkLines = vis.selectAll("line.link")
.data(links, function (d) {
return d.target.index;
});
linkLines.enter().insert("svg:line", ".node")
.attr("class", "link")
.attr('stroke','black')
linkLines.exit().remove();
nodeCircles = vis.selectAll("circle.node")
.data(nodes, function (d) {
return d.id;
})
.attr("fill", color)
.attr('stroke','black')
nodeCircles.enter().append("svg:circle")
.attr("class", "node")
.attr("r", function (d) {
return d.children ? 4.5 : Math.sqrt(d.size) / 10;
})
.style("fill", color);
nodeCircles.exit().remove();
}
function color(d) {
return d.children ? "#c6dbef" : d.group;
}
function tick() {
linkLines.attr("x1", function (d) {
return d.source.x;
})
.attr("y1", function (d) {
return d.source.y;
})
.attr("x2", function (d) {
return d.target.x;
})
.attr("y2", function (d) {
return d.target.y;
});
nodeCircles.attr("cx", function (d) {
return d.x;
})
.attr("cy", function (d) {
return d.y;
});
}
function readfile(json) {
root = json;
root.fixed = true;
root.x = w / 2;
root.y = h/2;
update();
};
function flatten(root) {
var nodes = [],
i = 0;
function recurse(node) {
if (node.children) node.size = node.children.reduce(function (p, v) {
return p + recurse(v);
}, 0);
if (!node.id) node.id = ++i;
nodes.push(node);
return node.size;
}
root.size = recurse(root);
return nodes;
}
var data = {
"dist": 0.00193506541936,
"name": "N3",
"children": [ {
"dist": 0.00488832259274,
"name": "N4",
"children": [ {
"dist": 0.00421186204991,
"name": "N5",
"children": [ {
"dist": 0.0163437491651,
"name": "N6",
"children": [{
"dist": 0.417946674158,
"group": "blue",
"name": "CHEMBL1644419",
"size": 2000.0000000000866
}, {
"dist": 0.00543077796308,
"name": "N8",
"children": [{
"dist": 0.0297671023157,
"name": "N9",
"children": [{
"dist": 0.359033872667,
"group": "red",
"name": "ASD03540222",
"size": 2000.0000000000866
}, {
"dist": 0.362485114675,
"group": "red",
"name": "ASD01150858",
"size": 2000.0000000000866
}]
},{
"dist": 0.0224504491652,
"name": "N12",
"children": [{
"dist": 0.00178517153851,
"name": "N13",
"children": [{
"dist": 0.364388220986,
"group": "blue",
"name": "CHEMBL197161",
"size": 2000.0000000000866
}, {
"dist": 0.0425243314393,
"name": "N15",
"children": [{
"dist": 0.336193167816,
"group": "blue",
"name": "CHEMBL1644268",
"size": 2000.0000000000866
}, {
"dist": 0.325677335782,
"group": "red",
"name": "CHEMBL593637",
"size": 2000.0000000000866
}]
}]
}, {
"dist": 0.0246952948163,
"name": "N18",
"children": [{
"dist": 0.358771918732,
"group": "blue",
"name": "CHEMBL569878",
"size": 2000.0000000000866
}, {
"dist": 0.36317930078,
"group": "blue",
"name": "CHEMBL434267",
"size": 2000.0000000000866
}]
}]
}]
}]
}, {
"dist": 0.00389420127272,
"name": "N21",
"children": [{
"dist": 0.010842478752,
"name": "N22",
"children": [{
"dist": 0.415105380276,
"group": "blue",
"name": "CHEMBL1275732",
"size": 2000.0000000000866
}, {
"dist": 0.0337121910412,
"name": "N24",
"children": [{
"dist": 0.0664262587727,
"name": "N25",
"children": [{
"dist": 0.315587114957,
"group": "red",
"name": "ASD00170175",
"size": 2000.0000000000866
}, {
"dist": 0.310918909139,
"group": "red",
"name": "CHEMBL292368",
"size": 2000.0000000000866
}]
}, {
"dist": 0.376684365543,
"group": "red",
"name": "ASD00170052",
"size": 2000.0000000000866
}]
}]
}, {
"dist": 0.00704072756384,
"name": "N29",
"children": [{
"dist": 0.0103358142929,
"name": "N30",
"children": [{
"dist": 0.412662682696,
"group": "blue",
"name": "CHEMBL14370",
"size": 2000.0000000000866
}, {
"dist": 0.427337317304,
"group": "blue",
"name": "CHEMBL94700",
"size": 2000.0000000000866
}]
}, {
"dist": 0.0142382687979,
"name": "N33",
"children": [{
"dist": 0.403816741996,
"group": "blue",
"name": "CHEMBL545557",
"size": 2000.0000000000866
}, {
"dist": 0.0752386947609,
"name": "N35",
"children": [{
"dist": 0.316746014667,
"group": "blue",
"name": "CHEMBL506342",
"size": 2000.0000000000866
}, {
"dist": 0.314832932701,
"group": "red",
"name": "CHEMBL1256402",
"size": 2000.0000000000866
}]
}]
}]
}]
} ]
}]
} ] };
readfile(data)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>

Fixing the axis-scale range that is presented

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>

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.

Zoom to fit Force layout in D3

I have the following Force layout graph in my D3 code...
// Code goes here
var width = w = 300,
height = h = 300,
link,
node,
svg,
force,
drag,
currentSelected;
function tick() {
link.attr("x1", function(d) {
return d.source.x;
})
.attr("y1", function(d) {
return d.source.y;
})
.attr("x2", function(d) {
return d.target.x;
})
.attr("y2", function(d) {
return d.target.y;
});
node.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
});
}
var graph = {
"nodes":
[
{
"code": "1130",
"name": "Interior",
"title": "Interior",
"id": 137,
"label": "ATAChild"
},
{
"code": "50",
"name": "Loose Equipment",
"title": "Loose Equipment",
"id": 146,
"label": "ATAChild"
},
{
"code": "2781 ",
"name": "LE FLAP POSITION IND SYSTEM",
"title": "LE FLAP POSITION IND SYSTEM",
"id": 218,
"label": "ATAChild"
},
{
"code": "2830 ",
"name": "FUEL DUMP",
"title": "FUEL DUMP",
"id": 227,
"label": "ATAChild"
},
{
"code": "1130",
"name": "Interior",
"title": "Interior",
"id": 138,
"label": "ATAChild"
},
{
"code": "50",
"name": "Loose Equipment",
"title": "Loose Equipment",
"id": 147,
"label": "ATAChild"
},
{
"code": "2781 ",
"name": "LE FLAP POSITION IND SYSTEM",
"title": "LE FLAP POSITION IND SYSTEM",
"id": 219,
"label": "ATAChild"
},
{
"code": "2830 ",
"name": "FUEL DUMP",
"title": "FUEL DUMP",
"id": 228,
"label": "ATAChild"
},
{
"code": "1130",
"name": "Interior",
"title": "Interior",
"id": 139,
"label": "ATAChild"
},
{
"code": "50",
"name": "Loose Equipment",
"title": "Loose Equipment",
"id": 148,
"label": "ATAChild"
},
{
"code": "2781 ",
"name": "LE FLAP POSITION IND SYSTEM",
"title": "LE FLAP POSITION IND SYSTEM",
"id": 220,
"label": "ATAChild"
},
{
"code": "2830 ",
"name": "FUEL DUMP",
"title": "FUEL DUMP",
"id": 229,
"label": "ATAChild"
}
],
"links":
[
]
}
function render() {
force
.nodes(graph.nodes)
.links(graph.links)
.start();
link = link.data(graph.links)
.enter().append("line")
.attr("class", "link");
node = node.data(graph.nodes)
.enter().append("circle")
.attr("class", "node")
.attr("r", 12)
.call(drag);
}
function init() {
force = d3.layout.force()
.size([width, height])
.charge(-400)
.linkDistance(40)
.on("tick", tick);
svg = d3.select("#graph").append("svg")
.attr("width", width)
.attr("height", height);
drag = force.drag();
link = svg.selectAll(".link");
node = svg.selectAll(".node");
}
window.onload = function(){
init();
render();
}
<div id="graph" class="full"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
Now I am fairly new to D3 but as you can see my issue is that you cannot see all the nodes. I am not sure what is happening here but I would like to have it zoom out so that even if it is painfully small I can still see all nodes. I have seen some answers related to zooming but I have had no luck getting it to work with the force layout. Im you need to play around I have a plnkr as well.

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>

Resources