简体   繁体   中英

d3, updating multiple paths

The following code has multiple paths on a single d3.js plot. I have the initial plot working, displaying the data set d0 . It looks like this on load:

加载时显示

I would like to display the data in d1 when the button is pressed, so it should look like this:

按下按钮后应该是什么样子

What currently happens is...nothing. No errors in the console, no change to the display, and no change to the DOM (that I can see?).

I've been through a dozen code examples and tutorials and just don't see what's going wrong here. Any help would be greatly appreciated (particularly if with an explanation of what I'm conceptually missing). Thanks!

 var d0 = [{ id: "A", values: [{ x: .25, y: .9 }, { x: .75, y: 1 }] }, { id: "B", values: [{ x: .25, y: .5 }, { x: .8, y: .4 }] }, { id: "C", values: [{ x: .1, y: .1 }, { x: .9, y: .1 }] } ] var d1 = [{ id: "A", values: [{ x: 0, y: 1 }, { x: 1, y: 1 }] }, { id: "B", values: [{ x: 0, y: .5 }, { x: 1, y: .5 }] }, { id: "C", values: [{ x: 0, y: 0 }, { x: 1, y: 0 }] } ] var svg = d3.select("svg") var margin = { top: 20, right: 80, bottom: 30, left: 50 } var width = svg.attr("width") - margin.left - margin.right var height = svg.attr("height") - margin.top - margin.bottom g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")") var scaleX = d3.scaleLinear().range([0, width]).domain([0, 1]) var scaleY = d3.scaleLinear().range([height, 0]).domain([0, 1]) g.append("g") .attr("class", "axis axis--x") .attr("transform", "translate(0," + height + ")") .call(d3.axisBottom(scaleX)); g.append("g") .attr("class", "axis axis--y") .call(d3.axisLeft(scaleY)) var line = d3.line() .x(function(d) { return scaleX(dx) }) .y(function(d) { return scaleY(dy) }); var lineg = g.selectAll(".lineg") .data(d0) .enter() .append("g") .attr("class", "lineg"); lineg.append("path") .attr("class", "line") .attr("d", function(d) { return line(d.values) }) function update() { var i = g.selectAll(".lineg") .data(d1) i.enter() .append("g") .attr("class", "lineg") i.exit() .remove() g.selectAll(".line") .attr("d", function(d) { return line(d.values) }) }
 .line { fill: none; stroke: steelblue; stroke-width: 1.5px; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script> <svg width="500" height="300"></svg> <br/> <button onclick="update()">Change</button>

Every SVG element that you call .data or .datum on has an internal reference to a data object. In your update call, you updated the data of the g elements that held the lines, but never of the lines themselves.

I was able to do that with the following code:

i.select(".line")
  .datum(function(d) {
    return d;
  })
  .attr("d", function(d) {
    return line(d.values)
  })

Here, starting from the newly selected groups i , which you already gave the correct data, I select the line, and then pass it the datum object from the g directly, through the function. That way, the datum object gets updated, and calling line(d.values) now actually uses entries from d1 instead of d0 .

 var d0 = [{ id: "A", values: [{ x: .25, y: .9 }, { x: .75, y: 1 }] }, { id: "B", values: [{ x: .25, y: .5 }, { x: .8, y: .4 }] }, { id: "C", values: [{ x: .1, y: .1 }, { x: .9, y: .1 }] } ] var d1 = [{ id: "A", values: [{ x: 0, y: 1 }, { x: 1, y: 1 }] }, { id: "B", values: [{ x: 0, y: .5 }, { x: 1, y: .5 }] }, { id: "C", values: [{ x: 0, y: 0 }, { x: 1, y: 0 }] } ] var svg = d3.select("svg") var margin = { top: 20, right: 80, bottom: 30, left: 50 } var width = svg.attr("width") - margin.left - margin.right var height = svg.attr("height") - margin.top - margin.bottom g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")") var scaleX = d3.scaleLinear().range([0, width]).domain([0, 1]) var scaleY = d3.scaleLinear().range([height, 0]).domain([0, 1]) g.append("g") .attr("class", "axis axis--x") .attr("transform", "translate(0," + height + ")") .call(d3.axisBottom(scaleX)); g.append("g") .attr("class", "axis axis--y") .call(d3.axisLeft(scaleY)) var line = d3.line() .x(function(d) { return scaleX(dx) }) .y(function(d) { return scaleY(dy) }); var lineg = g.selectAll(".lineg") .data(d0) .enter() .append("g") .attr("class", "lineg"); lineg.append("path") .attr("class", "line") .attr("d", function(d) { return line(d.values) }) function update() { var i = g.selectAll(".lineg") .data(d1) i.enter() .append("g") .attr("class", "lineg") i.exit() .remove() i.select(".line") .datum(function(d) { return d; }) .attr("d", function(d) { return line(d.values) }) }
 .line { fill: none; stroke: steelblue; stroke-width: 1.5px; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script> <svg width="500" height="300"></svg> <br/> <button onclick="update()">Change</button>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM