返回 登录
3

D3数据连接:进入

阅读3661

引言:数据连接是D3中的面包和黄油。D3不提供制图的基础函数,相反,它靠的是数据连接。数据连接可以让页面元素进入网页,一旦进入,可以修改、更新及退出。本文将主要介绍“进入”部分。
本文选自《图说D3:数据可视化利器从入门到进阶》。

什么是数据连接

  顾名思义,数据连接肯定是将数据和某些东西连接起来。这些东西是网页上的一个或一组——< rect>、< circle>、< div>等所有值得怀疑的常见元素。具体一点,就是这些常见元素的一个D3选择集。
  在深入了解之前,让我们忘记D3一会儿。现在,想象有一幅可交互的图形,可以是你以前看到过的、自己写的或者刚刚想象出来的,其中有一些代表数据的图形及一些用来控制某些数据显示与否的按钮。当你点击这些按钮,图形会发生变化:位置偏移了,发光或者闪烁,颜色也变了,甚至可以一起从屏幕中飞出——要多疯狂有多疯狂。
  现在,不管你的图形多么复杂,包含了多少数据,从基础层面看,涉及的这些形状(或线、文本标签、颜色及纹理)都只是在做以下3件事情。

  • 显示在页面上——没有数据和图形就不可能有数据可视化,所以图形需要显示出来。
  • 变换——当你点击按钮或调整滑块,图形的属性会按你想看到的最新数据进行更新。
  • 离开页面——有时,如果一个或多个图形表示的数据不再有效,其会从页面完全移除。

就是这样的3件事情。一个交互式图形就像一座剧院,当演出的时候,演员进入舞台,表演节目,然后退场。在数据可视化中,形状——或更笼统地说,图形元素——进入页面,更新自身,然后退出。
  数据连接充分利用了上述的初步想法。使用时,可以通过指令让图形元素进入、更新和退出。(实际上,我直接从D3中搬来了“enter”、“update”及“exit”这些词。)
  此外,D3让你可以基于数据执行上述所有操作。D3通过一种称为“数据绑定”的技术来达成这种能力。无论何时执行数据连接,数据会真正被关联,或绑定到元素上。这真的太方便了,D3让你可以非常轻松地绑定数据了。所以,你会说:“好了,矩形,你所绑定的数据是多少?35?嗯,好吧,希望你的宽度也正好是这么宽。”
  为了说明数据连接是如何工作的,我打算引入一个新的示例—— 一个涉及数据连接基本概念各方面知识点的示例。为了构建之前那幅人口分布条形图,我们也会引入数据连接,但不会描述得那么完整。所以,虽然有点跑题,但是引入一个新示例将有助于我们研究数据连接的方方面面。
  本文只涉及数据连接知识的一部分,重点在其整个生命周期中关于“进入”的部分。在后面的推送中,我们会用同样的示例来详细阐述“更新”和“退出”部分。
  好了,我们开始。
  假设你有一个朋友,名字叫Frank。Frank有一个癖好是喜欢看明星八卦杂志和各种小道报刊。《美国周刊》、《人物》及《国家调查者》等,就是那种你在杂货店排队结账,百无聊赖时会瞥见的刊物,Frank一定会有强烈的兴趣。问题是,他其实并不关心Kim和Kanye的近况,他只是想知道一件事情:谁上封面了?
  Frank最近一直在关注20多种不同杂志期刊封面上的特色名人,一个月内会有约50张不同的封面——已经持续了1年。此外,他还研究了过去4年各个封面人物的情况。“我认为那些在任何时刻都被人们议论的名人体现了这个国家的精神面貌”,Frank啰唆道。你有你的怀疑,但当Frank找到你并请求你帮他将这些信息做成可视化图形时,你也没法拒绝。
  Frank的想法是:基于他所收集的近5年的数据,按月显示最热门的5个名人。他希望这个可视化图形是可以交互的,并具有动画效果,但是他不知道图形应该做成什么样子。然而,你是有想法的。你在笔记本上画了几分钟,交给Frank一幅草图,然后开始解释。
               【图1】
                       为Frank准备的草图

  “图形展示了数据集中最老的,也就是2009年1月五大名人的列表”,你向他解释道。然后,每一个名人的名字是一个条形,代表了他(或她)这个月在杂志封面上出现的次数。这样,哪个名人拥有主导地位就一目了然了。Frank有两种方式切换到后续月份:他可以按下播放按钮,然后坐下欣赏(因为图形会自动按月显示);或者拖动滑块到指定的月份。当图形从一个月份变换到另外一个月份,新的名字会进入排行榜,旧的名字会退出,还有一部分会在列表上上下移动,同时条形的宽度会扩展或收缩至更新后的数值。“好极了!”Frank赞叹道。然后,他把剩余的3000行数据也一并发送给你。
