通过实例学习创建D3.js数据可视化

马克。布朗
分享

本文由米凯拉莱尔而且蒂姆Severien.感谢所有SitePoint的同行审必威西盟体育网页登录稿人,让SitePoint的内容成为最好的!

D3.js是一个JavaScript库,用于基于数据操作文档。D3帮助您使用HTML、SVG和CSS生动地呈现数据。

我只建议使用三个JavaScript库每一个web开发人员应该学习:jQuery,下划线和D3。这些库允许你以新的方式思考代码:jQuery让你用DOM写得更少,做得更多,下划线(或lodash)为你提供了改变程序编写方式的功能工具,D3为你提供了丰富的数据操作和图形编程工具集。如果你不熟悉D3,请花点时间看看令人印象深刻的D3示例库看看能用它做些什么。

这不是你爸爸的图库

威廉·普莱费尔发明了酒吧,行而且区域1786年的图表饼状图在1801年。今天,这些仍然是大多数数据集呈现的主要方式。现在,这些图表优秀的但D3给了你制作的工具和灵活性独特的对于网络数据可视化,你的创造力是唯一的限制因素。

D3是一个非常灵活的低级可视化库,具有类似jquery的API,用于将数据映射到HTML和SVG文档。它包含大量有用的数学函数,用于数据转换和物理计算,尽管它的大部分功能来自SVG中的几何图形和路径操作。

本文的目的是让您对D3的功能有一个高层次的概述,在每个示例中您都可以看到输入数据,转换和输出文档。而不是解释每个函数做什么,我将向您展示代码,您应该能够大致了解事情是如何工作的。我只会深入研究最重要的概念,尺度而且选择

柱状图

基本条形图"宽度="149

参见代码依赖体

我向你承诺过比William Playfair的图表更多的东西,但是用HTML制作简单的柱状图是理解D3如何将数据转换为文档的最简单方法之一。这是它的样子:

d3选择“图号”selectAll" div "数据4815162342输入附加" div "风格“高度”d= >d+“像素”

selectAll函数返回一个D3“selection”:一个元素数组,当我们输入而且附加每个数据点都有一个div。

这段代码映射输入数据[4, 8, 15, 16, 23, 42]到这个输出HTML。

<divid图表><div风格高度4px>div><div风格高度8px>div><div风格高度15px>div><div风格高度16px>div><div风格高度23px>div><div风格高度42px>div>div>

所有不变的样式属性都可以放入CSS中。

#图div显示inline-block背景# 4285 f4宽度20.pxmargin-right3.px

GitHub的贡献图表

通过几行额外的代码,我们可以将上面的柱状图转换为类似于Github的贡献图。

一个github风格的贡献图表"宽度="160"loading=

参见代码依赖体

而不是根据数据的值来设置高度,我们可以设置背景颜色代替。

常量colorMapd3interpolateRgbd3rgb“# d6e685”d3rgb“# 1 e6823”d3选择“图号”selectAll" div "数据.2.40013。.92输入附加" div "风格“背景颜色”d= >返回d= =0?“# eee”colorMapd

colorMap函数接受一个0到1之间的输入值,并沿着我们提供的两个颜色之间的颜色梯度返回一个颜色。插值是图形编程和动画中的一个关键工具,我们将在后面看到更多的例子。

SVG入门

D3的强大之处在于它与SVG一起工作,SVG包含用于绘制圆、多边形、路径和文本等2D图形的标签。

形状和文本的集合"宽度="200"loading=

<svg宽度200高度200><圆填满# 3 e5693残雪50cy120r20./><文本xOne hundred.yOne hundred.>你好SVG !文本><路径dM100, 70年10 l150预示70 z填满# BEDBC3中风# 539 e91笔划宽度3.>svg>

上面的代码绘制:

  • 半径为20的50,120的圆
  • 文本“Hello SVG!”100,100
  • 一个带有3px边框的三角形d属性具有以下说明
  • 移动到100,10
  • 行到150 70
  • 排到50,70
  • 关闭路径(Z)

<路径>是SVG中最强大的元素。

有标签的圆圈显示每天的销售时间"宽度="260"loading=

参见代码依赖体

前面例子中的数据集是一个简单的数字数组,D3也可以处理更复杂的类型。

