资讯专栏INFORMATION COLUMN

以 Join 的方式来思考D3.js

mikasa / 2963人阅读

摘要:以的方式来思考声明原文链接来自作者译文地址如果觉得还不错不妨去给个打个比方你想用画一个散点图用每一个的元素来可视化你的数据你会惊讶的发现居然没有直接创建多个元素的方法怎么回事当然有方法你可以用来创建单个元素比如但这只是一个圆如果你想要创建很

Join 的方式来思考D3.js 声明

原文链接: 来自 D3作者 Mike Bostock https://bost.ocks.org/mike/join/

译文地址: github repository

如果觉得还不错, 不妨去github给个star ?

Content

打个比方, 你想用D3画一个 散点图 , 用每一个svg的circle元素来可视化你的数据. 你会惊讶的发现: D3居然没有直接创建多个DOM元素的方法! 怎么回事?

当然, D3有 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, 用数据点的 xy 属性作为circle的坐标. 但这段代码里面的 selectAll("circle") 是什么意思? 我们为什么要 select 我们知道当前并不存在的 circle, 还用这个方法的返回值去创建新的元素?

这段代码的思想是: 不要告诉D3如何去做, 而是告诉D3你想要的效果. 你想要circle元素和数据一一对应, 那么你就不应该告诉D3去创建circle元素, 而是告诉D3: .selectAll("circle") 得到的circle集合应该和 .data(data) 一一对应. 这个思想就叫做 Join.

从上图中可以看到:

数据集合DOM元素集合 相交产生了中间的 update 集合

没有DOM元素与之对应的Data产生了左边的 enter 集合 (也就是缺失DOM元素)

同样的, 所有没有数据与之对应的DOM元素产生了右边的 exit 集合 (也就意味着这些DOM元素将被移除)

现在我们可以再来看看上面那段使用 enter-append 模型的代码了:

首先, svg.selectAll("circle") 返回的是一个空的集合, 因为当前 svg 容器还是空的. 这里的 svg 是所有后续创建的 circle元素的父节点.

svg.selectAll("circle") 返回的集合接下来和 data 进行 Join 操作, 得到的就是我们上面提到的三个集合: update 集合 , enter 集合 , exit 集合. 因为初始时 Elements集合(也就是circle集合)是空的, 所以 updateexit 集合为空, 而 enter 集合会自动为每一个新的data元素生成一个占位符.

默认 .data(data) 返回的是 update 集合, 因为 update 集合为空, 所以我们不对其进行操作, 这里我们调用 .enter() 得到 enter 集合.

接下来, 对于 enter 集合中的每一个元素, 我们使用 selection.append("circle") (值得注意的是, 对集合的操作会被应用到集合中的每一个元素上去). 这样就为每一个数据点创建了一个 circle (这些circle都在他们的父节点 svg 中)

Join 的方式来思考意味着, 我们要做的事情仅仅是声明 DOM集合(比如这里的 circle 集合) 和数据集合之间的关系, 并且通过处理三个不同状态的集合 enter, update , exit 来描述这种关系.

你也许会问, 为什么要用这种方式来进行我的数据可视化工作呢? 好处在哪? 为什么我不直接用for循环创建所有我想要的元素? 答案是这个思想确实是非常有好处的, 它的优美之处在于它的概括性. 现在我们的代码还只是处理了 enter 的部分, 这部分对于展示静态的数据已经足够了, 但如果你想进行动态的数据展示, 这种 Join 的方式将大大简化你的工作, 你只需要对 updateexit 进行很少的操作就能得到你想要的效果. 这也意味着你可以轻松的展示实时数据, 能够为用户添加动态的交互, 能平滑的切换不同的展示数据集.

下面这段代码展示了对于 exitupdate 集合的处理:

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; });

无论什么时候上面的这段代码被执行, 它都将重新计算 Join 并且维护好 DOM元素集合 和 数据集合 之间的对应关系. 如果你的新数据集比之前老的数据集要小, 多余的DOM元素就会进入 exit 集合, 然后被 remove掉. 如果新的数据集比老的大, 那么新的数据就将进入 enter 集合, 并创建出新的DOM元素. 如果新的数据集和老的数目相同, 那么只有 update 集合会被更新坐标.

