Data joins

给定一个数据数组和一个 D3 selection  我们就可以attach或者说是'join'数组中的每个数据到selection中的每个元素上。

这将使得我们的数据和可视化元素之间建立紧密的联系并实现可视化成为可能。

比如如果我们有以下SVG的circles:

<circle r="40" />
<circle r="40" cx="120" />
<circle r="40" cx="240" />
<circle r="40" cx="360" />
<circle r="40" cx="480" />

和下面的data数组:

var scores = [
{
"name": "Andy",
"score": 25
},
{
"name": "Beth",
"score": 39
},
{
"name": "Craig",
"score": 42
},
{
"name": "Diane",
"score": 35
},
{
"name": "Evelyn",
"score": 48
}
]

那么我们就可以选中这些circles并且join data到这个selection:

d3.selectAll('circle')
.data(scores);
随后我们就可以对这个selection中的元素来设置相应属性为绑定的数据
d3.selectAll('circle')
.attr('r', function(d) {
return d.score;
});

上面的代码就将每个圆的半径设置为每个人的score值的大小。(实际使用中,我们往往还会用到scaleSqrt比例尺,因为分数大小和可视化的半径大小往往需要一个映射!)

从这个形象化的结果,我们就实现了数据的可视化:score值越大,圆的半径就越大,因此只要看到圆大就知道其分数高!

Making a data join

var myData = [ 10, 40, 20, 30 ];

var s = d3.selectAll('circle');

s.data(myData);

数组可以包含任何类型的数据,比如对象数组:

var cities = [
{ name: 'London', population: 8674000},
{ name: 'New York', population: 8406000},
{ name: 'Sydney', population: 4293000}
]; var s = d3.selectAll('circle'); s.data(cities);

Data-driven modification of elements

d3.selectAll('circle')
.attr('r', function(d) {
return d;
});

对每个selection中的element, d3都会调用.attr()函数, 传入该element的joined data d. 而上面匿名函数的返回值作为r的值设定到该元素中.

再比如以下elements:

<circle />
<circle />
<circle />
<circle />
<circle />

和如下数据

var myData = [ 10, 40, 20, 30, 50 ];

我们执行一下data join:

var s = d3.selectAll('circle');

// Do the join
s.data(myData);
s.attr('r', function(d) {
return d;
});

传入 .attr() 的匿名函数将被调用 5 次 (selection中的每一个元素调用一次). 第一次调用时d 是10 因此第一个circle的r设置为10. 第二次调用时为40 因此第二个circle的r设置为40...

我们也可以对d做任何其他处理之后再返回,比如

s.attr('r', function(d) {
return 2 * d;
});

再比如,如果元素绑定的数据大于40,我们则给该元素添加一个css类,以便更改这类元素的样式。

s.classed('high', function(d) {
return d >= 40; // returns true or false
});

最后我们来使用 i 参数来设置其cx的位置:

s.attr('cx', function(d, i) {
return i * 120;
});

总结如下:

var myData = [ 10, 40, 20, 30, 50 ];

var s = d3.selectAll('circle');

// Do the data join
s.data(myData); // Modify the selected elements
s.attr('r', function(d) {
return d;
})
.classed('high', function(d) {
return d >= 40;
})
.attr('cx', function(d, i) {
return i * 120;
});

Arrays of objects

var cities = [
{ name: 'London', population: 8674000},
{ name: 'New York', population: 8406000},
{ name: 'Sydney', population: 4293000},
{ name: 'Paris', population: 2244000},
{ name: 'Beijing', population: 11510000}
]; var s = d3.selectAll('circle'); s.data(cities);

这时当我们根据joined data来修改元素属性时,d 将代表的是joined object. 这样对第一个元素,其 d 将是 { name: 'London', population: 8674000}.

我们再来根据每个城市的population设定circle的半径大小:

s.attr('r', function(d) {
var scaleFactor = 0.000005;
return d.population * scaleFactor;
})
.attr('cx', function(d, i) {
return i * 120;
});
 

当然,我们并不限于修改circle元素,加入我们还有rect和text元素,我们同样可以使用该data join并且设定这些元素的属性:

var cities = [
{ name: 'London', population: 8674000},
{ name: 'New York', population: 8406000},
{ name: 'Sydney', population: 4293000},
{ name: 'Paris', population: 2244000},
{ name: 'Beijing', population: 11510000}
]; // Join cities to rect elements and modify height, width and position
d3.selectAll('rect')
.data(cities)
.attr('height', 19)
.attr('width', function(d) {
var scaleFactor = 0.00004;
return d.population * scaleFactor;
})
.attr('y', function(d, i) {
return i * 20;
}) // Join cities to text elements and modify content and position
d3.selectAll('text')
.data(cities)
.attr('y', function(d, i) {
return i * 20 + 13;
})
.attr('x', -4)
.text(function(d) {
return d.name;
});
 

Under the hood

当d3执行data join时,d3将对每个dom元素增加一个attribute: __data__,并且将对应的data赋值给该属性。实际上,如果我们需要设置其他额外的数据的话,也可以在.each函数中通过.attr('custom_attr','data')来添加并且在后面使用。

使用这种方式来检查是否有绑定好的数据,在需要调试代码行为是否符合预期时是非常有用的。

如果我们的数组长度大于或者小鱼对应的selection元素将会发生什么?