常量数据{标签“早上7点”销售20.{标签“8点”销售12{标签“9点”销售8{标签“10点”销售27

对于每一个数据点,我们将附加一个< g >元素的#图和附加<圆>而且<文本>每个元素都具有对象的属性。

常量gd3选择“图号”selectAll“g”数据数据输入附加‘g’g附加“圆”attr“cy”40attr“cx”d= >+150attr“r”d= >d销售g附加“文本”attr“y”90attr“x”d= >+150文本d= >d标签

的变量g类型数组的d3“选择项”< g >节点,操作如append ()将一个新元素附加到所选项中的每个项。

这段代码将输入数据映射到这个SVG文档,您能看出它是如何工作的吗?

<svg高度One hundred.宽度250id图表><g><圆cy40残雪50r20./><文本y90x50>早上7点文本>g><g><圆cy40残雪One hundred.r12/><文本y90xOne hundred.>早上8点文本>g><g><圆cy40残雪150r8/><文本y90x150>9点文本>g><g><圆cy40残雪200r27/><文本y90x200>上午10点文本>g>svg>

折线图

基本折线图"宽度="200"loading=

参见代码依赖体

在SVG中绘制折线图非常简单,我们希望像这样转换数据:

常量数据{x0y30.{x50y20.{xOne hundred.y40{x150y80{x200y95

在本文档中:

<svgid图表高度One hundred.宽度200><路径笔划宽度2dM0 70预示80 l100 60 l150 20 l200, 5>svg>

请注意:y数值从图表的高度(100)中减去,因为我们想要ay值100位于SVG的顶部(从顶部开始为0)。

假设它只是一个单路径元素,我们可以我们自己用这样的代码来做:

常量路径“M”+数据地图d= >返回dx+”、“+One hundred.-dy加入“L”常量$ {路径" / >文档querySelector“图号”innerHTML=行

D3有路径生成函数,让这个更简单,这是它的样子。

常量d3svgxd= >dxyd= >One hundred.-dy插入“线性”d3选择“图号”附加“路径”attr“笔划宽度”2attr' d '数据

更好!的插入函数也有几种不同的方法可以围绕xy坐标画线。看看" linear ", " step-before ", " basis "和" cardinal "是什么样子。

线性风格的折线图"宽度="200"loading=
步进式折线图"宽度="200"loading=
一个基准样式的折线图"宽度="200"loading=
一个基数风格的折线图"宽度="200"loading=

尺度

比例是将输入域映射到输出范围的函数。

参见代码依赖体

在我们目前看到的例子中,我们已经能够使用“神奇数字”在图表范围内定位事物,当数据是动态的,你需要做一些数学计算来适当地缩放数据。

假设我们想要渲染一个500px宽,200px高的折线图,使用以下数据:

常量数据{x0y30.{x25y15{x50y20.

理想情况下,我们希望y轴值从0到30(最大y值),x轴值从0到50(最大x值),这样数据就占据了图表的全部维度。

我们可以用d3.max在我们的数据集中找到Max值并创建尺度用于将x, y输入值转换为SVG路径的x, y输出坐标。

常量宽度500常量高度200常量xMaxd3马克斯数据d= >dx常量yMaxd3马克斯数据d= >dy常量xScaled3规模线性0xMax//输入域范围0宽度//输出范围常量yScaled3规模线性0yMax//输入域范围高度0//输出范围

这些尺度类似于我们之前创建的颜色插值函数,它们只是将输入值映射到输出范围中的某个值的函数。

xScale0->0xScale10->One hundred.xScale50->500

它们也适用于输入域之外的值:

xScale-10->-One hundred.xScale60->600

我们可以在我们的线生成函数中使用这些刻度,就像这样:

常量d3svgxd= >xScaledxyd= >yScaledy插入“线性”

你可以很容易地使用缩放来做的另一件事是在输出范围周围指定填充:

常量填充20.常量xScaled3规模线性0xMax范围[填充宽度-填充常量yScaled3规模线性0yMax范围高度-填充,填充

现在我们可以渲染一个动态数据集,我们的折线图将始终适合我们的500px / 200px边界,两边都有20px的填充。

线性尺度是最常见的类型,但也有其他的战俘对于指数尺度序数用于表示非数字数据(如名称或类别)的刻度。除了定量尺度而且顺序尺度也有时间尺度用于映射日期范围。

例如,我们可以创建一个比例,将我的寿命映射到0到500之间的数字:

常量生活d3时间规模日期1986118日期范围0500//在0到500之间的哪一点是我的18岁生日?生活日期2004118

动画飞行可视化

这一切都很好,但到目前为止,我们只看到静态的无生气的图形。让我们制作一个动画可视化,显示澳大利亚墨尔本和悉尼之间的活跃航班随时间的变化。

看钢笔D3 -航班由Si必威西盟体育网页登录tePoint (@必威西盟体育网页登录SitePoint)CodePen.

这种类型的图形的SVG文档由文本、线条和圆组成。

<svgid图表宽度600高度500><文本时间x300y50文本链接中间>6:00文本><文本origin-textx90y75文本链接结束>梅尔文本><文本dest-textx510y75文本链接开始>悉德文本><圆origin-dotr5残雪One hundred.cy75/><圆dest-dotr5残雪500cy75/><行origin-dest-linex1110日元75x2490y275/><!--for each flight in the current time --><g飞行><文本flight-idx160yOne hundred.>金桥500文本><行航线x1One hundred.日元One hundred.x2150y2One hundred./><圆flight-dot残雪150cyOne hundred.r5/>g>svg>

动力部分是时间和元素飞行组和数据可能看起来像这样:

数据{离开“凌晨06:00时”到达“07:25点”id“捷星500”{离开“凌晨06:00时”到达“07:25点”id“澳航400”离开“凌晨06:00时”到达“07:25点”id“803年处女”

为了获得动态时间的x位置,我们需要为每个航班创建一个时间刻度,将其出发和到达时间映射到图表上的x位置。我们可以在开始添加时循环遍历数据日期物体和尺度,这样更容易处理。Moment.js在这里对数据解析和操作有很大帮助。

数据forEachd= >{ddepartureDate时刻d离开“hh-mm“迄今为止,darrivalDate时刻d到达“hh-mm“迄今为止,dxScaled3时间规模departureDate,arrivalDate范围One hundred.500

现在可以将更改后的Date传递给xScale ()得到每一次飞行的x坐标。

渲染循环

出发和到达的时间四舍五入为5分钟,这样我们就可以从第一次出发到最后一次到达,以5m为增量逐级查看数据。

现在时刻数据0离开“hh: mm”常量结束时刻数据数据长度-1到达“hh: mm”常量循环函数常量时间现在迄今为止,//过滤数据集为当前时间的活动航班常量currentData数据过滤器d= >返回ddepartureDate< =时间& &时间< =darrivalDate渲染currentData,时间如果现在< =结束//增加5m, 500ms后再次调用循环现在现在添加5“分钟”setTimeout循环500

输入、更新和退出

D3允许你在以下情况下指定元素的转换和过渡:

  • 输入新的数据点(输入)
  • 现有数据点变更(更新)
  • 删除现有数据点(退出)
常量渲染函数数据时间//显示时间d3选择“.time”文本时刻时间格式“hh: mm”//选择d3并应用我们的数据集常量飞行d3选择“图号”selectAll“g.flight”数据数据d= >did//为任何id不在DOM中的数据点输入新节点常量newFlight飞行输入附加“g”attr“类”“飞行”常量xPointd= >dxScale时间常量yPointd= >One hundred.+25newFlight附加“圆”attr“类”“flight-dot”attr“cx”xPointattr“cy”yPointattr“r”“5”//用数据中的id更新select中现有的节点飞行选择“.flight-dot”attr“cx”xPointattr“cy”yPoint//退出id不在数据中的旧节点常量oldFlight飞行退出删除

转换

上面的代码以5分钟的时间增量,每500ms渲染一帧:

  • 它会更新时间
  • 创建一个新的飞行组,每个飞行都有一个圆圈
  • 更新当前航班的x/y坐标
  • 当他们到达时,移除飞行小组

这是可行的,但我们真正想要的是每个帧之间的平滑过渡。我们可以通过在任何D3选择上创建过渡,并在设置属性或样式属性之前提供持续时间和缓和功能来实现这一点。

例如,让我们在进入飞行组的不透明性中逐渐淡化。

常量newFlight飞行输入附加“g”attr“类”“飞行”attr“不透明度”0newFlight过渡持续时间500attr“不透明度”1

让我们逐渐淡出正在起飞的航班群。

飞行退出过渡持续时间500attr“不透明度”0删除

在x点和y点之间添加平滑过渡。

飞行选择“.flight-dot”过渡持续时间500缓解“线性”attr“cx”xPointattr“cy”yPoint

方法还可以在5分钟增量之间转换时间,以便每分钟显示一次,而不是每5分钟显示一次渐变函数。

常量inFiveMinutes时刻时间添加5“分钟”迄今为止,常量d3插入时间,inFiveMinutesd3选择“.time”过渡持续时间500缓解“线性”渐变“文本”= >返回函数ttextContent时刻t格式“hh: mm”

t转换的进度值介于0和1之间。

要有创意

关于这个库还有很多我在本文中无法涵盖的内容,我很想深入挖掘一些更有意义的例子,但正如他们所说,你需要把马放在车前面。

还有很多例子D3画廊.如果你想了解更多,我强烈推荐Scott Murray的D3教程还有D3文档,这很好。

希望这个高水平的概述和一些实际的例子已经给了你一个如何使用选择,缩放和过渡的想法。考虑最好的方法来表示您的数据,并创建您自己独特的数据可视化。请在评论中留言告诉我你已经用D3构建!

Baidu