d3js data joins深入理解
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深入理解的更多相关文章
- 【wpf】Path画扇形以及Path的Data属性的理解
<Path x:Name="PathFillColor" Fill="{TemplateBinding Property=Button.Background}&qu ...
- d3js selections深入理解
D3 selections选择DOM元素以便可以对这些dom元素做相应的操作,比如:更改其style,修改其属性,执行data-join操作,或者插入.删除相应elements 比如,如果给定5个ci ...
- 学习Hadoop整体理解
HDFS是Hadoop的核心模块之一,围绕HDFS是什么.HDFS的设计思想和HDFS的体系结构三方面来介绍. Hadoop的设计思想受到Google公司的GFS设计思想的启示,基于一种开源的理念实现 ...
- Core Data(数据持久化)
Core Data可能是OS X和iOS中最容易被误解的框架之一了.为了帮助大家理解,我们将快速研究Core Data,来看一下它是关于什么的.为了正确使用Core Data, 有必要理解其概念.几乎 ...
- digitalocean解释:private networking和user data、IPv6是什么意思
digitalocean vps后台新建droplet的时候,底部会有available settings,里面有四个选项,大多数用户不懂啥意思,我今天解释下: Private Networking ...
- jQuery.prop , jQuery.attr ,jQuery.data
理一下这几个概念吧.根据jquery官网. jquery.prop 获取匹配的元素中第一个元素特定的属性值,或者是设置多个元素的属性值. 有4个重载. .prop(propertyName) 获取属性 ...
- JPA、Hibernate、Spring data jpa之间的关系,终于明白了
什么么是JPA? 全称Java Persistence API,可以通过注解或者XML描述[对象-关系表]之间的映射关系,并将实体对象持久化到数据库中. 为我们提供了: 1)ORM映射元数据:JPA支 ...
- Spring Data JPA、MyBatis还有Hibernate有什么区别
原文:https://www.imooc.com/article/19754?block_id=tuijian_wz Spring Data JPA.MyBatis还有Hibernate有什么区别 2 ...
- d3js enter/exit深入了解
在 Data joins 章节我们演示了当data和dom element个数相同时的情况 <div id="content"> <div></div ...
随机推荐
- 【文档】四、Mysql Binlog事件含义详解
下面对binlog中事件做个简单说明: UNKNOWN_EVENT 这个事件类型应该永远不会出现.它从不会写入binlog中.如果binlog中的事件没法被识别成其他已知事件,他被当做UNKNOWN_ ...
- JavaScript数据结构-4.栈操作
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- call()和apply()方法(切换上下文)
call方法: 语法:call([thisObj[,arg1[, arg2[, [,.argN]]]]]) 定义:调用一个对象的一个方法,以另一个对象替换当前对象. apply方法: 语法:apply ...
- 配置MySQL接受远程登录连接
一 开放mysql mysql的配置文件在/etc/mysql/my.cnf文件内,里面有一行bind-address = 127.0.0.1表示只允许本地访问,将这行注释即可 # bind-addr ...
- 环境准备 Ubuntu & Docker
目录 Ubuntu 简介 配置 Docker 简介 Docker CE 安装 参考 本文主要讲解在 Ubuntu 上安装和配置 Docker CE. Ubuntu 简介 Ubuntu(乌班图)是一个基 ...
- [作业] Python入门基础--猜年龄
age = 20 while True: try: guess_age = int(input('guess age:')) if guess_age > age: print('Is bigg ...
- code EINTEGRITY,npm安装时候报错
解决方法: 1.如果有package-lock.json文件,就删掉 2.管理员权限进入cmd 3.执行npm cache clean --force 4.之后再npm install 有时候网不好也 ...
- swagger api文档添加jwt授权配置
最近写的swagger文档,要加jwt授权,所以几经google终于搞定了,简简单单几行配置如下: securityDefinitions: APIKey: type: apiKey name: Au ...
- Vue学习笔记:Ref的使用
官网上的说明 1.了解Vue中的$refs在Vue中是怎么访问到DOM元素的 <div id="app"> <h1>{{ message }}</h1 ...
- JAVA基础之——JDK分析io、nio
在哪儿:jdk\jre\lib\rt.jar package java.io; package java.nio; 1 分类 1.1 IO 持久化序列化对象并压缩步骤 new FileOutput ...