进入,更新,退出……D3为此而生!

进入并绑定数据

  假设你已经整理了一些数据,为每个月、每个名人都增加了封面,并进行了排序。下图是你整理的前3个月的信息,也就是2009年1月到3月的信息(这些数值当然都是杜撰的)。
                   【图2】
                         前3个月的数据

  以下是关于这些数据的一些解释。

  • 封面人物的数量并不总是刚好等于50。这是因为有的封面包含两个名人,这种情况下,该封面算是这两个人的。
  • 1月所有封面上仅有4位名人,大部分期刊都在关注Brad Pitt和Angelina Jolie的故事。(这就是Frank所说的国民精神所在?)
  • 2月类似于1月,除了《世界新闻周刊》,其他杂志的封面人物都是著名的“蝠孩”。

通过JavaScript来组织这些数据的一种良好方式是创建一系列对象数组。例如,1月我们有如下数组。

var janData = [         
      {name:"Angelina Jolie", covers:20, rank:1},
      {name:"Brad Pitt", covers:18, rank:2},
      {name:"Jennifer Aniston", covers:10, rank:3},
      {name:"Britney Spears", covers:8, rank:4}
];

  你能看出来为什么这个结构很友好吗?数组janData包含4个数据对象,每个对象包含一个数据点该有的所有信息。我们将在第7章阐述有关数据结构的更多细节。
  好了,要事优先:我们需要在页面上显示一些图形。现在,让我们先忘掉这些条形,并且仅从这些人物的名字开始。我们可以用for循环为每个名字添加一个文本节点,但是我们不打算这么做。忘掉for循环,我们正在考虑数据连接,我们想让文本“进入”页面。
  具体方法是:我们先为当前页面上的所有文本元素创建一个选择集,然后为其连接数据。但是,等等……我们的页面是空白的,现在还没有文本元素!所以,“选择所有文本元素”到底意味着什么?
此处展现的就是D3进入阶段的“魔法”——通过d3.selectAll()创建一个并不存在的元素的选择集。在这种情况下,由于我们想让文本进入页面,因此可以通过d3.selectAll(“p”)选择所有这些还不存在的段落元素。这个概念如下。
                 【图3】
                       一个空的选择集
                       
  然后,你在这个选择集上调用了两个方法,分别是data()和enter()。这一记“组合拳”产生了真实的惊人效果:其为数据集中的每个数据点都创建了一个对象。是的,就是这样——你不必告诉D3你的数据集有多大。你只要将其与一个空选择集进行连接,它就会为你创建正确数量的对象。
             【图4】
                      data()和enter()的魔法

  一开始,这些数据只用来占位——文本元素还没有真正添加到页面上。为了做到这一点,我们就得用上我们的老朋友append()了。我们将为那些占位数据都附加一个段落元素。
             【图5】
                     用文本元素替换占位数据

  现在,我们已经在页面上放置了4个文本元素,但是其中还没有任何文字,所以我们的页面是空白的。如何让那些名人的姓名显示在正确的位置呢?奥秘就在data()方法中。该方法实际上执行了一次数据连接——当D3执行数据连接时,它将数据绑定到元素上。所以,每一个文本元素实际上都会有一个数据与其关联或绑定,正如上图所示。
  D3让我们可以很容易地绑定数据,所以我们可以通过数据来告知文本应该显示什么内容,以及在哪里显示:“好了,元素们,看看你们自己的数据点。你的名人名字叫什么?Angelina Jolie?好的,这就是我想让你的文本显示的内容。此外,它应该排在第几个?第1个?好的,你就排到顶上吧!”
  本文选自《图说D3:数据可视化利器从入门到进阶》,点此链接可在博文视点官网查看此书。
                    图片描述

评论