Issue with d3 Multi Line Chart - d3.js

I didn't get line throw this code,
i get perfect axis both side but line is still missing
while calling drawline function i got this errorr "Error: attribute d: Expected number, "M0,NaNL116.66666666…"."
i couldn't find out any solutions.
<script src="http://d3js.org/d3.v4.min.js"></script>
//Data from Webservice
var jsonData = [{ "YEAR": "2017", "JAN": "0", "FEB": "21", "MAR": "65", "APR": "25", "MAY": "33", "JUN": "30", "JUL": "17", "AUG": "26", "SEP": "0", "OCT": "5", "NOV": "33", "DEC": "12" }, { "YEAR": "2018", "JAN": "10", "FEB": "0", "MAR": "0", "APR": "0", "MAY": "0", "JUN": "0", "JUL": "0", "AUG": "0", "SEP": "0", "OCT": "0", "NOV": "0", "DEC": "0" }]; `
var x = d3.scaleBand().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
var tests = months.map(function (m) {`
return {
month: m,
values: jsonData.map(function (d) {
return {
year: d.YEAR,
quote: +d[m]
};
})
};
});
x.domain(tests.map(function (d) { return d.month; }));
y.domain([d3.min(tests, function (c) {
return d3.min(c.values, function (v) {
return v.quote;
});
}),
d3.max(tests, function (c) { return d3.max(c.values, ` `function (v) { return v.quote; }); })]);
// Create Line
var drawLine = d3.line()
.curve(d3.curveBasis)
.x(function (d) {
debugger;
return x(d.month);
})
.y(function (d) {
debugger;
return y(d.values);
});
var draw = svg.selectAll(".month")
.data(tests)
.enter().append("g")
.attr("class", "month")
.datum(tests)
.append("path")
.attr("class", "line")
.attr("d", drawLine)
.style("stroke", function (d) {
return color(d.year);
})
`

Looks like a lot of stuff is missing from your code.
I made a few changes in the code and it works now.
//Data from Webservice
var jsonData = [{ "YEAR": "2017", "JAN": "0", "FEB": "21", "MAR": "65", "APR": "25", "MAY": "33", "JUN": "30", "JUL": "17", "AUG": "26", "SEP": "0", "OCT": "5", "NOV": "33", "DEC": "12" }, { "YEAR": "2018", "JAN": "10", "FEB": "0", "MAR": "0", "APR": "0", "MAY": "0", "JUN": "0", "JUL": "0", "AUG": "0", "SEP": "0", "OCT": "0", "NOV": "0", "DEC": "0" }];
var width = 400;
var height = 400;
var svg = d3.select('#lineChart');
var x = d3.scaleBand().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
var months = [];
d3.keys(jsonData[0]).filter(function(key) {
if (key !== "YEAR") {
months.push(key)
}
});
var years = [];
for (var i = 0; i < jsonData.length; i++) {
years.push(jsonData[i]['YEAR']);
}
var tests = months.map(function(m) {
return {
month: m,
values: jsonData.map(function(d) {
return {
year: d.YEAR,
quote: parseInt(+d[m])
};
})
};
});
x.domain(tests.map(function(d) {
return d.month;
}));
var extent = [d3.min(tests, function(c) {
return d3.min(c.values, function(v) {
return v.quote;
});
}),
d3.max(tests, function(c) {
return d3.max(c.values, function(v) {
return v.quote;
});
})
]
y.domain(extent);
// Create Line
var drawLine = d3.line()
.curve(d3.curveBasis)
.x(function(d) {
return x(d.month);
})
.y(function(d) {
return y((d.values[0]['quote']));
});
var draw = svg.append('g').append("path")
.datum(tests)
.attr("class", "line")
.attr("d", drawLine)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("stroke-width", 1.5);

Related

Updating nodes and links with labels in d3 force directed network graph is not removing the nodes properly

I am trying to create a d3 force directed network graph where based on a given network I can update the network by modifying the links and nodes and re-update them in the svg.
I tweaked the code so that a g element can be created which enclose each node circle so that I can add a text inside that same g element.
But now the labels are working perfectly but when I transition from graph 3 to graph 1 by clicking button 3 first then clicking button 1, the links that are redundant (a->d, a->f) are removed perfectly but the nodes that are redundant (e and f) stays in the svg.
I could not figure out whether it was a wrong selection or do I need some tweaking in the tick() function?
Here is the code:
var height = 200;
var width = 200;
const graph = {
"nodes": [
{ "name": "a", "group": 1 },
{ "name": "b", "group": 2 },
{ "name": "c", "group": 3 },
{ "name": "d", "group": 4 }
],
"links": [
{ "source": "a", "target": "b", "value": 1 },
{ "source": "b", "target": "c", "value": 1 },
{ "source": "c", "target": "d", "value": 1 }
]
}
const graph2 = {
"nodes": [
{ "name": "a", "group": 1 },
{ "name": "b", "group": 2 },
{ "name": "c", "group": 3 },
{ "name": "d", "group": 4 }
],
"links": [
{ "source": "a", "target": "b", "value": 1 },
{ "source": "b", "target": "c", "value": 1 },
{ "source": "c", "target": "d", "value": 1 },
{ "source": "a", "target": "d", "value": 1 }
]
}
const graph3 = {
"nodes": [
{ "name": "a", "group": 1 },
{ "name": "b", "group": 2 },
{ "name": "c", "group": 3 },
{ "name": "d", "group": 4 },
{ "name": "e", "group": 4 },
{ "name": "f", "group": 4 }
],
"links": [
{ "source": "a", "target": "b", "value": 1 },
{ "source": "b", "target": "c", "value": 1 },
{ "source": "c", "target": "d", "value": 1 },
{ "source": "a", "target": "d", "value": 1 },
{ "source": "f", "target": "a", "value": 1 }
]
}
var simulation = d3.forceSimulation()
.force("ct", d3.forceCenter(height / 2, width / 2))
.force("link", d3.forceLink().id(function(d) { return d.name; })
.distance(50).strength(2))
.force("charge", d3.forceManyBody().strength(-240))
// use forceX and forceY instead to change the relative positioning
// .force("centering", d3.forceCenter(width/2, height/2))
.force("x", d3.forceX(width / 2))
.force("y", d3.forceY(height / 2))
.on("tick", tick);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.append("g").attr("class", "links");
svg.append("g").attr("class", "nodes");
function start(graph) {
var linkElements = svg.select(".links").selectAll(".link").data(graph.links);
linkElements.enter().append("line").attr("class", "link");
linkElements.exit().remove();
var nodeElements = svg.select(".nodes").selectAll(".node")
.data(graph.nodes, function(d) { return d.name })
.enter().append("g")
.attr("class", "node");
var circles = nodeElements.append("circle")
.attr("r", 8);
var labels = nodeElements.append("text")
.text(function(d) { return d.name; })
.attr("x", 10)
.attr("y", 10);
nodeElements.exit().remove();
simulation.nodes(graph.nodes);
simulation.force("link").links(graph.links);
simulation.alphaTarget(0.1).restart();
}
function tick() {
var nodeElements = svg.select(".nodes").selectAll(".node");
var linkElements = svg.select(".links").selectAll(".link");
nodeElements.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
})
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
linkElements.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; });
}
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.1).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
start(graph);
document.getElementById('btn1').addEventListener('click', function() {
start(graph);
});
document.getElementById('btn2').addEventListener('click', function() {
start(graph2);
});
document.getElementById('btn3').addEventListener('click', function() {
start(graph3);
});
.link {
stroke: #000;
stroke-width: 1.5px;
}
.node {
stroke-width: 1.5px;
}
text {
font-family: sans-serif;
font-size: 10px;
fill: #000000;
}
<body>
<div>
<button id='btn1'>1</button>
<button id='btn2'>2</button>
<button id='btn3'>3</button>
</div>
</body>
<script src="https://d3js.org/d3.v5.min.js"></script>
Here is the jsfiddle version of the code: https://jsfiddle.net/syedarehaq/myd0h5w1/
In the provided code, variable nodeElements contains the enter selection, rather than the whole data binding selection.
var nodeElements = svg.select(".nodes").selectAll(".node")
.data(graph.nodes, function(d) { return d.name })
.enter().append("g")
.attr("class", "node");
nodeElements declaration should not contain the .enter bit - it should be just like linkSelection variable declaration:
var nodeElements = svg.select(".nodes").selectAll(".node")
.data(graph.nodes, function(d) { return d.name })
Then, in order to append the new circles and texts only to the entering g elements, adapt as follows:
var enterSelection = nodeElements.enter().append("g")
.attr("class", "node");
var circles = enterSelection.append("circle")
.attr("r", 8);
var labels = enterSelection.append("text")
.text(function(d) { return d.name; })
.attr("x", 10)
.attr("y", 10);
The exit function call is now working as expected.
Demo in the snippet below.
var height = 200;
var width = 200;
const graph = {
"nodes": [
{ "name": "a", "group": 1 },
{ "name": "b", "group": 2 },
{ "name": "c", "group": 3 },
{ "name": "d", "group": 4 }
],
"links": [
{ "source": "a", "target": "b", "value": 1 },
{ "source": "b", "target": "c", "value": 1 },
{ "source": "c", "target": "d", "value": 1 }
]
}
const graph2 = {
"nodes": [
{ "name": "a", "group": 1 },
{ "name": "b", "group": 2 },
{ "name": "c", "group": 3 },
{ "name": "d", "group": 4 }
],
"links": [
{ "source": "a", "target": "b", "value": 1 },
{ "source": "b", "target": "c", "value": 1 },
{ "source": "c", "target": "d", "value": 1 },
{ "source": "a", "target": "d", "value": 1 }
]
}
const graph3 = {
"nodes": [
{ "name": "a", "group": 1 },
{ "name": "b", "group": 2 },
{ "name": "c", "group": 3 },
{ "name": "d", "group": 4 },
{ "name": "e", "group": 4 },
{ "name": "f", "group": 4 }
],
"links": [
{ "source": "a", "target": "b", "value": 1 },
{ "source": "b", "target": "c", "value": 1 },
{ "source": "c", "target": "d", "value": 1 },
{ "source": "a", "target": "d", "value": 1 },
{ "source": "f", "target": "a", "value": 1 }
]
}
var simulation = d3.forceSimulation()
.force("ct", d3.forceCenter(height / 2, width / 2))
.force("link", d3.forceLink().id(function(d) { return d.name; })
.distance(50).strength(2))
.force("charge", d3.forceManyBody().strength(-240))
// use forceX and forceY instead to change the relative positioning
// .force("centering", d3.forceCenter(width/2, height/2))
.force("x", d3.forceX(width / 2))
.force("y", d3.forceY(height / 2))
.on("tick", tick);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.append("g").attr("class", "links");
svg.append("g").attr("class", "nodes");
function start(graph) {
var linkElements = svg.select(".links").selectAll(".link").data(graph.links);
linkElements.enter().append("line").attr("class", "link");
linkElements.exit().remove();
var nodeElements = svg.select(".nodes").selectAll(".node")
.data(graph.nodes, function(d) { return d.name })
var enterSelection = nodeElements.enter().append("g")
.attr("class", "node");
var circles = enterSelection.append("circle")
.attr("r", 8);
var labels = enterSelection.append("text")
.text(function(d) { return d.name; })
.attr("x", 10)
.attr("y", 10);
nodeElements.exit().remove();
simulation.nodes(graph.nodes);
simulation.force("link").links(graph.links);
simulation.alphaTarget(0.1).restart();
}
function tick() {
var nodeElements = svg.select(".nodes").selectAll(".node");
var linkElements = svg.select(".links").selectAll(".link");
nodeElements.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
})
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
linkElements.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; });
}
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.1).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
start(graph);
document.getElementById('btn1').addEventListener('click', function() {
start(graph);
});
document.getElementById('btn2').addEventListener('click', function() {
start(graph2);
});
document.getElementById('btn3').addEventListener('click', function() {
start(graph3);
});
.link {
stroke: #000;
stroke-width: 1.5px;
}
.node {
stroke-width: 1.5px;
}
text {
font-family: sans-serif;
font-size: 10px;
fill: #000000;
}
<body>
<div>
<button id='btn1'>1</button>
<button id='btn2'>2</button>
<button id='btn3'>3</button>
</div>
</body>
<script src="https://d3js.org/d3.v5.min.js"></script>

create flexible links in d3 tree paths

I'm new to D3 js. I would like to draw a tree structure using d3. However, I want the paths between my nodes to be flexible unlike the usual diagonal and projection methods. I need connections between the nodes to be like this:
How do I do this in d3?
This is my current code with diagonal.
<html>
<head>
<title> Box office </title>
</head>
<body>
<style>
.node {
cursor: pointer;
}
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 3px;
}
.node text {
font: 12px sans-serif;
}
.link {
fill: none;
stroke: #ccc;
stroke-width: 2px;
}
</style>
<!-- load the d3.js library -->
<script src="https://d3js.org/d3.v3.min.js"></script>
<div id = "boxoffice"></div>
<script type="text/javascript">
var sampleData = [
{
"ChangeFlowsFromParent": "false",
"ChangeFlowsToParent": "false",
"StreamType": "Mainline",
"streamName": "ArgOS_2_0",
"Parent": "none",
"Compliance": "Released",
"children": [
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Development",
"streamName": "ArgOS_2_0_DHAL",
"Parent": "ArgOS_2_0",
"Compliance": "Released"
},
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Development",
"streamName": "ArgOS_2_0_Dev",
"Parent": "ArgOS_2_0",
"Compliance": "Released",
"children": [
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Release",
"streamName": "r_ArgOS_0230",
"Parent": "ArgOS_2_0_Dev",
"Compliance": "Released"
},
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Release",
"streamName": "branch1",
"Parent": "ArgOS_2_0_Dev",
"Compliance": "Released",
"children": [
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Release",
"streamName": "branch100",
"Parent": "branch1",
"Compliance": "Released"
},
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Release",
"streamName": "branch200",
"Parent": "branch1",
"Compliance": "Released",
"children": [
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Release",
"streamName": "honey",
"Parent": "branch200",
"Compliance": "Released"
}
]
}
]
}
]
},
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Development",
"streamName": "ArgOS_2_0_IPC-Tracer",
"Parent": "ArgOS_2_0",
"Compliance": "Released",
"children": [
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Release",
"streamName": "ArgOS_2_0_IPC_child 1",
"Parent": "ArgOS_2_0_IPC",
"Compliance": "Released"
},
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Release",
"streamName": "ArgOS_2_0_IPC_child 2",
"Parent": "ArgOS_2_0_IPC",
"Compliance": "Released"
}
]
},
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Development",
"streamName": "ArgOS_2_0_NSW_Temp",
"Parent": "ArgOS_2_0",
"Compliance": "Released"
},
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Development",
"streamName": "ArgOS_2_0_Test",
"Parent": "ArgOS_2_0",
"Compliance": "Released"
},
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Development",
"streamName": "ArgOS_2_CBD",
"Parent": "ArgOS_2_0",
"Compliance": "Released"
},
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Development",
"streamName": "test_mergewp",
"Parent": "ArgOS_2_0",
"Compliance": "Released"
}
]
}
]
var margin = {top:100, bottom: 100, left:100, right:100},
width = 1800 - margin.left-margin.right, //total width minus side margins
height = 1500 - margin.top - margin.bottom; //total height minus vertical margins
var tree = d3.layout.tree().size([width, height]);
tree.nodeSize([40,100]);
var diagonal = d3.svg.diagonal()
.projection(function(d) { return [d.x, -d.y]; });
var svgContainer = d3.select("#boxoffice").append("svg").attr("width", width).attr("height", height).append("g").attr("transform", "translate(" + (width/2) + "," + (height - 500) + ")");
var root = sampleData[0];
root.x0 = width/2;
root.y0 = 0;
update(root);
d3.select(self.frameElement).style("height", "500px");
function update(sourceNode){
var nodes = tree.nodes(sourceNode).reverse(),
links = tree.links(nodes);
nodes.forEach(function(d){d.y = d.depth * 180});
var node = svgContainer.selectAll("g.node").attr("class", "node").data(nodes, function(d, i){return d.id || (d.id = ++i); });
var nodeEnter = node.enter().append("g")
.attr("transform", function(d) {
<!-- if(d.StreamType == "Mainline") -->
<!-- return "translate(-100,-100)"; -->
<!-- else -->
return "translate(" + sourceNode.y0 + "," + sourceNode.x0 + ")";
});
nodeEnter.append("circle")
.attr("r", 15)
.style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
nodeEnter.append("text")
.attr("x", function(d) { return d.children || d._children ? -13 : 13; })
.attr("dy", ".35em")
.attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
.text(function(d) { return d.streamName; })
.style("fill-opacity", 1e-6);
var nodeUpdate = node.transition()
.duration(100)
.attr("transform", function(d) {
if(d.StreamType == "Mainline")
{
var lastElement = nodes[0];
return "translate(" + (lastElement.y + 100) + "," + (lastElement.x -130) + ")"; //adding the root element
}
else
return "translate(" + d.y + "," + (d.x-(margin.top + margin.bottom)) + ")";
});
nodeUpdate.select("circle")
.attr("r", 10)
.style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
nodeUpdate.select("text")
.style("fill-opacity", 1);
var link = svgContainer.selectAll("path.link")
.data(links, function(d) { return d.target.id; });
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function(d) {
var o = {x: sourceNode.x0, y: sourceNode.y0};
return diagonal({source: o, target: o});
});
// Transition links to their new position.
link.transition()
.duration(10)
.attr("d", diagonal);
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
}
function positionLink(d) {
return "M" + d[0].x + "," + d[0].y
+ "S" + d[1].x + "," + d[1].y
+ " " + d[2].x + "," + d[2].y;
}
</script>
</body>
</html>
As in this code, the links are all messy. I can tidy it up for diagonal path links, but I want my links to be dynamic and flexible. How can I achieve this?
It's unclear what you mean by "flexible". More accurate terminology can be gathered from https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths#Bezier_Curves . For example, you may want a cubic Bezier curve.
To implement this, you will need to alter this section of code:
.attr("d", function(d) {
var o = {x: sourceNode.x0, y: sourceNode.y0};
return diagonal({source: o, target: o});
More information can be found at this example, which seems to implement what you want:
https://bl.ocks.org/mbostock/4339184
It uses:
.attr("d", d3.linkHorizontal()
.x(function(d) { return d.y; })
.y(function(d) { return d.x; }));
The link capabilities are related, but not equivalent to the diagonal capabilities.

JSON instead of CSV for bubble chart

I'm using bubble chart which takes input from csv file, is there a way to use JSON instead?
Here is the Problem url:
http://ec2-54-198-148-171.compute-1.amazonaws.com/webapp/provider-view
Problem Code:
d3.csv(flare.csv, function(d) {
//console.log(d);
d.value = +d.value;
d.seq = +d.seq;
if (d.value) return d;
}, function(error, classes) {
if (error) throw error;
var root = d3.hierarchy({children: classes})
.sum(function(d) { return d.value; })
.each(function(d) {
if (id = d.data.id) {
var id,seq, i = id.lastIndexOf(".");
d.id = id;//console.log(i + " " + id);
d.package = id.slice(0, i);//console.log(d.package);
d.class = id.slice(i + 1);
d.seq = d.data.seq;
}
});
var node = svg.selectAll(".node")
.data(pack(root).leaves())
.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) {
if(d.seq==1){
d.x = d.x - 100;
d.y = d.y + 20;
return "translate(" + d.x + "," + d.y + ")";
}else{
d.x = d.x + 500;
d.y = d.y + 20;
return "translate(" + d.x + "," + d.y + ")";
} });
node.append("circle")
.attr("id", function(d) { return d.id; })
.attr("r", function(d) { d.r = parseInt(d.r)-5; return d.r; })
.attr("onclick",function(d) { return "demo('" +d.id + "',"+ d.seq+","+ (d.x+d.r+111)+","+ (d.y+100-30)+");"; })
.style("fill", function(d) { //console.log(d.seq);
if(d.seq==1){
return "url(#gradient1)";
}else{
return "#773F9B";
}
});
node.append("clipPath")
.attr("id", function(d) { return "clip-" + d.id; })
.append("use")
.attr("xlink:href", function(d) { return "#" + d.id; });
node.append("div")
.attr("id","tooltip")
.attr("style","width:100px;height:10px;background-color:gray;z-index:1000");
});
Sample csv :
id,value,seq
demo11,100,1
demo12,200,1
demo13,300,1
demo14,400,1
demo15,500,1
demo16,600,1
demo17,600,1
demo21,50,2
demo22,100,2
demo23,150,2
demo24,200,2
demo25,250,2
demo26,300,2
demo27,350,2
The short answer is: yes.
The long answer: to change the data from a csv file to a json file, it's not simply a matter of changing d3.csv for d3.json. That's necessary, of course, as #RobertLongson said in the comments. But, besides that, you'll have to understand how d3.csv creates an array of objects with your CSV, since you need to create your JSON mimicking that array.
So, given your CSV, this is how d3.csv creates an array of objects:
var data = d3.csvParse(d3.select("#csv").text());
console.log(JSON.stringify(data))
pre {
display: none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<pre id="csv">id,value,seq
demo11,100,1
demo12,200,1
demo13,300,1
demo14,400,1
demo15,500,1
demo16,600,1
demo17,600,1
demo21,50,2
demo22,100,2
demo23,150,2
demo24,200,2
demo25,250,2
demo26,300,2
demo27,350,2</pre>
That being said, to change your data from CSV to JSON (without doing any further change in the code), your JSON need to have exactly this structure:
[{
"id": "demo11",
"value": "100",
"seq": "1"
}, {
"id": "demo12",
"value": "200",
"seq": "1"
}, {
"id": "demo13",
"value": "300",
"seq": "1"
}, {
"id": "demo14",
"value": "400",
"seq": "1"
}, {
"id": "demo15",
"value": "500",
"seq": "1"
}, {
"id": "demo16",
"value": "600",
"seq": "1"
}, {
"id": "demo17",
"value": "600",
"seq": "1"
}, {
"id": "demo21",
"value": "50",
"seq": "2"
}, {
"id": "demo22",
"value": "100",
"seq": "2"
}, {
"id": "demo23",
"value": "150",
"seq": "2"
}, {
"id": "demo24",
"value": "200",
"seq": "2"
}, {
"id": "demo25",
"value": "250",
"seq": "2"
}, {
"id": "demo26",
"value": "300",
"seq": "2"
}, {
"id": "demo27",
"value": "350",
"seq": "2"
}]

d3 update path with maximum value of area

I display a d3.area(). To show the highest value, I draw a horizontal line with d3.line() at the maximum value of the dataset. This value is calculated using:
var max_out = d3.max(data, function(d){ return +d.out; });
To brush through the graph, I use the setup as in this example:
As soon as the area is brushed, I would also like to move the "maximum line" up and down reflecting the new domain instead of using the whole dataset.
Any pointers?
Let's have a line function definition, in the first time only defining the x attribute:
var line = d3.line()
.x(function(d) { return x(d.date); });
Right after you append your area in the main view, add another path, which will be used to draw your horizontal line above the corresponding area:
focus.append("path")
.attr("class", "line");
Notice that I'm giving it a line class for styling.
We're also gonna draw the line, at first simply using the function you are currently using to determine the peak of your data:
.attr("d", line.y(function () {
return y(max);
}));
... and feed our line generator the right data :):
.datum(data)
To summarize, here's what we got on initialization:
// There's your main view's data area
focus.append("path")
.datum(data)
.attr("class", "area")
.attr("d", area);
// There's your 'peak' horizontal line
var max = d3.max(data, function(d){ return d.price; });
focus.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line.y(function () {
return y(max);
}));
In the functions that trigger a re-drawing of your elements, you simply have to update the d attribute of your path.line element.
We're gonna simply do the following:
Filter out data points that aren't within the updated domain of your x-axis
Evaluate the maximum value of that sub-set (using the method you described)
Let D3 generate the new value for the d attribute and set it.
That translates into the following:
var lo = x.domain()[0],
hi = x.domain()[1];
var max = d3.max(data.filter(function (d) {
return d.date.getTime() >= lo && d.date.getTime() <= hi;
}), function(d){ return d.price; });
focus.select(".line").attr("d", line.y(function () {
return y(max);
}));
See an example in action in the snippet below or on JSFiddle.
var svg = d3.select("svg"),
margin = {top: 20, right: 20, bottom: 110, left: 40},
margin2 = {top: 180, right: 20, bottom: 30, left: 40},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
height2 = +svg.attr("height") - margin2.top - margin2.bottom;
var x = d3.scaleTime().range([0, width]),
x2 = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]),
y2 = d3.scaleLinear().range([height2, 0]);
var xAxis = d3.axisBottom(x),
xAxis2 = d3.axisBottom(x2),
yAxis = d3.axisLeft(y);
var brush = d3.brushX()
.extent([[0, 0], [width, height2]])
.on("brush end", brushed);
var zoom = d3.zoom()
.scaleExtent([1, Infinity])
.translateExtent([[0, 0], [width, height]])
.extent([[0, 0], [width, height]])
.on("zoom", zoomed);
var area = d3.area()
.x(function(d) { return x(d.date); })
.y0(height)
.y1(function(d) { return y(d.price); });
var area2 = d3.area()
.x(function(d) { return x2(d.date); })
.y0(height2)
.y1(function(d) { return y2(d.price); });
var line = d3.line()
.x(function(d) { return x(d.date); });
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("class", "context")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
var data;
(function (_data) {
data = _data;
data.forEach(function (d) {
d.date = new Date(d.date);
});
data = (function uniqBy(a, key) {
var seen = {};
return a.filter(function(item) {
var k = key(item);
return seen.hasOwnProperty(k) ? false : (seen[k] = true);
});
})(data, function (d) {return d.date;});
data.sort(function(a,b) {
return new Date(a.date).getTime() - new Date(b.date).getTime();
});
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.price; })]);
x2.domain(x.domain());
y2.domain(y.domain());
focus.append("path")
.datum(data)
.attr("class", "area")
.attr("d", area);
var max = d3.max(data, function(d){ return d.price; });
focus.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line.y(function () {
return y(max);
}));
focus.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
focus.append("g")
.attr("class", "axis axis--y")
.call(yAxis);
context.append("path")
.datum(data)
.attr("class", "area")
.attr("d", area2);
context.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.append("g")
.attr("class", "brush")
.call(brush)
.call(brush.move, x.range());
svg.append("rect")
.attr("class", "zoom")
.attr("width", width)
.attr("height", height)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(zoom);
})([{"date":"1999-12-31T23:00:00.000Z","price":1394.46},{"date":"2000-01-31T23:00:00.000Z","price":1366.42},{"date":"2000-02-29T23:00:00.000Z","price":1498.58},{"date":"2000-03-31T22:00:00.000Z","price":1452.43},{"date":"2000-04-30T22:00:00.000Z","price":1420.6},{"date":"2000-05-31T22:00:00.000Z","price":1454.6},{"date":"2000-06-30T22:00:00.000Z","price":1430.83},{"date":"2000-07-31T22:00:00.000Z","price":1517.68},{"date":"2000-08-31T22:00:00.000Z","price":1436.51},{"date":"2000-09-30T22:00:00.000Z","price":1429.4},{"date":"2000-10-31T23:00:00.000Z","price":1314.95},{"date":"2000-11-30T23:00:00.000Z","price":1320.28},{"date":"2000-12-31T23:00:00.000Z","price":1366.01},{"date":"2001-01-31T23:00:00.000Z","price":1239.94},{"date":"2001-02-28T23:00:00.000Z","price":1160.33},{"date":"2001-03-31T22:00:00.000Z","price":1249.46},{"date":"2001-04-30T22:00:00.000Z","price":1255.82},{"date":"2001-05-31T22:00:00.000Z","price":1224.38},{"date":"2001-06-30T22:00:00.000Z","price":1211.23},{"date":"2001-07-31T22:00:00.000Z","price":1133.58},{"date":"2001-08-31T22:00:00.000Z","price":1040.94},{"date":"2001-09-30T22:00:00.000Z","price":1059.78},{"date":"2001-10-31T23:00:00.000Z","price":1139.45},{"date":"2001-11-30T23:00:00.000Z","price":1148.08},{"date":"2001-12-31T23:00:00.000Z","price":1130.2},{"date":"2002-01-31T23:00:00.000Z","price":1106.73},{"date":"2002-02-28T23:00:00.000Z","price":1147.39},{"date":"2002-03-31T22:00:00.000Z","price":1076.92},{"date":"2002-04-30T22:00:00.000Z","price":1067.14},{"date":"2002-05-31T22:00:00.000Z","price":989.82},{"date":"2002-06-30T22:00:00.000Z","price":911.62},{"date":"2002-07-31T22:00:00.000Z","price":916.07},{"date":"2002-08-31T22:00:00.000Z","price":815.28},{"date":"2002-09-30T22:00:00.000Z","price":885.76},{"date":"2002-10-31T23:00:00.000Z","price":936.31},{"date":"2002-11-30T23:00:00.000Z","price":879.82},{"date":"2002-12-31T23:00:00.000Z","price":855.7},{"date":"2003-01-31T23:00:00.000Z","price":841.15},{"date":"2003-02-28T23:00:00.000Z","price":848.18},{"date":"2003-03-31T22:00:00.000Z","price":916.92},{"date":"2003-04-30T22:00:00.000Z","price":963.59},{"date":"2003-05-31T22:00:00.000Z","price":974.5},{"date":"2003-06-30T22:00:00.000Z","price":990.31},{"date":"2003-07-31T22:00:00.000Z","price":1008.01},{"date":"2003-08-31T22:00:00.000Z","price":995.97},{"date":"2003-09-30T22:00:00.000Z","price":1050.71},{"date":"2003-10-31T23:00:00.000Z","price":1058.2},{"date":"2003-11-30T23:00:00.000Z","price":1111.92},{"date":"2003-12-31T23:00:00.000Z","price":1131.13},{"date":"2004-01-31T23:00:00.000Z","price":1144.94},{"date":"2004-02-29T23:00:00.000Z","price":1126.21},{"date":"2004-03-31T22:00:00.000Z","price":1107.3},{"date":"2004-04-30T22:00:00.000Z","price":1120.68},{"date":"2004-05-31T22:00:00.000Z","price":1140.84},{"date":"2004-06-30T22:00:00.000Z","price":1101.72},{"date":"2004-07-31T22:00:00.000Z","price":1104.24},{"date":"2004-08-31T22:00:00.000Z","price":1114.58},{"date":"2004-09-30T22:00:00.000Z","price":1130.2},{"date":"2004-10-31T23:00:00.000Z","price":1173.82},{"date":"2004-11-30T23:00:00.000Z","price":1211.92},{"date":"2004-12-31T23:00:00.000Z","price":1181.27},{"date":"2005-01-31T23:00:00.000Z","price":1203.6},{"date":"2005-02-28T23:00:00.000Z","price":1180.59},{"date":"2005-03-31T22:00:00.000Z","price":1156.85},{"date":"2005-04-30T22:00:00.000Z","price":1191.5},{"date":"2005-05-31T22:00:00.000Z","price":1191.33},{"date":"2005-06-30T22:00:00.000Z","price":1234.18},{"date":"2005-07-31T22:00:00.000Z","price":1220.33},{"date":"2005-08-31T22:00:00.000Z","price":1228.81},{"date":"2005-09-30T22:00:00.000Z","price":1207.01},{"date":"2005-10-31T23:00:00.000Z","price":1249.48},{"date":"2005-11-30T23:00:00.000Z","price":1248.29},{"date":"2005-12-31T23:00:00.000Z","price":1280.08},{"date":"2006-01-31T23:00:00.000Z","price":1280.66},{"date":"2006-02-28T23:00:00.000Z","price":1294.87},{"date":"2006-03-31T22:00:00.000Z","price":1310.61},{"date":"2006-04-30T22:00:00.000Z","price":1270.09},{"date":"2006-05-31T22:00:00.000Z","price":1270.2},{"date":"2006-06-30T22:00:00.000Z","price":1276.66},{"date":"2006-07-31T22:00:00.000Z","price":1303.82},{"date":"2006-08-31T22:00:00.000Z","price":1335.85},{"date":"2006-09-30T22:00:00.000Z","price":1377.94},{"date":"2006-10-31T23:00:00.000Z","price":1400.63},{"date":"2006-11-30T23:00:00.000Z","price":1418.3},{"date":"2006-12-31T23:00:00.000Z","price":1438.24},{"date":"2007-01-31T23:00:00.000Z","price":1406.82},{"date":"2007-02-28T23:00:00.000Z","price":1420.86},{"date":"2007-03-31T22:00:00.000Z","price":1482.37},{"date":"2007-04-30T22:00:00.000Z","price":1530.62},{"date":"2007-05-31T22:00:00.000Z","price":1503.35},{"date":"2007-06-30T22:00:00.000Z","price":1455.27},{"date":"2007-07-31T22:00:00.000Z","price":1473.99},{"date":"2007-08-31T22:00:00.000Z","price":1526.75},{"date":"2007-09-30T22:00:00.000Z","price":1549.38},{"date":"2007-10-31T23:00:00.000Z","price":1481.14},{"date":"2007-11-30T23:00:00.000Z","price":1468.36},{"date":"2007-12-31T23:00:00.000Z","price":1378.55},{"date":"2008-01-31T23:00:00.000Z","price":1330.63},{"date":"2008-02-29T23:00:00.000Z","price":1322.7},{"date":"2008-03-31T22:00:00.000Z","price":1385.59},{"date":"2008-04-30T22:00:00.000Z","price":1400.38},{"date":"2008-05-31T22:00:00.000Z","price":1280},{"date":"2008-06-30T22:00:00.000Z","price":1267.38},{"date":"2008-07-31T22:00:00.000Z","price":1282.83},{"date":"2008-08-31T22:00:00.000Z","price":1166.36},{"date":"2008-09-30T22:00:00.000Z","price":968.75},{"date":"2008-10-31T23:00:00.000Z","price":896.24},{"date":"2008-11-30T23:00:00.000Z","price":903.25},{"date":"2008-12-31T23:00:00.000Z","price":825.88},{"date":"2009-01-31T23:00:00.000Z","price":735.09},{"date":"2009-02-28T23:00:00.000Z","price":797.87},{"date":"2009-03-31T22:00:00.000Z","price":872.81},{"date":"2009-04-30T22:00:00.000Z","price":919.14},{"date":"2009-05-31T22:00:00.000Z","price":919.32},{"date":"2009-06-30T22:00:00.000Z","price":987.48},{"date":"2009-07-31T22:00:00.000Z","price":1020.62},{"date":"2009-08-31T22:00:00.000Z","price":1057.08},{"date":"2009-09-30T22:00:00.000Z","price":1036.19},{"date":"2009-10-31T23:00:00.000Z","price":1095.63},{"date":"2009-11-30T23:00:00.000Z","price":1115.1},{"date":"2009-12-31T23:00:00.000Z","price":1073.87},{"date":"2010-01-31T23:00:00.000Z","price":1104.49},{"date":"2010-02-28T23:00:00.000Z","price":1140.45 }]);
function brushed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") return; // ignore brush-by-zoom
var s = d3.event.selection || x2.range();
x.domain(s.map(x2.invert, x2));
focus.select(".area").attr("d", area);
focus.select(".axis--x").call(xAxis);
svg.select(".zoom").call(zoom.transform, d3.zoomIdentity
.scale(width / (s[1] - s[0]))
.translate(-s[0], 0));
var lo = x.domain()[0],
hi = x.domain()[1];
var max = d3.max(data.filter(function (d) {
return d.date.getTime() >= lo && d.date.getTime() <= hi;
}), function(d){ return d.price; });
focus.select(".line").attr("d", line.y(function () {
return y(max);
}));
}
function zoomed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") return; // ignore zoom-by-brush
var t = d3.event.transform;
x.domain(t.rescaleX(x2).domain());
focus.select(".area").attr("d", area);
focus.select(".axis--x").call(xAxis);
context.select(".brush").call(brush.move, x.range().map(t.invertX, t));
var lo = x.domain()[0],
hi = x.domain()[1];
var max = d3.max(data.filter(function (d) {
return d.date.getTime() >= lo && d.date.getTime() <= hi;
}), function(d){ return d.price; });
focus.select(".line").attr("d", line.y(function () {
return y(max);
}));
}
function type(d) {
d.date = parseDate(d.date);
d.price = +d.price;
return d;
}
.area {
fill: steelblue;
clip-path: url(#clip);
}
.line {
stroke: red;
clip-path: url(#clip);
}
.zoom {
cursor: move;
fill: none;
pointer-events: all;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="250"></svg>
Something like this:
focus.append("line")
.attr("class", "peak")
.style("stroke", "orange")
.attr("stroke-width", 3);
function setPeak(){
var maxY = {
x: null,
y: -1e100
};
data.forEach(function(d){
if (d.date >= x.domain()[0] &&
d.date <= x.domain()[1] &&
d.price > maxY.y){
maxY.y = d.price;
maxY.x = d.date;
}
});
d3.select(".peak")
.attr("x1", x(maxY.x))
.attr("x2", x(maxY.x))
.attr("y1", 0)
.attr("y2", height);
}
setPeak();
Running code:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.area {
fill: steelblue;
clip-path: url(#clip);
}
.zoom {
cursor: move;
fill: none;
pointer-events: all;
}
</style>
<svg width="400" height="300"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var svg = d3.select("svg"),
margin = {
top: 20,
right: 20,
bottom: 110,
left: 40
},
margin2 = {
top: 230,
right: 20,
bottom: 30,
left: 40
},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
height2 = +svg.attr("height") - margin2.top - margin2.bottom;
var x = d3.scaleTime().range([0, width]),
x2 = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]),
y2 = d3.scaleLinear().range([height2, 0]);
var xAxis = d3.axisBottom(x),
xAxis2 = d3.axisBottom(x2),
yAxis = d3.axisLeft(y);
var brush = d3.brushX()
.extent([
[0, 0],
[width, height2]
])
.on("brush end", brushed);
var zoom = d3.zoom()
.scaleExtent([1, Infinity])
.translateExtent([
[0, 0],
[width, height]
])
.extent([
[0, 0],
[width, height]
])
.on("zoom", zoomed);
var area = d3.area()
.curve(d3.curveMonotoneX)
.x(function(d) {
return x(d.date);
})
.y0(height)
.y1(function(d) {
return y(d.price);
});
var area2 = d3.area()
.curve(d3.curveMonotoneX)
.x(function(d) {
return x2(d.date);
})
.y0(height2)
.y1(function(d) {
return y2(d.price);
});
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("class", "context")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
//d3.csv("data.csv", type, function(error, data) {
// if (error) throw error;
var data = [{
"date": "1999-12-31T23:00:00.000Z",
"price": 1394.46
}, {
"date": "2000-01-31T23:00:00.000Z",
"price": 1366.42
}, {
"date": "2000-02-29T23:00:00.000Z",
"price": 1498.58
}, {
"date": "2000-03-31T22:00:00.000Z",
"price": 1452.43
}, {
"date": "2000-04-30T22:00:00.000Z",
"price": 1420.6
}, {
"date": "2000-05-31T22:00:00.000Z",
"price": 1454.6
}, {
"date": "2000-06-30T22:00:00.000Z",
"price": 1430.83
}, {
"date": "2000-07-31T22:00:00.000Z",
"price": 1517.68
}, {
"date": "2000-08-31T22:00:00.000Z",
"price": 1436.51
}, {
"date": "2000-09-30T22:00:00.000Z",
"price": 1429.4
}, {
"date": "2000-10-31T23:00:00.000Z",
"price": 1314.95
}, {
"date": "2000-11-30T23:00:00.000Z",
"price": 1320.28
}, {
"date": "2000-12-31T23:00:00.000Z",
"price": 1366.01
}, {
"date": "2001-01-31T23:00:00.000Z",
"price": 1239.94
}, {
"date": "2001-02-28T23:00:00.000Z",
"price": 1160.33
}, {
"date": "2001-03-31T22:00:00.000Z",
"price": 1249.46
}, {
"date": "2001-04-30T22:00:00.000Z",
"price": 1255.82
}, {
"date": "2001-05-31T22:00:00.000Z",
"price": 1224.38
}, {
"date": "2001-06-30T22:00:00.000Z",
"price": 1211.23
}, {
"date": "2001-07-31T22:00:00.000Z",
"price": 1133.58
}, {
"date": "2001-08-31T22:00:00.000Z",
"price": 1040.94
}, {
"date": "2001-09-30T22:00:00.000Z",
"price": 1059.78
}, {
"date": "2001-10-31T23:00:00.000Z",
"price": 1139.45
}, {
"date": "2001-11-30T23:00:00.000Z",
"price": 1148.08
}, {
"date": "2001-12-31T23:00:00.000Z",
"price": 1130.2
}, {
"date": "2002-01-31T23:00:00.000Z",
"price": 1106.73
}, {
"date": "2002-02-28T23:00:00.000Z",
"price": 1147.39
}, {
"date": "2002-03-31T22:00:00.000Z",
"price": 1076.92
}, {
"date": "2002-04-30T22:00:00.000Z",
"price": 1067.14
}, {
"date": "2002-05-31T22:00:00.000Z",
"price": 989.82
}, {
"date": "2002-06-30T22:00:00.000Z",
"price": 911.62
}, {
"date": "2002-07-31T22:00:00.000Z",
"price": 916.07
}, {
"date": "2002-08-31T22:00:00.000Z",
"price": 815.28
}, {
"date": "2002-09-30T22:00:00.000Z",
"price": 885.76
}, {
"date": "2002-10-31T23:00:00.000Z",
"price": 936.31
}, {
"date": "2002-11-30T23:00:00.000Z",
"price": 879.82
}, {
"date": "2002-12-31T23:00:00.000Z",
"price": 855.7
}, {
"date": "2003-01-31T23:00:00.000Z",
"price": 841.15
}, {
"date": "2003-02-28T23:00:00.000Z",
"price": 848.18
}, {
"date": "2003-03-31T22:00:00.000Z",
"price": 916.92
}, {
"date": "2003-04-30T22:00:00.000Z",
"price": 963.59
}, {
"date": "2003-05-31T22:00:00.000Z",
"price": 974.5
}, {
"date": "2003-06-30T22:00:00.000Z",
"price": 990.31
}, {
"date": "2003-07-31T22:00:00.000Z",
"price": 1008.01
}, {
"date": "2003-08-31T22:00:00.000Z",
"price": 995.97
}, {
"date": "2003-09-30T22:00:00.000Z",
"price": 1050.71
}, {
"date": "2003-10-31T23:00:00.000Z",
"price": 1058.2
}, {
"date": "2003-11-30T23:00:00.000Z",
"price": 1111.92
}, {
"date": "2003-12-31T23:00:00.000Z",
"price": 1131.13
}, {
"date": "2004-01-31T23:00:00.000Z",
"price": 1144.94
}, {
"date": "2004-02-29T23:00:00.000Z",
"price": 1126.21
}, {
"date": "2004-03-31T22:00:00.000Z",
"price": 1107.3
}, {
"date": "2004-04-30T22:00:00.000Z",
"price": 1120.68
}, {
"date": "2004-05-31T22:00:00.000Z",
"price": 1140.84
}, {
"date": "2004-06-30T22:00:00.000Z",
"price": 1101.72
}, {
"date": "2004-07-31T22:00:00.000Z",
"price": 1104.24
}, {
"date": "2004-08-31T22:00:00.000Z",
"price": 1114.58
}, {
"date": "2004-09-30T22:00:00.000Z",
"price": 1130.2
}, {
"date": "2004-10-31T23:00:00.000Z",
"price": 1173.82
}, {
"date": "2004-11-30T23:00:00.000Z",
"price": 1211.92
}, {
"date": "2004-12-31T23:00:00.000Z",
"price": 1181.27
}, {
"date": "2005-01-31T23:00:00.000Z",
"price": 1203.6
}, {
"date": "2005-02-28T23:00:00.000Z",
"price": 1180.59
}, {
"date": "2005-03-31T22:00:00.000Z",
"price": 1156.85
}, {
"date": "2005-04-30T22:00:00.000Z",
"price": 1191.5
}, {
"date": "2005-05-31T22:00:00.000Z",
"price": 1191.33
}, {
"date": "2005-06-30T22:00:00.000Z",
"price": 1234.18
}, {
"date": "2005-07-31T22:00:00.000Z",
"price": 1220.33
}, {
"date": "2005-08-31T22:00:00.000Z",
"price": 1228.81
}, {
"date": "2005-09-30T22:00:00.000Z",
"price": 1207.01
}, {
"date": "2005-10-31T23:00:00.000Z",
"price": 1249.48
}, {
"date": "2005-11-30T23:00:00.000Z",
"price": 1248.29
}, {
"date": "2005-12-31T23:00:00.000Z",
"price": 1280.08
}, {
"date": "2006-01-31T23:00:00.000Z",
"price": 1280.66
}, {
"date": "2006-02-28T23:00:00.000Z",
"price": 1294.87
}, {
"date": "2006-03-31T22:00:00.000Z",
"price": 1310.61
}, {
"date": "2006-04-30T22:00:00.000Z",
"price": 1270.09
}, {
"date": "2006-05-31T22:00:00.000Z",
"price": 1270.2
}, {
"date": "2006-06-30T22:00:00.000Z",
"price": 1276.66
}, {
"date": "2006-07-31T22:00:00.000Z",
"price": 1303.82
}, {
"date": "2006-08-31T22:00:00.000Z",
"price": 1335.85
}, {
"date": "2006-09-30T22:00:00.000Z",
"price": 1377.94
}, {
"date": "2006-10-31T23:00:00.000Z",
"price": 1400.63
}, {
"date": "2006-11-30T23:00:00.000Z",
"price": 1418.3
}, {
"date": "2006-12-31T23:00:00.000Z",
"price": 1438.24
}, {
"date": "2007-01-31T23:00:00.000Z",
"price": 1406.82
}, {
"date": "2007-02-28T23:00:00.000Z",
"price": 1420.86
}, {
"date": "2007-03-31T22:00:00.000Z",
"price": 1482.37
}, {
"date": "2007-04-30T22:00:00.000Z",
"price": 1530.62
}, {
"date": "2007-05-31T22:00:00.000Z",
"price": 1503.35
}, {
"date": "2007-06-30T22:00:00.000Z",
"price": 1455.27
}, {
"date": "2007-07-31T22:00:00.000Z",
"price": 1473.99
}, {
"date": "2007-08-31T22:00:00.000Z",
"price": 1526.75
}, {
"date": "2007-09-30T22:00:00.000Z",
"price": 1549.38
}, {
"date": "2007-10-31T23:00:00.000Z",
"price": 1481.14
}, {
"date": "2007-11-30T23:00:00.000Z",
"price": 1468.36
}, {
"date": "2007-12-31T23:00:00.000Z",
"price": 1378.55
}, {
"date": "2008-01-31T23:00:00.000Z",
"price": 1330.63
}, {
"date": "2008-02-29T23:00:00.000Z",
"price": 1322.7
}, {
"date": "2008-03-31T22:00:00.000Z",
"price": 1385.59
}, {
"date": "2008-04-30T22:00:00.000Z",
"price": 1400.38
}, {
"date": "2008-05-31T22:00:00.000Z",
"price": 1280
}, {
"date": "2008-06-30T22:00:00.000Z",
"price": 1267.38
}, {
"date": "2008-07-31T22:00:00.000Z",
"price": 1282.83
}, {
"date": "2008-08-31T22:00:00.000Z",
"price": 1166.36
}, {
"date": "2008-09-30T22:00:00.000Z",
"price": 968.75
}, {
"date": "2008-10-31T23:00:00.000Z",
"price": 896.24
}, {
"date": "2008-11-30T23:00:00.000Z",
"price": 903.25
}, {
"date": "2008-12-31T23:00:00.000Z",
"price": 825.88
}, {
"date": "2009-01-31T23:00:00.000Z",
"price": 735.09
}, {
"date": "2009-02-28T23:00:00.000Z",
"price": 797.87
}, {
"date": "2009-03-31T22:00:00.000Z",
"price": 872.81
}, {
"date": "2009-04-30T22:00:00.000Z",
"price": 919.14
}, {
"date": "2009-05-31T22:00:00.000Z",
"price": 919.32
}, {
"date": "2009-06-30T22:00:00.000Z",
"price": 987.48
}, {
"date": "2009-07-31T22:00:00.000Z",
"price": 1020.62
}, {
"date": "2009-08-31T22:00:00.000Z",
"price": 1057.08
}, {
"date": "2009-09-30T22:00:00.000Z",
"price": 1036.19
}, {
"date": "2009-10-31T23:00:00.000Z",
"price": 1095.63
}, {
"date": "2009-11-30T23:00:00.000Z",
"price": 1115.1
}, {
"date": "2009-12-31T23:00:00.000Z",
"price": 1073.87
}, {
"date": "2010-01-31T23:00:00.000Z",
"price": 1104.49
}, {
"date": "2010-02-28T23:00:00.000Z",
"price": 1140.45
}];
data = data.map(type);
console.log(data)
x.domain(d3.extent(data, function(d) {
return d.date;
}));
y.domain([0, d3.max(data, function(d) {
return d.price;
})]);
x2.domain(x.domain());
y2.domain(y.domain());
focus.append("path")
.datum(data)
.attr("class", "area")
.attr("d", area);
focus.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
focus.append("g")
.attr("class", "axis axis--y")
.call(yAxis);
context.append("path")
.datum(data)
.attr("class", "area")
.attr("d", area2);
context.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.append("g")
.attr("class", "brush")
.call(brush)
.call(brush.move, x.range());
svg.append("rect")
.attr("class", "zoom")
.attr("width", width)
.attr("height", height)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(zoom);
focus.append("line")
.attr("class", "peak")
.style("stroke", "orange")
.attr("stroke-width", 3);
//});
function setPeak(){
var maxY = {
x: null,
y: -1e100
};
data.forEach(function(d){
if (d.date >= x.domain()[0] &&
d.date <= x.domain()[1] &&
d.price > maxY.y){
maxY.y = d.price;
maxY.x = d.date;
}
});
d3.select(".peak")
.attr("x1", x(maxY.x))
.attr("x2", x(maxY.x))
.attr("y1", 0)
.attr("y2", height);
}
setPeak();
function brushed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") return; // ignore brush-by-zoom
var s = d3.event.selection || x2.range();
x.domain(s.map(x2.invert, x2));
focus.select(".area").attr("d", area);
focus.select(".axis--x").call(xAxis);
svg.select(".zoom").call(zoom.transform, d3.zoomIdentity
.scale(width / (s[1] - s[0]))
.translate(-s[0], 0));
setPeak();
}
function zoomed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") return; // ignore zoom-by-brush
var t = d3.event.transform;
x.domain(t.rescaleX(x2).domain());
focus.select(".area").attr("d", area);
focus.select(".axis--x").call(xAxis);
context.select(".brush").call(brush.move, x.range().map(t.invertX, t));
}
function type(d) {
d.date = new Date(d.date);
d.price = +d.price;
return d;
}
</script>

Json d3 access each object

{
"name": "Max",
"value": 107,
"children": [
{
"name": "Don",
"value": 60,
"children" [
{"name": "CC", "value": 25},
{"name": "Jim", "value": 35}
]
},
{
"name": "David",
"value": 47,
"children": [
{"name": "Jeff", "value": 32},
{"name": "Buffy", "value": 15}
]
}
]
}
How can I access the inner most child name with d3?
I tried doing :
.text(function (d) { return d.children ? null : d.name; });
But it didn't work....
When I do
.text(function (d) { return d.name });
it only shows the name of the outer loop --> Don, David.
d3.json('flare.json', function (data) {
var canvas = d3.select('p1')
.append('svg')
.attr('width', 800)
.attr('height', 800)
var color = d3.scale.category20c();
var data1 = data.children;
canvas.selectAll('text')
.data(data1)
.enter()
.append('text')
.attr('x', function (d) { return 2; })
.attr('y', function (d, i) { return i * 15; })
.attr('fill', 'black')
.style('font-size', '12px')
.text(function (d) { return d.children ? null: d.name; })
Data I had before ↓ ↓
{
"name": "Don",
"value": 75,
"children" [
{"name": "CC", "value": 25},
{"name": "Jim", "value": 35}
]
}
When the data was in this single nested format, my code worked perfectly, but when I did double nest on it, it no longer works
You need a recursive function for this --
function getNames(d) {
return d.children ? d.children.map(getNames) : d.name;
}
This will return a nested list with the names of the elements that have no children.

Resources