D3是什么?狭义的理解是一个JavaScript可视化库。通过操作HTML的基础元素或SVG元素构建可视化图形,绘制出精美交互性强的可视化图像。D3是Data-Driven Documents的简写,一个基于数据操纵文档的JavaScript库,文档指的是HTML的DOM,即文档对象模型(Document Object Model),D3提供了各种实用的方法将数据绑定到DOM,根据数据操纵文档,画图只是它的功能之一。
D3第一行代码
D3操作的是Web上的文档,可以便捷快速地生成和发布可视化作品,对操作系统和设备的依赖很低。
D3库的功能和特点:
- 将数据和DOM绑定在一起、图形随着数据变化;
- 数据转换和绘制独立;不是提供Pie()这类函数绘图而是将数据转换成饼图数据,再按需绘图。像面粉可以做出各种糕点而不是直接提供面条;
- 擅长矢量图形,缩放不损失图形精度,不擅长位图和瓦片,不擅长探索型可视化;
- 作为HTML文档,不隐藏原始数据,如果不想共享数据,为什么还要将它们可视化呢?
D3本质上还是JavaScript,这意味着我们可以用原生JavaScript代码实现讲到的所有功能,但D3对各种常用操作进行了很好的封装,大大减轻了做可视化的工作量并应对各种需求。用D3做可视化的代码框架如下:
1 |
|
来细看这段代码,除d3.select("body")...
句外,都是通用的HTML代码,D3的第一行代码就只是d3.select("body").append("p").text("hello world!");
。HTML标记中,
<p></p>
),并把文本内容hello world!
添加给这个段落。
需要说明的是,本系列笔记都基于v6.x版本,v5之后的版本和网上各种教程用的v3.x差别还挺大的,亲测一些书籍和教程里的写法都不能正常运行了,典型的一些例子后续具体内容里会提到。
总结一下D3可视化的基本步骤如下:
- 创建新元素并绑定数据(html的元素可理解为划定区域和声明类型的闭合标签,如p表示其是一个段落,是段落就可以有段落文本、长宽、id等属性和标识);
- 设置相应元素的可视属性,将数据值映射为元素大小、颜色、位置等可视属性;
- 对元素进行排列和变换,还有响应交互;
D3那句链式调用了.select()、append()等,也可以用中间变量承接,写成:
1 | //拆成多个语句的写法: |
原始HTML文档和浏览器中D3代码发挥作用后生成的HTML文档对比效果如下,左边是原始代码,右边的HTML文档中
标签里多了一行文本hello world!
。幻化万千的返璞归真
操纵<p>
等HTML标签是牛刀小试,绘制可视化图形主流做法是生成和操作<svg>
标签生成点线面,再组合成柱图、饼图、地图等可视化图表。
1 | var svg=d3.select("body").append("svg") |
画一个完整的统计图表还需要绘制坐标轴、加文本标签、加标题/图例等图元,这些d3都可以通过操纵<svg>
实现。
1 | var dataset = [76,37,90,60,50]; |
数据+坐标系+布局+文本图元,最终幻化万千可视图。
D3基础技术概念
为了更方便地理解D3代码和实现原理,本节对d3可视化设计到的一些前端技术概念进行概述,如果对HTML、CSS、JavaScript、SVG很了解可以跳过这部分。
HTML
HTML(Hypertext Markup Language, 超文本标记语言) ,用于向浏览器说明内容的标记结构,例如显示什么文字、用段落显示还是表格显示等。HTML 的核心功能就是让你“标记”内容,进而给出结构。文字还是那些文字,但加上结构之后,可读性就不一样了。HTML每个元素都有一个标记标签(Markup Tag)。之前的代码里就用到了<html>
、<body>
、<p>
等标签,都是用一对尖括号包围的。标签有成对出现的,如<p></p>
;也有不成对出现的,如<br/>
。
HTML 有上百个元素,日常使用和d3学习中只需要知道少数几种。拿之前的d3代码框架对照着看:
1 |
|
<!DOCTYPE html>
:这是标准的文档类型声明,必须在文档的第一行,不是HTML标签,其主要目
的是告诉浏览器HTML的版本信息。html标签:包含文档中的所有 HTML 内容;
head:文档的头部,包含所有文档的元数据。比如标题和对外部样式表、脚本的引用。里面的标签有title、meta、script等;
meta:定义文档的元数据内容,没有结束标签,内容作为属性写在标签里;例如
<meta charset="utf-8">
;title:文档的标题。浏览器会把这个元素的内容显示在窗口标题栏中,并在收藏网页时使用这一标题;典型写法如
<title>D3可视化代码框架</title>
;body:所有不包含在 head 中的内容,都包含在 body 中。这里面的内容是可以在网页中看到的;
h1 、 h2 、 h3 、 h4、h5:用于标记不同级别的标题。 h1 代表顶级标题, h2 代表二级标题,依此类推;
ul 、 ol 、 li:ul 用于标记无序列表,也就是带项目符号的列表, ol 用于标记有序列表,带编号。 ul 和 ol 都包含 li 元素,用于标记列表项;
p:一个段落;
strong:加粗文本,表示额外强调,
<b>
标签也是加粗文本;em:表示强调,显示斜体文本,
<i>
标签表示的是一般的斜体文本;span:任意文本,一般都包含在 p 这样的大容器元素中;
div:任意文本块,常用于分组相关元素和个性化内容;
a:链接,一般显示为带下划线的蓝色文本,例如
<a href="https://d3js.org/">D3网站</a>
;link:用于引用外部资源,如引用同一文件夹下的css文件:
<link rel="stylesheet" type="text/css" href="style.css" />
;style:用于在文档中定义CSS样式;如果内容很多,则建议写在外部文件中,再用
<link>
标签引用;script:用于定义客户端脚本,最常见的是JavaScript脚本,我们写的d3代码在
<script> </script>
标签里;注释:html里注释的写法为
<!-- 要注释的内容 -->
;
DOM,指文档对象模型(Document Object Model),是针对结构化文档的一个接口,它允许程序和脚本动态地访问和修改文档。使用这套模型即可任意访问和修改HTML元素。D3中的函数大量脱胎于DOM。DOM是以树形结构来描述HTML文档的,其被称为节点树,每个HTML元素都是树上的一个节点。
CSS
CSS(Cascading Style Sheets,层叠样式表)控制 DOM 元素的视觉外观,用于定义HTML元素的样式,如字体大小、背景颜色、布局等。一个CSS语句例子和效果如下:
CSS 样式由选择符和属性组成。选择符后面跟着属性,被一对花括号所包围。属性和值由冒号分隔,每个属性声明以分号结尾。相同的属性可以应用给多个选择符,只要用逗号分隔选择符即可。
1 | 选择符 A, |
JavaScript
JavaScript 是动态脚本语言,通过操作 DOM 动态修改页面。D3是一个JavaScript库,也就是说D3的写法符合JavaScript的语法规范。
JavaScript单行注释用//
,多行注释用 /* */
,和C家族的语言一致,css的注释也是用的 /* */
,和JavaScript一样。JavaScript区分大小写,每条语句结尾用分号(;)标识,是弱类型语言,声明变量通常用var,不论是浮点数、字符串或者数组,都可以用var,通过var a=5;
给变量a赋值5。也可以写let a=5
。
1 | var pi=3.14; //数值 |
数值间的加(+)、减(-)、乘(*)、除(/)、比较运算等都是常规的写法。
分支和循环的写法和C语言家族基本一致,函数通过function(arr){return arr}
定义。
1 | if (t==true){ |
JavaScript脚本除了直接写在HTML的<script>
标签里,也可以保存在独立的js文件里,通过<script type="text/javascript" src="d3-learning.js"></script>
引入。
SVG
SVG(Scalable Vector Graphics,可伸缩矢量图形)基于XML标签来表示图形。基于HTML文档的可视化基本都使用canvas或svg元素作为数据到图形的映射容器。D3也可以直接操作div或其他原生HTML元素来绘图,但这就显得笨重不灵活,且容易出现浏览器间不一致的问题。而用 SVG就更可靠,图形效果更一致,且绘图速度更快。
SVG 元素可以理解为能在上面绘制各种形状的画布。一个基础的svg示例如下,描述了一个半径为20像素的圆形,在网页端就可以显示为一个圆形。
1 | <svg width="500" height="50"> |
在SVG的预定义元素里,有6种基本元素rect(矩形)、circle(圆形)、ellipse(椭圆)、line(线段)、polyline(折线)、polygon(多边形)和功能强大的path(路径),在SVG里也可以添加text(文本)元素。
和一些编程语言的坐标系统一样,基于像素的坐标系统的原点位于画布的左上角。这意味着增大 x 的值,图形会向右移动;增大 y 值,图形会向下移动。
关于于 SVG 元素,最关键是要记住它们的各个方面都是通过属性来设定的。换句话说,就是通过标签中的属性:值对来指定 SVG 元素的各方面特征,比如:<rect x="30"></rect>
如果熟悉HTML就会觉得很容易上手<p class="lyndon">txt</p>
,毕竟都是基于XML进行标记数据。
D3学习资源
D3库一些实用的文档和资源。D3官网有最新版本最权威的API列表和各种示例的链接,有个中文版的文档网站https://d3js.org.cn/;
- 各种d3案例:https://bl.ocks.org/mbostock
- 可以用函数名称等检索bl.ocks的网站:http://bl.ocksplorer.org/
- 基于d3的动态可视化封装js库:https://github.com/NPashaP/Viz
- 专门为探索大型、多维数据集而进行优化的js库:http://dc-js.github.io/dc.js/
- 基于d3画动态排序条形图:Historical-ranking-data-visualization-based-on-d3
总结
D3是一个基于数据操纵文档的JavaScript库,大家普遍用来作为可视化库,可以绘制出丰富的可视化图表,很多JavaScript库基于D3来绘图,很多Python可视化库基于d3封装,例如altair、bokeh、bqplot、mpld3等等,足以见其影响力,而且经过这些年的发展,d3有着丰富的实例库和和生态。深入学d3的好处在于可以体验从点线面到可视化图形的成就感,加深对SVG的了解,更深刻地理解一些可视化库的原理和接口设置,有更底层的视野和感悟。
后续文章继续学习用D3操作svg从0到1绘制包含交互统计图。