Thinking with Joins

作者: 雷朝建 | 来源:发表于2018-04-21 08:30 被阅读0次

    Joins

    在D3中, 我们是动态创建dom元素。一般可以使用append来创建单一元素:

    const svg = d3.select("svg");
    svg.append("circle").attrs({ cx: 5, cy: 5, r: 2.5 });
    

    而如果要根据数组进行批量创建dom, 则需要以下写法:

    const svg = d3.select("svg");
    svg.selectAll('circle').data([20, 30, 40])
      .enter().append('circle')
      .attrs({ cx: d => d, cy: d => d, r: 5 });
    

    而这里所有的疑惑, 都可使用下图进行解答:


    image.png
    • 首先, 我们使用svg.selectAll('circle')产生一组空的选择器。
    • 选择器选择和数据进行绑定,这时候会产生三个操作:enter,update和exit。依据数据数据,enter依次对应数组中的每个元素,使用append产生update效果,在循环结束后,使用exit退出。

    Key Function

    一般情况下,我们使用data时候,要保证数组数据的顺序。如果是数组,则默认索引。如果数组的元素为一个字典,则需要提供一个key(因为字典是无序的)。
    考虑以下的代码:

    const otherData = [{value: 65}, {value: 35}, {value: 95}];
    const svg = d3.select("svg");
    svg.selectAll('circle').data(otherData)
      .enter().append('circle')
      .attrs({ cx: d => d.value, cy: d => d.value + 100, r: 5 });
    

    这样会在界面上生成三个circle(图1)。虽然字典是无序的,但是不需要和已绘制的circle进行匹配,所以不需要key function.

    1.png

    在上述代码前面增加以下代码:

    svg.selectAll('circle').data(data)
      .enter().append('circle')
      .attrs({ cx: d => d, cy: d => d, r: 5 });
    

    这样会生成新的三个circle,图1的circle消失了。这是因为存在图1的代码情况下,图2的代码需要key function明确保证数组的顺序,否则无法绘图。
    当我们加入:

    .data(otherData, d => d.value)
    

    后,图1图2均显示出来。

    1.png

    Enter, Update and Exit

    Update: 提供数据,存在匹配的元素
    Enter: 提供数据,不存在匹配的元素。
    Exit: 提供元素,没有匹配的数据。

    const data = [35, 65, 95];
    const divs = d3.select('.chart').selectAll('p').data(data);
    divs.enter().append('p').text(d => d);
    
    const d1 = d3.select('.chart').selectAll('p').data([35, 65]);
    d1.exit().remove();
    
    • 第一个divs,提供了update/enter的说明。
    • 而d1中,由于只提供了前两个数据,经过exit.remove后,会删除第三条数据。
    • 假设我们编写如下的代码(d1将做无用功),将不匹配的数据重新加入到页面中,则页面依旧保留三条数据:
        d1.exit().enter().append('p').text(d => d);
    

    相关文章

      网友评论

        本文标题:Thinking with Joins

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