Reputation: 23
I'm creating a small dashboard in D3 where: when a slice of a donut chart is clicked, an adjacent line chart will be updated. The code is loosely based on this block http://bl.ocks.org/diethardsteiner/3287802.
Here is a JSFiddle of what I have now and the issue: https://jsfiddle.net/394mLyz9/
If you scroll to the end of the fiddle, you'll find the 'update' code as follows:
function updateLineChart(group, colorChosen) {
var basics = dsLineChartBasics();
var margin = basics.margin,
width = basics.width,
height = basics.height;
var currentDatasetLineChart = datasetLineChartChosen(group);
var dataNest1 = d3.nest()
.key(function(d) {return d.group2;})
.entries(currentDatasetLineChart);
console.log(dataNest1);
console.log(currentDatasetLineChart);
var xScale = d3.scale.linear()
.range([0, width])
.domain(d3.extent(currentDatasetLineChart, function(d) { return d.category; }));
var yScale = d3.scale.linear()
.range([height, 0])
.domain([0, d3.max(currentDatasetLineChart, function(d) { return d.measure; })]);
var line = d3.svg.line()
.interpolate("basis")
.x(function(d, i) { return xScale(d.category); })
.y(function(d) { return yScale(d.measure); });
var svg = d3.select("#lineChart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
var plot = svg.selectAll("plot")
.data(dataNest1)
.enter()
.append("g")
.append("path")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.attr("class", "line")
.attr("d", function(d) { return line(d.values); })
.style("stroke", colorChosen);
//plot.exit().remove();
}
As you'll notice, when a pie slice is clicked, it will create new line chart under the existing one rather than updating the existing one. I've read though the general update pattern tutorials and have still had little success. Any help would be appreciated.
Upvotes: 2
Views: 539
Reputation: 108512
First, you are doing way too much work in your update function. If you increase the scope of a few of your variables, you don't need to recreate them on each update. svg
, xScale
, yScale
, margins
and line
are all things your initial draw and updates can share.
Second, while the update pattern is important, in this situation, you aren't really updating a plot with new data, you are creating a whole new plot with all new data. With that in mind, I'd just dump the contents of the SVG and re-add your lines.
Line Chart Function:
// increase the scope of these
var margin, line, svg, xScale, yScale;
function lineChart() {
var basics = dsLineChartBasics();
// declared above
margin = basics.margin,
...
// declared above
xScale = d3.scale.linear()
...
}
Update Chart Function:
function updateLineChart(group, colorChosen) {
var currentDatasetLineChart = datasetLineChartChosen(group);
...
// adjust xScale based on new data
xScale.domain(d3.extent(currentDatasetLineChart, function(d) {
return d.category;
}));
// adjust yScale based on new data
yScale.domain([0, d3.max(currentDatasetLineChart, function(d) {
return d.measure;
})]);
// remove contents of svg
svg.selectAll("*").remove();
// replot
var plot = svg.selectAll("g") //<-- don't use "plot" here it has no meaning
.data(dataNest1)
...
}
Full code example:
<!DOCTYPE html>
<html>
<head>
<script data-require="[email protected]" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
<style>
#chart-container {
float: left;
}
.line {
fill: none;
stroke-width: 3px;
}
#pieChart {
float: left;
width: 50%;
}
#lineChart {
width: 50%;
float: right;
}
</style>
</head>
<body>
<div id="pieChart"></div>
<div id="lineChart"></div>
<script>
function pieChart() {
var dataset = [{
category: "A",
measure: 3270
}, {
category: "B",
measure: 19309
}, {
category: "C",
measure: 13120
}, ];
var width = 350,
height = 350,
outerRadius = Math.min(width, height) / 2,
innerRadius = outerRadius * .5,
color = d3.scale.category20();
var svg = d3.select("#chart-container").append("svg")
.attr("width", width)
.attr("height", height)
.attr("id", "chart");
var vis = d3.select("#pieChart")
.append("svg:svg")
.data([dataset])
.attr("width", width)
.attr("height", height)
.append("svg:g")
.attr("transform", "translate(" + outerRadius + "," + outerRadius + ")");
var arc = d3.svg.arc()
.outerRadius(outerRadius).innerRadius(innerRadius);
var pie = d3.layout.pie()
.value(function(d) {
return d.measure;
});
var arcs = vis.selectAll("g")
.data(pie)
.enter()
.append("svg:g")
.on("click", change);
arcs.append("svg:path")
.attr("fill", function(d, i) {
return color(i);
})
.attr("d", arc);
//change event for line visualization
function change(d, i) {
updateLineChart(d.data.category, color(i));
}
}
pieChart();
var datasetLineChart = [
//0
{
"group": "All",
"category": 0,
"measure": 171,
"group2": 0
}, {
"group": "All",
"category": 25,
"measure": 191,
"group2": 0
}, {
"group": "All",
"category": 50,
"measure": 239,
"group2": 0
}, {
"group": "All",
"category": 75,
"measure": 1212,
"group2": 0
}, {
"group": "All",
"category": 100,
"measure": 1773,
"group2": 0
}, {
"group": "All",
"category": 125,
"measure": 3866,
"group2": 0
}, {
"group": "All",
"category": 150,
"measure": 9092,
"group2": 0
}, {
"group": "All",
"category": 175,
"measure": 6973,
"group2": 0
}, {
"group": "All",
"category": 200,
"measure": 11717,
"group2": 0
},
//1
{
"group": "All",
"category": 0,
"measure": 180,
"group2": 1
}, {
"group": "All",
"category": 25,
"measure": 188,
"group2": 1
}, {
"group": "All",
"category": 50,
"measure": 248,
"group2": 1
}, {
"group": "All",
"category": 75,
"measure": 950,
"group2": 1
}, {
"group": "All",
"category": 100,
"measure": 1607,
"group2": 1
}, {
"group": "All",
"category": 125,
"measure": 3961,
"group2": 1
}, {
"group": "All",
"category": 150,
"measure": 8405,
"group2": 1
}, {
"group": "All",
"category": 175,
"measure": 17304,
"group2": 1
}, {
"group": "All",
"category": 200,
"measure": 24097,
"group2": 1
},
//20
{
"group": "All",
"category": 0,
"measure": 215,
"group2": 20
}, {
"group": "All",
"category": 25,
"measure": 369,
"group2": 20
}, {
"group": "All",
"category": 50,
"measure": 1311,
"group2": 20
}, {
"group": "All",
"category": 75,
"measure": 3323,
"group2": 20
}, {
"group": "All",
"category": 100,
"measure": 5766,
"group2": 20
}, {
"group": "All",
"category": 125,
"measure": 13473,
"group2": 20
}, {
"group": "All",
"category": 150,
"measure": 21960,
"group2": 20
}, {
"group": "All",
"category": 175,
"measure": 28305,
"group2": 20
}, {
"group": "All",
"category": 200,
"measure": 34886,
"group2": 20
},
//100
{
"group": "All",
"category": 0,
"measure": 228,
"group2": 100
}, {
"group": "All",
"category": 25,
"measure": 389,
"group2": 100
}, {
"group": "All",
"category": 50,
"measure": 1981,
"group2": 100
}, {
"group": "All",
"category": 75,
"measure": 3646,
"group2": 100
}, {
"group": "All",
"category": 100,
"measure": 6846,
"group2": 100
}, {
"group": "All",
"category": 125,
"measure": 17987,
"group2": 100
}, {
"group": "All",
"category": 150,
"measure": 23910,
"group2": 100
}, {
"group": "All",
"category": 175,
"measure": 29333,
"group2": 100
}, {
"group": "All",
"category": 200,
"measure": 35154,
"group2": 100
},
//0
{
"group": "A",
"category": 0,
"measure": 16,
"group2": 0
}, {
"group": "A",
"category": 25,
"measure": 18,
"group2": 0
}, {
"group": "A",
"category": 50,
"measure": 22,
"group2": 0
}, {
"group": "A",
"category": 75,
"measure": 132,
"group2": 0
}, {
"group": "A",
"category": 100,
"measure": 194,
"group2": 0
}, {
"group": "A",
"category": 125,
"measure": 386,
"group2": 0
}, {
"group": "A",
"category": 150,
"measure": 865,
"group2": 0
}, {
"group": "A",
"category": 175,
"measure": 761,
"group2": 0
}, {
"group": "A",
"category": 200,
"measure": 1214,
"group2": 0
},
//1
{
"group": "A",
"category": 0,
"measure": 17,
"group2": 1
}, {
"group": "A",
"category": 25,
"measure": 17,
"group2": 1
}, {
"group": "A",
"category": 50,
"measure": 24,
"group2": 1
}, {
"group": "A",
"category": 75,
"measure": 104,
"group2": 1
}, {
"group": "A",
"category": 100,
"measure": 174,
"group2": 1
}, {
"group": "A",
"category": 125,
"measure": 339,
"group2": 1
}, {
"group": "A",
"category": 150,
"measure": 787,
"group2": 1
}, {
"group": "A",
"category": 175,
"measure": 1583,
"group2": 1
}, {
"group": "A",
"category": 200,
"measure": 2198,
"group2": 1
},
//20
{
"group": "A",
"category": 0,
"measure": 20,
"group2": 20
}, {
"group": "A",
"category": 25,
"measure": 34,
"group2": 20
}, {
"group": "A",
"category": 50,
"measure": 142,
"group2": 20
}, {
"group": "A",
"category": 75,
"measure": 340,
"group2": 20
}, {
"group": "A",
"category": 100,
"measure": 585,
"group2": 20
}, {
"group": "A",
"category": 125,
"measure": 1233,
"group2": 20
}, {
"group": "A",
"category": 150,
"measure": 1998,
"group2": 20
}, {
"group": "A",
"category": 175,
"measure": 2578,
"group2": 20
}, {
"group": "A",
"category": 200,
"measure": 3278,
"group2": 20
},
//100
{
"group": "A",
"category": 0,
"measure": 20,
"group2": 100
}, {
"group": "A",
"category": 25,
"measure": 34,
"group2": 100
}, {
"group": "A",
"category": 50,
"measure": 211,
"group2": 100
}, {
"group": "A",
"category": 75,
"measure": 363,
"group2": 100
}, {
"group": "A",
"category": 100,
"measure": 667,
"group2": 100
}, {
"group": "A",
"category": 125,
"measure": 1593,
"group2": 100
}, {
"group": "A",
"category": 150,
"measure": 2111,
"group2": 100
}, {
"group": "A",
"category": 175,
"measure": 2636,
"group2": 100
}, {
"group": "A",
"category": 200,
"measure": 3270,
"group2": 100
},
//0
{
"group": "C",
"category": 0,
"measure": 37,
"group2": 0
}, {
"group": "C",
"category": 25,
"measure": 45,
"group2": 0
}, {
"group": "C",
"category": 50,
"measure": 52,
"group2": 0
}, {
"group": "C",
"category": 75,
"measure": 413,
"group2": 0
}, {
"group": "C",
"category": 100,
"measure": 527,
"group2": 0
}, {
"group": "C",
"category": 125,
"measure": 1252,
"group2": 0
}, {
"group": "C",
"category": 150,
"measure": 2914,
"group2": 0
}, {
"group": "C",
"category": 175,
"measure": 2109,
"group2": 0
}, {
"group": "C",
"category": 200,
"measure": 3687,
"group2": 0
},
//1
{
"group": "C",
"category": 0,
"measure": 42,
"group2": 1
}, {
"group": "C",
"category": 25,
"measure": 43,
"group2": 1
}, {
"group": "C",
"category": 50,
"measure": 52,
"group2": 1
}, {
"group": "C",
"category": 75,
"measure": 317,
"group2": 1
}, {
"group": "C",
"category": 100,
"measure": 491,
"group2": 1
}, {
"group": "C",
"category": 125,
"measure": 1225,
"group2": 1
}, {
"group": "C",
"category": 150,
"measure": 2723,
"group2": 1
}, {
"group": "C",
"category": 175,
"measure": 6004,
"group2": 1
}, {
"group": "C",
"category": 200,
"measure": 8668,
"group2": 1
},
//20
{
"group": "C",
"category": 0,
"measure": 47,
"group2": 20
}, {
"group": "C",
"category": 25,
"measure": 80,
"group2": 20
}, {
"group": "C",
"category": 50,
"measure": 422,
"group2": 20
}, {
"group": "C",
"category": 75,
"measure": 1039,
"group2": 20
}, {
"group": "C",
"category": 100,
"measure": 1826,
"group2": 20
}, {
"group": "C",
"category": 125,
"measure": 4537,
"group2": 20
}, {
"group": "C",
"category": 150,
"measure": 7782,
"group2": 20
}, {
"group": "C",
"category": 175,
"measure": 10493,
"group2": 20
}, {
"group": "C",
"category": 200,
"measure": 13122,
"group2": 20
},
//100
{
"group": "C",
"category": 0,
"measure": 51,
"group2": 100
}, {
"group": "C",
"category": 25,
"measure": 93,
"group2": 100
}, {
"group": "C",
"category": 50,
"measure": 664,
"group2": 100
}, {
"group": "C",
"category": 75,
"measure": 1171,
"group2": 100
}, {
"group": "C",
"category": 100,
"measure": 2103,
"group2": 100
}, {
"group": "C",
"category": 125,
"measure": 6414,
"group2": 100
}, {
"group": "C",
"category": 150,
"measure": 8713,
"group2": 100
}, {
"group": "C",
"category": 175,
"measure": 10830,
"group2": 100
}, {
"group": "C",
"category": 200,
"measure": 13120,
"group2": 100
},
//0
{
"group": "B",
"category": 0,
"measure": 110,
"group2": 0
}, {
"group": "B",
"category": 25,
"measure": 123,
"group2": 0
}, {
"group": "B",
"category": 50,
"measure": 155,
"group2": 0
}, {
"group": "B",
"category": 75,
"measure": 773,
"group2": 0
}, {
"group": "B",
"category": 100,
"measure": 1093,
"group2": 0
}, {
"group": "B",
"category": 125,
"measure": 2307,
"group2": 0
}, {
"group": "B",
"category": 150,
"measure": 5579,
"group2": 0
}, {
"group": "B",
"category": 175,
"measure": 3969,
"group2": 0
}, {
"group": "B",
"category": 200,
"measure": 6754,
"group2": 0
},
//1
{
"group": "B",
"category": 0,
"measure": 114,
"group2": 1
}, {
"group": "B",
"category": 25,
"measure": 112,
"group2": 1
}, {
"group": "B",
"category": 50,
"measure": 163,
"group2": 1
}, {
"group": "B",
"category": 75,
"measure": 576,
"group2": 1
}, {
"group": "B",
"category": 100,
"measure": 994,
"group2": 1
}, {
"group": "B",
"category": 125,
"measure": 2422,
"group2": 1
}, {
"group": "B",
"category": 150,
"measure": 5140,
"group2": 1
}, {
"group": "B",
"category": 175,
"measure": 10315,
"group2": 1
}, {
"group": "B",
"category": 200,
"measure": 13675,
"group2": 1
},
//20
{
"group": "B",
"category": 0,
"measure": 139,
"group2": 20
}, {
"group": "B",
"category": 25,
"measure": 243,
"group2": 20
}, {
"group": "B",
"category": 50,
"measure": 799,
"group2": 20
}, {
"group": "B",
"category": 75,
"measure": 2027,
"group2": 20
}, {
"group": "B",
"category": 100,
"measure": 3507,
"group2": 20
}, {
"group": "B",
"category": 125,
"measure": 8148,
"group2": 20
}, {
"group": "B",
"category": 150,
"measure": 12621,
"group2": 20
}, {
"group": "B",
"category": 175,
"measure": 15735,
"group2": 20
}, {
"group": "B",
"category": 200,
"measure": 18961,
"group2": 20
},
//100
{
"group": "B",
"category": 0,
"measure": 149,
"group2": 100
}, {
"group": "B",
"category": 25,
"measure": 259,
"group2": 100
}, {
"group": "B",
"category": 50,
"measure": 1189,
"group2": 100
}, {
"group": "B",
"category": 75,
"measure": 2213,
"group2": 100
}, {
"group": "B",
"category": 100,
"measure": 4311,
"group2": 100
}, {
"group": "B",
"category": 125,
"measure": 10631,
"group2": 100
}, {
"group": "B",
"category": 150,
"measure": 13645,
"group2": 100
}, {
"group": "B",
"category": 175,
"measure": 16443,
"group2": 100
}, {
"group": "B",
"category": 200,
"measure": 19309,
"group2": 100
}
];
// set initial group value
var group = "All";
function datasetLineChartChosen(group) {
var ds = [];
for (x in datasetLineChart) {
if (datasetLineChart[x].group == group) {
ds.push(datasetLineChart[x]);
}
}
return ds;
}
var firstDatasetLineChart = datasetLineChartChosen(group);
function dsLineChartBasics() {
var margin = {
top: 0,
right: 0,
bottom: 0,
left: 0
},
width = 500 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
return {
margin: margin,
width: width,
height: height
}
}
var margin, line, svg, xScale, yScale;
function lineChart() {
var basics = dsLineChartBasics();
margin = basics.margin,
width = basics.width,
height = basics.height;
var dataNest = d3.nest()
.key(function(d) {
return d.group2;
})
.entries(firstDatasetLineChart);
xScale = d3.scale.linear()
.range([0, width])
.domain(d3.extent(datasetLineChart, function(d) {
return d.category;
}));
yScale = d3.scale.linear()
.range([height, 0])
.domain([0, d3.max(datasetLineChart, function(d) {
return d.measure;
})]);
line = d3.svg.line()
.interpolate("basis")
.x(function(d) {
return xScale(d.category);
})
.y(function(d) {
return yScale(d.measure);
});
svg = d3.selectAll("#lineChart")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.selectAll("plot")
.data(dataNest)
.enter()
.append("path")
.attr("class", "line")
.attr("d", function(d) {
return line(d.values);
})
.style("stroke", "lightGrey");
}
lineChart();
function updateLineChart(group, colorChosen) {
var currentDatasetLineChart = datasetLineChartChosen(group);
var dataNest1 = d3.nest()
.key(function(d) {
return d.group2;
})
.entries(currentDatasetLineChart);
console.log(dataNest1);
console.log(currentDatasetLineChart);
xScale.domain(d3.extent(currentDatasetLineChart, function(d) {
return d.category;
}));
yScale.domain([0, d3.max(currentDatasetLineChart, function(d) {
return d.measure;
})]);
svg.selectAll("*").remove();
var plot = svg.selectAll("g")
.data(dataNest1)
.enter()
.append("g")
.append("path")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.attr("class", "line")
.attr("d", function(d) {
return line(d.values);
})
.style("stroke", colorChosen);
//plot.exit().remove();
}
</script>
</body>
</html>
Upvotes: 1