d3.js:用<g>分组(数据连接进入/更新/退出循环)

时间:2017-04-08 16:57:24

标签: javascript d3.js svg

我做了一个JSFiddle来直观地解释我的问题:https://jsfiddle.net/nph/poyxrmn7/

我正在尝试使用&lt; g&gt;我的d3代码中的元素有效地以一种与转换一起使用的方式移动对象组。

例如,我正在尝试制作带有标记点的图形。我可以这样做,它的工作原理:

var labeledCircles1 = function(data){
  var svg = d3.select('svg');

  var circles = svg.selectAll('circle')
    .data(data);

  circles.enter().append('circle')
  circles.exit().remove()
  circles
    .attr('cx', function(d,i){ return i; })
    .attr('cy', function(d){ return d; })
    .attr('r', 10)

  var texts = svg.selectAll('text')
    .data(data)

  texts.enter().append('text')
  texts.exit().remove()
  texts
    .text(function(d){ return d; })
    .attr('x', function(d,i){ return i; })
    .attr('y', function(d){ return d; })
    .attr('dy', -10)
};

输出如下内容:

<svg>
  <circle cx="0" cy="10" r="10"></circle>
  <circle cx="1" cy="30" r="10"></circle>
  <text x="0" y="10" dy="-10">10</text>
  <text x="1" y="30" dy="-10">30</text>
</svg>

但这涉及到重复自我,如果我要为每一点添加更多元素,我将不得不重复自己。它也不会在生成的svg中逻辑地对元素进行分组,如上所示。

我希望能够只指定一次位置,并使这些组更符合逻辑。我想要输出这个的代码:

<svg>
  <g transform="translate(0,10)">
    <circle r="10"></circle>
    <circle r="10"></circle>
  </g>
  <g transform="translate(1,30)">
    <text dy="-10">10</text>
    <text dy="-10">30</text>
  </g>
</svg>

但我无法弄清楚如何去做。如何开始足够清楚:

var svg = d3.select('svg');

var groups = svg.selectAll('.group')
  .data(data)

groups.enter().append('g')
  .attr('class', 'group')
groups.exit().remove();
groups
  .attr('transform', function(d,i){
    var x = i * 20 + 50;
    var y = d + 20;
    return 'translate(' + x + ',' + y + ')';
  })

但是我不确定如何从那里开始。

如果我追加到groups,它第一次有效,但是当我更改数据集时,它会重新绘制我的circletext元素:

groups.append('circle')
  .attr('r', 10)

groups.append('text')
  .text(function(d) { return d; })
  .attr('dy', -10);

但如果我对群组进行selectAll,那么(当然)它根本就不会绘制元素。

我确定我有一些简单的遗漏,但我不知道是什么。

(这似乎很可能是重复,但我无法找到其他人解决这个一般性问题。)

2 个答案:

答案 0 :(得分:1)

https://jsfiddle.net/guanzo/poyxrmn7/1/

您需要在嵌套选择内继续执行数据连接。也就是说,圈子和文本的数据连接。你每次都要添加一个新的圆圈,这就是重新绘制它的原因。

var circles = groups.selectAll('circle')
    .data(d=>[d])

  circles.enter().append('circle')
  circles.attr('r', 10)
        .attr('cx', 0)
        .attr('cy', 0)

答案 1 :(得分:1)

如果您想一次添加数据,那么简单的方法就是

 public String toString() {
    int namePad = 10-name.length();
    return String.format(id + " -" + " %-5s" + "%10s" , name, "");
}

和js功能

All customers:
1 - Bill Gates          *// padding all the strings to here
2 - Trump           *  
3 - Tali           *            
4 - James Bond          *