2

I create a group with data values:

var group = svg.append("g");
group.data([{color : "green", opacity: 0.3 }]);

If I want to update these values, do I need to set a new data array?

group.data([{color : "blue", opacity: 0.3 }]);

Or can I somehow iterate and update the values inside the group, like:

group.data.foreach(d, function() { return d.color = "blue"; })

or

group.data.foreach(d, function() { return d.opacity += 0.5; })

My use case is that I have a group with a rectangle and a circle. And the group has data in it.

var group = svg.append("g");
group.data([{color : "green", opacity: 0.3 }]);

var line = group.append("rect");
line.attr("x", self.xWorldToGraph(xx) - self.lineWidth / 2)
  .attr("y", self.yWorldToGraph(yy))
  .attr("width", self.lineWidth)
  .attr("height", height)
  .style("stroke", function(d) { return d.color; })
  .style('stroke-opacity', function(d) { return d.opacity; })

group.append("circle")
  .attr("cx", self.xWorldToGraph(xx))
  .attr("cy", self.yWorldToGraph(yy))
  .attr("r", 50)
  .style("stroke", function(d) { return d.color; })
  .style('stroke-opacity', function(d) { return d.opacity; })

Now I want to update the group color so the circle and rectangle also change color.

  • This will do group.data().foreach(d, function() { return d.color = "blue"; }) – Cyril Cherian Dec 09 '15 at 12:35
  • How do I tell d3 that the value in data has been updated? – Taufik Hidayat Dec 09 '15 at 12:56
  • I will not be able to answer that as there are many ways i think you need some insight here http://bl.ocks.org/mbostock/3808218 – Cyril Cherian Dec 09 '15 at 13:14
  • 1
    You "tell" `d3` the data has changed by calling the `.style` functions again. Here's an [example](http://plnkr.co/edit/pGFoW78zM49Dxlw8Z6k2?p=preview) using @cyril `forEach`. – Mark Dec 09 '15 at 14:16
  • Thank you:) everything is working now – Taufik Hidayat Dec 09 '15 at 14:40
  • @Mark Do you want to add this as an answer? – Lars Kotthoff Dec 09 '15 at 18:24
  • @LarsKotthoff, I can, it seemed like low hanging fruit for a full answer. The problem with the enter, update, exit pattern (and closing questions about it as a duplicate) is that most people don't get it until they see it with their data in a live example. I feel like all I do is explain it time and time again on here. – Mark Dec 09 '15 at 18:48
  • @Mark Yep, I think we've all been there :) Still it's better to answer these questions that aren't exact duplicates simply so that others will see the answer. – Lars Kotthoff Dec 09 '15 at 18:56

1 Answers1

1

d3 won't "auto" redraw after you switch out data. You have to "tell" it the data has changed by calling the .style functions again (in the enter, update, exit pattern, this is an update).

Here's an example using your code:

<!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>
</head>

<body>
  <script>
    var svg = d3.select('body')
      .append('svg')
      .attr('width', 500)
      .attr('height', 500);

    var group = svg.append("g");
    
    group.data([{
      color: "green",
      opacity: 0.3
    }]);

    group.append("circle")
      .attr("cx", 100)
      .attr("cy", 100)
      .attr("r", 50)
      .style("stroke-width", 30)
      .style("stroke", function(d) {
        return d.color;
      })
      .style('stroke-opacity', function(d) {
        return d.opacity;
      });
      
    var colors = d3.scale.category20();
    var i = 0;

    function changeColor() {
      group.data().forEach(function(d) {
        d.color = colors(i);
      });
      group.selectAll('circle').style("stroke", function(d) {
        return d.color;
      })
      i++;
    }

    setInterval( changeColor, 1000 );

  </script>
</body>

</html>
Mark
  • 106,305
  • 20
  • 172
  • 230