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用于特定场景。

时间: 2024-10-10 04:12:47

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

Data Science(什么是数据科学)

科学上网时看到的有关于Data Science的理解,感觉挺好的,就翻一下. Data science is about understanding systems, whether they be natural systems such as climate, or man-made systems like the economy. (数据科学可以称之为理解系统,无论这个系统是自然系统,例如天气系统,或者人造的生态环境系统). Scientists have been conducting

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('

ISP模块之RAW DATA去噪(一)

ISP(Image Signal Processor),图像信号处理器,主要用来对前端图像传感器输出信号处理的单元,主要用于手机,监控摄像头等设备上. RAW DATA,可以理解为:RAW图像就是CMOS或者CCD图像感应器将捕捉到的光源信号转化为数字信号的原始数据,是无损的,包含了物体原始的颜色信息等.RAW数据格式一般采用的是Bayer排列方式,通过滤波光片,产生彩色滤波阵列(CFA),鉴于人眼对绿色波段的色彩比较敏感,Bayer数据格式中包含了50%的绿色信息,以及各25%的红色和蓝色信息

Core Data系列译文:Core Data概述

在"伯乐在线"发现了一篇很不错的关于CoreData的文章,只是那里不能收藏,故而转载至此 以下是文章原文: 本文由 伯乐在线 - IvyShao 翻译自 Daniel Eggert.欢迎加入技术翻译小组.转载请参见文章末尾处的要求. [2013-11-19 21:24:26 伯乐在线补充]:由于之前和译者@shaojingkk 沟通不够,我们在发布这篇译文之前并不知道译者参考对照@answer-huang 之前的译文版本,所以发布文章时未能在文中特别说明,责任在我们,在此向@answ

JPA Hibernate jpa spring data jpa

什么么是JPA? 全称Java Persistence API,可以通过注解或者XML描述[对象-关系表]之间的映射关系,并将实体对象持久化到数据库中. 为我们提供了: 1)ORM映射元数据:JPA支持XML和注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中: 如:@Entity.@Table.@Column.@Transient等注解. 2)JPA 的API:用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者从繁琐的JDBC和

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

什么是jpa? 全称Java Persistence API,可以通过注解或者XML描述[对象-关系表]之间的映射关系,并将实体对象持久化到数据库中. 为我们提供了: 1)ORM映射元数据:JPA支持XML和注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中: 如:@Entity.@Table.@Column.@Transient等注解. 2)JPA 的API:用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者从繁琐的JDBC和S

JPA、Hibernate、Spring data jpa之间的关系,以及和springboot的整合

什么么是JPA? 全称Java Persistence API,可以通过注解或者XML描述[对象-关系表]之间的映射关系,并将实体对象持久化到数据库中. 为我们提供了: 1)ORM映射元数据:JPA支持XML和注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中: 如:@Entity.@Table.@Column.@Transient等注解. 2)JPA 的API:用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者从繁琐的JDBC和

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

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

React的React Native

React无疑是今年最火的前端框架,github上的star直逼30,000,基于React的React Native的star也直逼20,000.有了React,组件化似乎不再步履蹒跚,有了React Native,前端的边界似乎广阔无边.而Webpack凭借它异步加载和可分离打包等优秀的特性,走在取代Grunt和Gulp的路上.而面向未来的ES6,模块化的支持似乎已成定局. 我们现在就可以打造自己的Webpack+React+ES6环境并且开始探索起来. 这篇文章就给还没走在这条路上的前端一