使用 Join 的思想能让我们的代码更加直观. 你只需要处理好这三种状态的集合, 而不需要 iffor 来进行复杂的逻辑判断. 你只需要描述好你的数据集合和DOM集合想要有怎样的对应关系.

Join 还让你可以对不同状态的DOM元素进行不同的操作. 比如, 你可以只对 enter 集合进行操作, 这样就不会每次都对所有的 DOM元素进行更新, 这能显著的提升你的数据可视化作品的渲染效率.
同样的, 你也可以给指定集合的元素添加动画效果, 比如给 enter 的元素添加放大进入的效果:

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

或者给 exit 的集合添加 缩小隐藏 的效果:

circle.exit().transition()
    .attr("r", 0)
    .remove();
译者注:

这里有一个非常好的实践 Join 思想的例子(同样来自D3作者), 不妨看看:

Mike Bostock 的实现

这里是我对这个例子的实现(也包括一些其他的案例):

在线演示

源代码

想继续了解 D3.js

这里是我的 D3.js数据可视化 的github 地址, 欢迎 start & fork

D3-blog

如果觉得不错的话, 不妨点击下面的链接关注一下 : )

github主页

知乎专栏

掘金

想直接联系我 ?

邮箱: ssthouse@163.com

微信:

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95410.html

相关文章

  • d3数据绑定与selection实践

    摘要:本篇的使用的版本为将按照简要介绍实验及意义进行简要通过数据绑定创建,更新及销毁元素,如何操作元素则是通过。 本篇blog的使用的d3版本为d3.js v5.9.2 将按照简要介绍、实验及意义进行 简要 d3.js通过data join(数据绑定)创建,更新及销毁元素,如何操作元素则是通过selection。总结如下 showImg(https://segmentfault.com/...

    Tangpj 评论0 收藏0
  • d3.js入门——selection与创建条形图

    摘要:入门,根据官网部分教程学习,发现因为版本更新,有些和概念可能不适用,但总体思想未变。 入门d3.js,根据官网部分教程学习,发现因为版本更新,有些api和概念可能不适用,但总体思想未变。本文思路跟随此篇blogLet’s Make a Bar Chart学习,加上自己的理解,并且查阅了部分更新资料 元素选择 d3通过d3.select()或者d3.selectAll()获取元素,这两个...

    yanbingyun1990 评论0 收藏0
  • 声明式与响应式——前端新一代数据可视化方案

    摘要:数据可视化图表图表作为数据可视化最常见的表现形式之一,往往被以偏概全的认为图表就是数据可视化。严格来说,数据可视化应该是连接数据与视觉的一个映射关系,将数据映射成人更容易感知其规律的可视化结果。 题目中的新一代是个相对的概念,事实上本文即将介绍的方法已经有了生产环境可用的实现方案(这也侧面佐证了其可行性),但考虑到此方法与现在大部分前端项目中所使用的数据可视化方案相比仍有一些优势,因此...

    xuhong 评论0 收藏0
  • 使用JavaScript和D3.js实现数据可视化

    摘要:它的全称是数据驱动文档,并且它被称为一个互动和动态的数据可视化库网络。我们将使用文本编辑器和浏览器。出于测试目的,建议使用工具来检查和调试和,例如或。使矩形反映数据目前,我们阵列中的所有矩形沿轴具有相同的位置,并且不代表高度方面的数据。 欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由独木桥先生 发表于云+社区专栏 介绍 D3.js是一个JavaScript库。它的...

    mingde 评论0 收藏0
  • 使用D3.js构建实时图形

    摘要:在本教程中,我们将探讨如何使用和构建实时图形。通过方法监听轮询更新,并在收到更新后使用最新数据调用函数,以便重新呈现图形。 首先你需要在计算机上安装Node和npm。 数据的可视化表示是传递复杂信息的最有效手段之一,D3.js提供了创建这些数据可视化的强大工具和灵活性。 D3.js是一个JavaScript库,用于使用SVG,HTML和CSS在Web浏览器中生成动态的交互式数据可视化。...

    Ryan_Li 评论0 收藏0

发表评论

0条评论

mikasa

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<