d3js enter/exit深入了解

在 Data joins 章节我们演示了当data和dom element个数相同时的情况

<div id="content">
  <div></div>
  <div></div>
  <div></div>
</div>

给定下面的数据

var myData = [ 10, 40, 20 ];

当我们对div元素join上数据时

d3.select(‘#content‘)
  .selectAll(‘div‘)
  .data(myData);

myData 数据的个数和div元素的个数是相同的。

但是,如果数据和dom元素的个数如果不相同的话,会怎样呢?

  • 如果数据个数多于dom元素个数那么说明有DOM元素的缺口,我们需要 add elements
  • 如果数据个数少于dom元素个数,那么说明DOM元素有剩余,我们需要 remove elements

幸运的是D3可以帮助我们非常方便地管理这两种情况,分别通过 .enter来添加 而通过.exit来删除.

.enter

.enter 指明了所有和data相比dom元素的缺口,enter和exit都是定义在update selection上的 (the selection returned by .data):

d3.select(‘#content‘)
  .selectAll(‘div‘)
  .data(myData)
  .enter();

.enter 返回代表需要增加的那些元素(已经绑定了数据)的selection. 通常跟随.enter的都是 .append 操作

d3.select(‘#content‘)
  .selectAll(‘div‘)
  .data(myData)
  .enter()
  .append(‘div‘);

Let’s look at an example. Suppose we have the following div elements:

<div id="content">
  <div></div>
  <div></div>
  <div></div>
</div>

and this data:

var myData = [‘A‘, ‘B‘, ‘C‘, ‘D‘, ‘E‘];

we use .enter and .append to add div elements for D and E:

  d3.select(‘#content‘)
    .selectAll(‘div‘)
    .data(myData)
    .enter()
    .append(‘div‘);

View source | Edit in JS Bin

Note that we can join an array to an empty selection which is a very common pattern in the examples on the D3 website.

View source | Edit in JS Bin

.exit

.exit returns an exit selection which consists of the elements that need to be removed from the DOM. It’s usually followed by .remove:

d3.select(‘#content‘)
  .selectAll(‘div‘)
  .data(myData)
  .exit()
  .remove();

Let’s repeat the example above, but using .exit. Starting with elements:

<div id="content">
  <div></div>
  <div></div>
  <div></div>
</div>

and data (notice that it’s shorter than the selection):

var myData = [‘A‘];

we use .exit and .remove to remove the surplus elements:

d3.select(‘#content‘)
  .selectAll(‘div‘)
  .data(myData)
  .exit()
  .remove();

View source | Edit in JS Bin

Putting it all together

So far in this section we’ve not concerned ourselves with modifying elements using functions such as .style, .attr and .classed.

D3 allows us to be specific about which elements are modified when new elements are entering. We can modify:

  • the existing elements
  • the entering elements
  • both existing and entering elements

(Most of the time the last option is sufficient, but sometimes we might want to style entering elements differently.)

The existing elements are represented by the update selection. This is the selection returned by .data and is assigned to u in this example:

var myData = [‘A‘, ‘B‘, ‘C‘, ‘D‘, ‘E‘];

var u = d3.select(‘#content‘)
  .selectAll(‘div‘)
  .data(myData);

u.enter()
  .append(‘div‘);

u.text(function(d) {
  return d;
});

View source | Edit in JS Bin

When the button is clicked, new elements are added, but because .text is only called on the update selection, it’s only the existing elements that are modified. (Note that if the button is clicked a second time, all the elements are modified. This is because the selection will contain all 5 div elements. Don’t worry about this too much if you’re new here!)

The entering elements are represented by the enter selection. This is the selection returned by .enter. We can modify the enter selection using:

var myData = [‘A‘, ‘B‘, ‘C‘, ‘D‘, ‘E‘];

var u = d3.select(‘#content‘)
  .selectAll(‘div‘)
  .data(myData);

u.enter()
  .append(‘div‘)
  .text(function(d) {
    return d;
  });

View source | Edit in JS Bin

When the button is clicked, new elements are added and their text content is updated. Only the entering elements have their text updated because we call .text on the enter selection.

If we want to modify the existing and entering elements we could call .text on the update and enter selections.

However D3 has a function .merge which can merge selections together. This means we can do the following:

var myData = [‘A‘, ‘B‘, ‘C‘, ‘D‘, ‘E‘];

var u = d3.select(‘#content‘)
  .selectAll(‘div‘)
  .data(myData);

u.enter()
  .append(‘div‘)
  .merge(u)
  .text(function(d) {
    return d;
  });

View source | Edit in JS Bin

This is a big departure from v3. The entering elements were implicitly included in the update selection so there was no need for .merge.

General update pattern

A common pattern (proposed by D3’s creator Mike Bostock) is to encapsulate the above behaviour of adding, removing and updating DOM elements in a single function:

function update(data) {
  var u = d3.select(‘#content‘)
    .selectAll(‘div‘)
    .data(data);

  u.enter()
    .append(‘div‘)
    .merge(u)
    .text(function(d) {
      return d;
    });

  u.exit().remove();
}

View source | Edit in JS Bin

Typically the update function is called whenever the data changes.

Here’s another example where we colour entering elements orange:

function update(data) {
  var u = d3.select(‘#content‘)
    .selectAll(‘div‘)
    .data(data);

  u.enter()
    .append(‘div‘)
    .classed(‘new‘, true)
    .text(function(d) {
      return d;
    });

  u.text(function(d) {
      return d;
    })
    .classed(‘new‘, false);

  u.exit().remove();
}

View source | Edit in JS Bin

Data join key function

When we do a data join D3 binds the first array element to the first element in the selection, the second array element to the second element in the selection and so on.

However, if the order of array elements changes (such as during element sorting, insertion or removal), the array elements might get joined to different DOM elements.

We can solve this problem by providing .data with a key function. This function should return a unique id value for each array element, allowing D3 to make sure each array element stays joined to the same DOM element.

Let’s look at an example, first using a key function, and then without.

We start with an array [‘Z‘] and each time the button is clicked a new letter is added at the start of the array.

Because of the key function each letter will stay bound to the same DOM element meaning that when a new letter is inserted each existing letter transitions into a new position:

Without a key function the DOM elements’ text is updated (rather than position) meaning we lose a meaningful transition effect:

There’s many instances when key functions are not required but if there’s any chance that your data elements can change position (e.g. through insertion or sorting) and you’re using transitions then you should probably use them.

时间: 2024-10-05 05:31:29

d3js enter/exit深入了解的相关文章

【 D3.js 入门系列 --- 7 】 理解 update, enter, exit 的使用

本人的个人博客为: www.ourd3js.com csdn博客为: blog.csdn.net/lzhlzz 转载请注明出处,谢谢. 在前面几节中反复出现了如下代码: svg.selectAll("rect") .data(dataset) .enter() .append("rect") 当所选择的 rect 数量比绑定的数据 dataset 的数量少的时候,通常会用到以上代码,这一节就详细说说当被选择元素和数据数量不一致时该如何处理. 这一节将涉及到三个函数.

内置方法 call enter exit

class A(object): def __init__(self,name,age): self.name = name self.age = age def __call__(self) print('AAA') A()() # 源码里用比较多 Flask web框架# 对象()自动触发__call__中的内容 Python 的 __call__ 方法可以让类的实例具有类似于函数的行为,通常用于定义和初始化一些带有上下文的函数. 既然说是妙处,那不得不提及 Python 世界中的那几个经典

d3.js中data(), enter() 和 exit()的作用

我在刚接触使用d3.js的时候,最感到困惑的一个地方是data(), enter(), exit()这几个操作. 在我接触一段时间,有了一些了解之后,简单说说我的理解. data() 先看一个例子: <body> <p></p> <p></p> <p></p> </body> 执行代码: d3.select("body").selectAll("p").data([1,

d3可视化实战02:理解d3数据驱动的真正含义

前文中已经提到,SVG从诞生之初起就可以非常方便地使用javascript脚本语言来进行其DOM对象的控制.当然,控制的方法有很多,有直接控制SVG对象的方法,例如使用原生js:有帮你封装一下图形接口再进行直接控制的js类库,如 Raphaël.但是正如我在第一篇文章中所说,d3作为一个中间型类库还能脱颖而出的重要原因,在于它突破了其他类库的那种直接控制表现层的机制,而采用了对于web图形处理领域较为新颖的数据驱动机制(2011),并获得了极大的成功. 数据驱动的历史 数据驱动编程并不是一个新鲜

D3中动画(transition函数)的使用

关于transition的几个基本点: 1. transition()是针对与每个DOM element的,每个DOM element的transition并不会影响其他DOM element的transition操作: 2. 对于每一个DOM element的transition每次只能执行一个,如果在一个DOM element上添加了许多transition操作,只有最后一个会起作用,前面的都会被覆盖掉.但是例外是,当这些transition是chaining的形式连接的时候,这些trans

[D3.js] 综述

D3.js 是操作基于数据文件的JavaScript库.它使用HTML.SVG和CSS让你的数据基情四射.D3在web标准上着重为你提供现代浏览器的全部功能,而且不需要通过使用你自己专门的框架.结合强大的可视化组件和DOM操作的数据驱动方法. 点击下载最新版(3.5.5): d3.zip 或者,在页面上引用: <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>

d3从入门到出门

前言 基于d3js 5.5版本基础教程 环境配置 下载最新d3js文件, 参考: d3js官网 当前版本5.5, d3js v4与v3之间的api有一定的差异. 选择元素 d3主要有两个选择器 select 选择相应的dom元素, 如果有多个, 选择第一个 selectAll 选择所有的指定的dom元素. 通过选择器可以选择相应得dom元素, 而选择器的语法基本就是css选择器的语法. css选择器语法: http://www.w3school.com.cn/c***ef/css_selecto

使用SHELL完成两个数字的大小比较

简要说明: 提示用户输入两个数字: 判断输入的内容是否都为数字: 数字做计算并反馈结果: 计算完毕后询问客户是否继续使用: 给用户提供随时退出的方法. [[email protected] scripts]# cat jisuan2.sh #!/bin/bash ###thank_oldboy ###2016/3/6 ###i wish you all the best. . /etc/init.d/functions ### read number. function read_number(

hdoj 4289 Control 【拆点 求最小割】

Control Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2295    Accepted Submission(s): 961 Problem Description You, the head of Department of Security, recently received a top-secret informati