到目前为止,数据数组的长度和元素的个数是相同的。往往现实并非如此,这时我们就需要了解enter和exit的概念了,我们在另外一篇博客中描述。

What’s .datum for?

在有些情况下, (比如当处理地图相关的可视化时 geographic visualisations) ,我们可能需要给一个只含一个元素的selection绑定一个single data,比如:

var featureCollection = {type: 'FeatureCollection', features: features};
d3.select('path#my-map')
.datum(featureCollection);

这将添加一个 __data__ attribute 到元素上并且 assigns the joined data (featureCollection )到这个元素上。可以查看 geographic visualisations

大多数情况下.data用于data join, .datum用于特定场景。

d3js data joins深入理解的更多相关文章

  1. 【wpf】Path画扇形以及Path的Data属性的理解

    <Path x:Name="PathFillColor" Fill="{TemplateBinding Property=Button.Background}&qu ...

  2. d3js selections深入理解

    D3 selections选择DOM元素以便可以对这些dom元素做相应的操作,比如:更改其style,修改其属性,执行data-join操作,或者插入.删除相应elements 比如,如果给定5个ci ...

  3. 学习Hadoop整体理解

    HDFS是Hadoop的核心模块之一,围绕HDFS是什么.HDFS的设计思想和HDFS的体系结构三方面来介绍. Hadoop的设计思想受到Google公司的GFS设计思想的启示,基于一种开源的理念实现 ...

  4. Core Data(数据持久化)

    Core Data可能是OS X和iOS中最容易被误解的框架之一了.为了帮助大家理解,我们将快速研究Core Data,来看一下它是关于什么的.为了正确使用Core Data, 有必要理解其概念.几乎 ...

  5. digitalocean解释:private networking和user data、IPv6是什么意思

    digitalocean vps后台新建droplet的时候,底部会有available settings,里面有四个选项,大多数用户不懂啥意思,我今天解释下: Private Networking ...

  6. jQuery.prop , jQuery.attr ,jQuery.data

    理一下这几个概念吧.根据jquery官网. jquery.prop 获取匹配的元素中第一个元素特定的属性值,或者是设置多个元素的属性值. 有4个重载. .prop(propertyName) 获取属性 ...

  7. JPA、Hibernate、Spring data jpa之间的关系,终于明白了

    什么么是JPA? 全称Java Persistence API,可以通过注解或者XML描述[对象-关系表]之间的映射关系,并将实体对象持久化到数据库中. 为我们提供了: 1)ORM映射元数据:JPA支 ...

  8. Spring Data JPA、MyBatis还有Hibernate有什么区别

    原文:https://www.imooc.com/article/19754?block_id=tuijian_wz Spring Data JPA.MyBatis还有Hibernate有什么区别 2 ...

  9. d3js enter/exit深入了解

    在 Data joins 章节我们演示了当data和dom element个数相同时的情况 <div id="content"> <div></div ...

随机推荐

  1. Mac使用Launchd命令行lauchctl操作服务的简单用法

    注意:操作时前面比如带上sudo,不然只能操作当前用户的服务,会出现无法操作一些root用户的服务的问题.系统版本为Mac 10.12. 1.配置好plist之后: #加载一个服务到启动列表 sudo ...

  2. 【gcc】命令记录

    编译程序gcc -o <eecutable> <soure_code.c>

  3. word-wrap/word-break/white-space

    word-wrap语法: word-wrap : normal | break-word normal : 默认值,单词如果单词超长,会冲出边界(单个单词超长,在当前行显示) break-word : ...

  4. 深入理解系列之 float

    float的设计初衷: 仅仅是为了实现文字环绕效果 float的感性认知: 包裹性: 收缩:元素应用了float后,宽度收缩,紧紧地包裹住内容(即元素的宽度收缩到元素内的内容的宽度大小 坚挺:原来没有 ...

  5. Modular Rails: The complete Guide to Modular Rails Applications 笔记

    fix SamuraiCRM/engines/core/test/dummy/config/routes 修改如下 Rails.application.routes.draw do mount Sam ...

  6. 安装Postgresql之后,创建用户 配置rails

    登录 sudo su - postgres psql 1 创建Postgresql新用户,devpg是用户名,密码也是devpg, 不是超级管理员,拥有创建数据库权限,登录权限,继承拥有角色权限 cr ...

  7. Zepto自定义模块打包构建

    文章转自 http://www.chengxuyuans.com/web_technology/zeptojs-build.html zepto.js 是个好东西,遵循 jQuery API,但比 j ...

  8. digestmd5.c:4037:15: error: #elif with no expression

    执行如下:sed -i.bak 's/#elif WITH_DES/#elif defined(WITH_DES)/' \ plugins/digestmd5.c

  9. To B服务想做移动化?腾讯云案例了解一下

    本文由 腾讯云助手团队 发布于 腾讯云云+社区 | 导语:腾讯云那么多资源和服务,就不能手机管理吗? 能. 当用户在使用To B服务时,往往会遇到各种各样的限制: 1.操作难度:涉及各种权限.多重验证 ...

  10. 四大CPU体系结构:ARM、X86/Atom、MIPS、PowerPC

    补充介绍一下RISC:RISC(reduced instruction set computer,精简指令集计算机)是一种执行较少类型计算机指令的微处理器,起源于80年代的MIPS主机(即RISC机) ...