面向对象的D3 JS - 如何选择对象?

时间:2016-11-18 05:07:18

标签: javascript oop d3.js

设置我的D3项目,它将在屏幕上设置多个形状的动画(Org类)。我正在尝试维护面向对象的范例,并利用D3动画(https://jrue.github.io/coding/2014/lesson07/)。

请考虑以下代码:

function test() {

    class Org {
        constructor(_width, _height) {
            this.width = _width;
            this.height = _height;
        }
    }
    var orgs = [];
    var canvas = d3.select('body')
            .append('svg')
            .attr('width', screen.width)
            .attr('height', screen.height);

    for (var x = 0; x < 100; x++) {
        var circle = new Org(Math.random()*screen.width, Math.random()*screen.height);
        orgs.push(circle);
        canvas.append('circle')
            .attr('cx', circle.width)
            .attr('cy', circle.height)
            .attr('r', 5)
            .attr('fill', 'pink');
    }

    for (var b = 0; b < orgs.length; b++) {
        circle.transition().attr('cx', 0); //DOES NOT WORK
    }
}

显然,注释行会抛出错误,因为transition()属于D3,而不属于我的类。如何选择这些对象并为其设置动画?

2 个答案:

答案 0 :(得分:2)

也许给他们一个id并用d3选择它们?

首先给圈子一个id:

var obj = JSON.parse(response)

if(typeof obj._body == "string") {
    obj._body = JSON.parse(obj._body)
}

console.log(obj);

然后按ID:

选择它们
for (var x = 0; x < 100; x++) {
        var circle = new Org(Math.random()*screen.width,    Math.random()*screen.height);
        orgs.push(circle);
        canvas.append('circle')
            .attr('id', "myCircle_" + x)
            .attr('cx', circle.width)
            .attr('cy', circle.height)
            .attr('r', 5)
            .attr('fill', 'pink');
    }

答案 1 :(得分:2)

您的代码不是D3- ish ,这使得实现目标变得很麻烦。请记住,D3本质上是关于数据驱动的文档,因此,data binding是其核心。理解这个概念以充分利用这个库是至关重要的。在相应地重构代码时,解决方案变得非常明显。

也就是说,在处理D3时,使用for循环总是看起来很可疑。很少需要使用这些循环,因为这是由D3的内部工作处理的。在不破坏OO方法的情况下,您可以将orgs数组绑定到选区,并利用D3实现其魔力:

var circles = canvas.selectAll("circle")
  .data(orgs)
  .enter().append('circle')
    .attr('cx', d => d.width )
    .attr('cy', d => d.height )
    .attr('r', 5)
    .attr('fill', 'pink');

这会将圆圈添加到您的选择中,对应于Org数组中使用orgs绑定到选区的所有.data(orgs)个实例。上述陈述还保留了对circles变量中包含所有新添加的圆的选择的引用,您可以将其用于以后的操作。

此参考在进行转换时非常方便:

circles
  .transition()
    .attr('cx', 0);

看看下面的代码片段,它与您的方法相同,但是以D3的方式进行。

&#13;
&#13;
class Org {
  constructor(_width, _height) {
    this.width = _width;
    this.height = _height;
  }
}

var orgs = d3.range(100).map(function() {
  return new Org(Math.random() * screen.width, Math.random() * screen.height);
});

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

var circles = canvas.selectAll("circle")
  .data(orgs)
  .enter().append('circle')
    .attr('cx', d => d.width )
    .attr('cy', d => d.height )
    .attr('r', 5)
    .attr('fill', 'pink');

circles
  .transition()
    .attr('cx', 0);
&#13;
<script src="https://d3js.org/d3.v4.js"></script>
&#13;
&#13;
&#13;

您可能希望查看有关此概念的一些教程,以获得更深入的介绍:

  1. Three Little Circles
  2. Let’s Make a Bar Chart, Parts III&amp; III
  3. Thinking with Joins
  4. How Selections Work(高级)