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. (热死你)Resin https ssl Linux 配置,实战可用

    (热死你)Resin https ssl Linux 配置,实战可用 一.配置resin 1.在resin服务器中创建目录keys文件和openssl.conf,格式内容如下: #先复制以下的内容: ...

  2. redux设计到源码 --- 美团点评技术团队(转)

    https://tech.meituan.com/redux-design-code.html

  3. spring boot快速入门 4: jpa数据库操作 实现增删改查

    spring boot jpa逆向生成表 简单实例: 第一步:pom文件: <?xml version="1.0" encoding="UTF-8"?&g ...

  4. 阅读The Java® Language Specification需要知道的英文单词

      In any case/on any account  在任何情况下 “Varargs”是“variable number of arguments”的意思.有时候也被简单的称为“variable ...

  5. 【总结】java 后台文件上传整理

    public Map<String,String> clientUploadAttachment(Long belongId, String fileSource, MultipartFi ...

  6. C# 通过反射获取方法/类上的自定义特性

    1.所有自定义属性都必须继承System.Attribute 2.自定义属性的类名称必须为 XXXXAttribute 即是已Attribute结尾 自定义属性QuickWebApi [Attribu ...

  7. php中的字符串常用函数 str_replace 字符串替换,替换全角空格

    <?php $str = "hello world!"; echo(str_replace(array('hello', 'world'), array('tom', 'cl ...

  8. 使用k8s创建容器一直处于ContainerCreating状态

    容器报错信息为(两种): FailedSynError syncing pod, skipping: failed to {kubelet 127.0.0.1} Warning FailedSync ...

  9. Knockout.js hasFocus

    <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8&quo ...

  10. <深入理解JavaScript>学习笔记(1)_编写高质量JavaScript代码的基本要点

    注:本文是拜读了 深入理解JavaScript 之后深有感悟,故做次笔记方便之后查看. JQuery是一个很强大的JavaScript 类库,在我刚刚接触JavaScript的就开始用了. JQuer ...