使用 D3 更新多折线图的模式
Posted
技术标签:
【中文标题】使用 D3 更新多折线图的模式【英文标题】:Update Pattern for Multi-Line Chart with D3 【发布时间】:2016-03-21 23:31:38 【问题描述】:我正在 D3 中创建一个小型仪表板,其中:单击圆环图的一部分时,将更新相邻的折线图。代码大致基于此块http://bl.ocks.org/diethardsteiner/3287802。
这是我现在所拥有的和问题的 JSFiddle:https://jsfiddle.net/394mLyz9/
如果您滚动到小提琴的末尾,您会发现“更新”代码如下:
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();
您会注意到,当一个饼图被点击时,它会在现有的下方创建新的折线图,而不是更新现有的折线图。我已经阅读了一般更新模式教程,但仍然收效甚微。任何帮助将不胜感激。
【问题讨论】:
【参考方案1】:首先,您在更新功能中做了太多工作。如果您增加了一些变量的范围,则无需在每次更新时重新创建它们。 svg
、xScale
、yScale
、margins
和 line
都是您可以分享的初始抽奖和更新内容。
其次,虽然更新模式很重要,但在这种情况下,您并没有真正用新数据更新绘图,而是用所有新数据创建了一个全新的绘图。考虑到这一点,我将转储 SVG 的内容并重新添加您的行。
折线图功能:
// 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()
...
更新图表功能:
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)
...
完整代码示例:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3@3.5.3" 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>
【讨论】:
正是我需要的建议,感谢您提供的其他建议!以上是关于使用 D3 更新多折线图的模式的主要内容,如果未能解决你的问题,请参考以下文章