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.
在上述代码前面增加以下代码:
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均显示出来。
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);
网友评论