(译)理解D3数据绑定

原文连接git

本人所有译文地址github

当你想要使用D3绘制散点图时,你须要在图中建立多个circle来表达你的数据信息。这时你会发现D3根本没有给你一个建立多个DOM元素的原生方法。数组

虽然它为咱们提供了.append这个方法来建立单个元素。app

svg.append('circle')
    .attr("cx", d.x)
    .attr("cy", d.y)
    .attr("r", 2.5)
复制代码

但这样每次只能建立一个circle元素,然而咱们须要一堆圆来传达数据内容。在你想要使用for循环或者暴力解决这个问题前,请理解下面例子中的链式方法的意义。svg

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元素,赋值xy属性定位到对应位置。在上面的代码中selectAll('circle')作了什么?为何咱们须要选择不存在的元素来建立新的元素?spa

这是约定俗成的写法,与其告诉D3如何来作事,不如直接说你想要什么。咱们想要circle元素来对应数据信息,每一个圆对应一份数据元素。为此咱们告诉D3咱们须要一个与数据对应的cirlce元素选择集,而不是要求D3建立circle元素。这个思想就是咱们本次所要说明的数据绑定翻译

IMAGE

当数据绑定到已存在元素上时,会建立update选择集。其他未被绑定到元素上的数据会建立enter选择集,表示缺失的元素。一样,已存在且未被绑定到数据的元素会返回exit选择集,一般表示须要被删除的元素。code

下面咱们经过解释代码来一步步说明enter-append模式数据绑定的意义:cdn

  1. 首先,svg.selectAll('circle')返回一个全新的空选择集,由于SVG容器中是空的,这个选择集的父元素节点就是SVG容器自己。
  2. 接着这个选择集与一个数组进行数据绑定,返回三个表示三种状态的新选择集:enterupdateexit。由于这些选择集如今是空的,因此返回的updateexit也是空的。可是由于已经绑定数组了,因此此时enter选择集包含对应每一个数据元素的占位符。
  3. 当执行selection.data方法时会返回update选择集,enterexit选择集不会返回。执行selection.enter则会返回对应的enter选择集。
  4. enter选择集上执行selection.append方法会在SVG容器中添加缺失的元素。如今在SVG容器中,每一个数据项都有一个对应的circle元素存在了。

数据绑定的本质是先声明选择集和数据之间的关系,而后经过enterupdateexit三个状态来具体实现这个关系。blog

为何这么麻烦?就不能提供一个直接建立多元素的原生方法吗?数据绑定的好处在于它能够泛化。当以上代码只是处理了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; });
复制代码

每当运行此代码时,它将从新计算数据绑定并维护元素和数据之间所需的对应关系。若是此时新数据集数量少于老数据集时,剩余的元素将出如今exit选择集当中而且会被删除。若是新数据集中元素数量多于老数据集时,enter选择集会为这些数据生成占位符,并建立对应的circle元素。若是新数据集和老数据集数量相同,则现有元素会更新到新数据集对应的位置,没有元素增减。

以数据绑定的思想来编写意味着你的代码更具备声明性:你能够处理这三种状态无需任何条件语句或循环。相反,你能够描述元素应该如何与数据相对应。若是返回的enterupdateexit选择集为空,对应的代码是不会执行的。

若是有须要,数据绑定还容许你操做元素为特定状态。好比你能够设定给enter选择集的元素设定属性(例如圆半径,定义'r'属性)。

circle.enter().append("circle")
    .attr("r", 0)
  .transition()
    .attr("r", 2.5);
复制代码

后记

本文翻译自D3做者Mike Bostock2012年的博文,翻译本文的目的是但愿能够从做者自己的角度来理解为何要用绑定数据和元素的方式来完成建立多SVG元素的操做。

相关文章
相关标签/搜索