D3:无法更新选择

时间:2017-02-02 02:41:18

标签: javascript d3.js

我的update()功能出现问题。在svg.append('rect') {}} {}} {}}} {}}} {}} {{}} {}}我在.on('click')内我只需更改数据,然后运行update()

为什么这不起作用?我如何使它工作?

  var width = 640,
      height = 480;

  var graphNodes = [
    { id: 0, x: 39, y: 343, r: 15 },
    { id: 1, x: 425, y: 38, r: 15 },
    { id: 2, x: 183, y: 417, r: 15 },
    { id: 3, x: 564, y: 31, r: 15 },
    { id: 4, x: 553, y: 351, r: 15 },
    { id: 5, x: 454, y: 298, r: 15 },
    { id: 6, x: 493, y: 123, r: 15 },
    { id: 7, x: 471, y: 427, r: 15 },
    { id: 8, x: 142, y: 154, r: 15 }
  ];

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

  svg.append('rect')
      .attr('class', 'graph')
      .attr('width', width)
      .attr('height', height)
      .attr('fill', 'lightblue')
      .attr('opacity', 0.3)
      .on('click', function(){

        graphNodes[8].id = 'hey there'; //  <----- Why doesn't this happen?

        update();
      });

  var nodeGroup = svg.selectAll('.nodes')
      .data(graphNodes, function(d){ return d.id; })
      .enter().append('g')
      .attr('class', 'node');

  nodeGroup.append('circle')
      .attr('cx', function(d) { return d.x })
      .attr('cy', function(d) { return d.y })
      .attr("r", function(d){ return d.r; })
      .attr("fill", "gray");

  nodeGroup.append('text')
      .attr("dx", function(d){ return d.x + 20; })
      .attr("dy", function(d){ return d.y + 5; })
      .text(function(d) { return d.id });

  function update() {

    if(nodeGroup){

      // Update nodes
      var node = nodeGroup.data(graphNodes, function(d){ return d.id; }),
          nodeEnter = node.enter().append('g')
              .attr('class', 'node');

      nodeEnter.append('circle')
              .attr('cx', function(d) { return d.x; })
              .attr('cy', function(d) { return d.y; })
              .attr('r', function(d){ return d.r; })
              .attr('fill', 'gray');

      nodeEnter.append('text')
          .attr("dx", function(d){ return d.x + 20; })
          .attr("dy", function(d){ return d.y + 5; })
          .text(function(d) { return d.id });

      nodeGroup = nodeEnter.merge(node);
      node.exit().remove();
    }
  }

这是fiddle

1 个答案:

答案 0 :(得分:1)

在你留给我的邮件中输入此作为评论,但这里是答案。

您需要将在输入,更新和退出时执行的操作分开。在输入时,您只想追加并设置任何永不改变的属性。在更新时,您要添加/更改文本并添加/更改半径。退出时,您将删除。在这里,我已经正确处理了输入,更新,退出范例:

  // bind the data
  var node = nodeGroup.data(graphNodes, function(d){ return d.id; }),
      // this is the enter selection
      nodeEnter = node.enter().append('g')
          .attr('class', 'node');

  // append to enter selection
  // append and set color, we never change color
  nodeEnter.append('circle')
          .attr('cx', function(d) { return d.x; })
          .attr('cy', function(d) { return d.y; })
          .attr('fill', 'gray');

  // again entering, append text and set position
  nodeEnter.append('text')
      .attr("dx", function(d){ return d.x + 20; })
      .attr("dy", function(d){ return d.y + 5; });          

  // nodeGroup is the enter + update selection
  nodeGroup = nodeEnter.merge(node);

  // change the things we want to change on every update
  nodeGroup.select("text")
    .text(function(d) { return d.text ? d.text : d.id });

  nodeGroup.select("circle")
   .attr('r', function(d){ return d.r; })

  // exit, just remove
  node.exit().remove();

运行代码:

var width = 640,
      height = 480;

  var graphNodes = [
    { id: 0, x: 39, y: 343, r: 15 },
    { id: 1, x: 425, y: 38, r: 15 },
    { id: 2, x: 183, y: 417, r: 15 },
    { id: 3, x: 564, y: 31, r: 15 },
    { id: 4, x: 553, y: 351, r: 15 },
    { id: 5, x: 454, y: 298, r: 15 },
    { id: 6, x: 493, y: 123, r: 15 },
    { id: 7, x: 471, y: 427, r: 15 },
    { id: 8, x: 142, y: 154, r: 15 }
  ];

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

  svg.append('rect')
      .attr('class', 'graph')
      .attr('width', width)
      .attr('height', height)
      .attr('fill', 'lightblue')
      .attr('opacity', 0.3)
      .on('click', function(){
        /*graphNodes.push({
          x: d3.mouse(this)[0],
          y: d3.mouse(this)[1],
          id: graphNodes.length,
          r: 15
        });*/

        graphNodes.splice(2, 1);
        
        graphNodes[Math.floor(Math.random() * graphNodes.length)].text = "Tomato!";
        
        graphNodes[Math.floor(Math.random() * graphNodes.length)].r = Math.random() * 30;
        
        update();
      });

  var nodeGroup = svg.selectAll('.nodes')
      .data(graphNodes, function(d){ return d.id; })
      .enter().append('g')
      .attr('class', 'node');

  nodeGroup.append('circle')
      .attr('cx', function(d) { return d.x })
      .attr('cy', function(d) { return d.y })
      .attr("r", function(d){ return d.r; })
      .attr("fill", "gray");

  nodeGroup.append('text')
      .attr("dx", function(d){ return d.x + 20; })
      .attr("dy", function(d){ return d.y + 5; })
      .text(function(d) { return d.id });

  function update() {
  
    if(nodeGroup){

      // Update nodes
      var node = nodeGroup.data(graphNodes, function(d){ return d.id; }),
          nodeEnter = node.enter().append('g')
              .attr('class', 'node');
      
      // this is the enter selection
      // append and set color, we never change color
      nodeEnter.append('circle')
              .attr('cx', function(d) { return d.x; })
              .attr('cy', function(d) { return d.y; })
              .attr('fill', 'gray');

      nodeEnter.append('text')
          .attr("dx", function(d){ return d.x + 20; })
          .attr("dy", function(d){ return d.y + 5; });          

      // nodeGroup is the enter + update selection
      nodeGroup = nodeEnter.merge(node);
      
      // change the things we want to change on every update
      nodeGroup.select("text")
      	.text(function(d) { return d.text ? d.text : d.id });
        
     	nodeGroup.select("circle")
     		.attr('r', function(d){ return d.r; })
      
      // exit, just remove
      node.exit().remove();
    }
  }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.min.js"></script>