美文网首页
Tinking with Joins(D3.js)

Tinking with Joins(D3.js)

作者: 高级程序狗 | 来源:发表于2020-04-22 15:57 被阅读0次

    假如你正在使用D3开发一个散点图,需要创建一些SVG circle 元素来展示你的数据。你可能会惊讶的发现D3并不像原始那样创建多个DOM元素。

    下面是一个用来创建单个元素的append方法:

    svg.append("circle")
        .attr("cx", d.x)
        .attr("cy", d.y)
        .attr("r", 2.5);
    

    这只是一个圆,而你想要根据数据创建更多的圆。在你使用for循环暴力解决之前,思考一下D3示例中的这个神奇的代码片段:

    svg.selectAll("circle")
      .data(data)
      .enter().append("circle")
        .attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; })
        .attr("r", 2.5);
    

    这段代码完全能够满足你的需要:它为每个数据点创建一个circle元素,使用X和Y数据属性进行定位。但是selectAll("circle")是什么意思?为什么要选择不存在的元素?

    事情是这样的。不要告诉D3如何做某事,而是告诉它你想要做什么。你想要的是根据数据画圆,每一条数据对应一个圆,而不是教D3如何创建圆。因此告诉D3圆集合应该对应数据。这个概念叫做数据联接:

    join

    从上图可以看出三种选集的关系:
    update选集:数据和已经存在的元素的交集。
    enter选集:表示未绑定的数据集合。
    exit选集:表示未绑定的元素集合。

    现在,我们可以通过数据联接来解释之前的代码片段:

    1. 首选,因为SVG容器是空的,svg.selectAll("circle")返回一个新的空选集。
    2. 然后,通过selection.data(data)方法建立了数据和元素的连接。由于还没有元素,此时updateexit为空,enter选集包含每条数据的占位符。
    3. 通过selection.enter方法获取需要创建元素的集合。
    4. 通过selection.append("circle")创建元素。

    数据联接意味着宣告元素和数据之间的关系,然后通过updateexitenter三种状态来实现这种关系。

    但是为什么搞这么麻烦?为什么不直接创建元素呢?
    数据联接的优点在于它便于选择整个集合。虽然上面的代码只处理enter选集,这对于静态可视化来说是足够的,但是你可以扩展它以支持动态可视化,只需对updateexit进行一些小的修改。这意味着您可以可视化实时数据,允许交互式探索,并在数据集之间平滑过渡

    下面是操作三种状态的一个例子:

    var circle = svg.selectAll("circle")
      .data(data);
    
    circle.exit().remove();
    circle.enter().append("circle")
        .attr("r", 2.5)
      .merge(circle)
        .attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; });
    

    每当此代码运行时,它将重新计算数据联接,并维护元素和数据之间所需的对应关系。如果新的数据集比原来的小,那么多余的元素将被删除circle.exit().remove();。如果新的数据集更大,更多的元素将被创建。如果新的数据集和旧的大小完全相同,所有元素将更新坐标,并不会删除或添加新的元素。

    数据联接意味着你的代码更具声明性:处理这三种状态时不需要任何迭代和判断,而是描述元素和数据之间的对应关系。如果updateexitenter选集为空,则不做任何处理。

    如果需要,联接还允许将操作定位到特定的状态。例如,可以在enter而不是update上设置常量属性(例如圆圈的半径,由“r”属性定义)。通过重新选择元素和最小化DOM更改,可以极大地提高呈现性能!类似地,您也可以针对特定状态的动画转换。例如,对于进入展开形式出现:

    circle.enter().append("circle")
        .attr("r", 0)
      .transition()
        .attr("r", 2.5);
    

    同理,收缩的形式移除:

    circle.exit().transition()
        .attr("r", 0)
        .remove();
    

    翻译自:https://bost.ocks.org/mike/join/

    相关文章

      网友评论

          本文标题:Tinking with Joins(D3.js)

          本文链接:https://www.haomeiwen.com/subject/ovibihtx.html