D3.js
(
D3
或
Data-Driven Documents
)
是一个使用动态图形进行资料可视化的
JavaScript程序库。
与W3C标准兼容,
并且利用广泛实现的SVG
、JavaScript
和CSS标准
,
改良自早期的Protovis程序库
。
与其他的程序库相比,
D3对视图结果有很大的可控性。
D3是2011年面世的,
同年的8月发布了2.0.0版。
到2018年4月,
D3已被更新到了5.5.0版。
D3.js
已被数十万个网站使用,
最常被运用在
在线新闻网站
呈现交互式图形、
呈现数据资料的图表
和呈现含有地理信息的资料。
另外SVG的输出功能
也使得D3.js
能用于印刷出版物
的绘制上。
历史
在D3.js
开发之前
已经有出现过
许多尝试做资料可视化的包,
例如Prefuse
,Flare
和Protovis程序库
,
他们都可以视为D3.js
的前身。
然而Prefuse
和Flare
皆有缺点,
皆不能
只透过浏览器完成渲染,
皆须要透过额外插件
来完成。
例如
2005年发布的Prefuse
是一个资料可视化程序库,
但是它需要透过
网页的Java插件
才能于浏览器中呈现;
而Flare
是2007年
发布的另一个资料可视化工具包
,
由于其是使用ActionScript编程语言
开发,
因此也需要额外插件,
即Flash插件
才能完成渲染。
2009年,
史丹佛大学
的史丹佛可视化团队
(Stanford Visualization Group)
的杰佛瑞·赫尔
、迈克·保斯托
和瓦迪姆·欧格菲兹齐
利用开发Prefuse
和Flare
的经验
开始用Javscript开发了
可从给定资料产生SVG图形的Protovis程序库
。
而Protovis程序库
在业界和学界皆有一定的知名度。
2011年
,
史丹佛可视化团队
停止开发Protovis
,
并开始开发新的资料可视化程序库,
借由之前开发Protovis
的经验,
开发出了D3.js
程序库,
在注重于Web标准的同时
提供了更丰富的平台
也有了更好的性能。
技术原理
D3.js
透过预先创建好
嵌入于网页中的JavaScript函数
来选择网页元素
、创建SVG元素
、调整CSS
来呈现资料
,
并且也可以
设置动画
、
动态改变对象状态
或
加入工具提示
来完成用户交互功能。
使用简单的D3.js函数
就能够将大型的数据
数据结构与SVG对象
进行绑定,
并且能生成格式化文本
和各种图表
。
其数据
数据结构的格式
可以是JSON
、CSV
(以逗号分隔的资料)或GeoJSON
,
也可以透过
自己写JavaScript函数
来读取其他或自定义格式的资料,
例如Shapefile
。
对象选择
D3.js
所使用的对象选择方式是
透过使用CSS样式选择器
来选择一个或多个或一组文档对象模型对象
,
然后透过
类似jQuery
的方式
控制所选的对象。
例如,
选择所有的<p>...</p>
网页元素,
将之改成
方形类别、
移动位置、
并更换颜色为淡紫色。
在D3.js中只要使用简单的代码即可完成:
d3.selectAll("p") // 选择所有<p>网页元素
.style("color", "lavender") // 将颜色"color"样式改成"lavender"淡紫色 (薰衣草色)
.attr("class", "squares") // 将"class" 改成 "squares"
.attr("x", 50); // 将属性值 "x" (水平位置) 改为50px
动态改变对象状态
透过D3.js定义的对象
成员函数function transition (name)
则可以在一定时间内
平滑地改变对象的属性或样式的值
,
例如可以在500毫秒内
逐渐将所有的<p>...</p>网页元素
渐变为粉红色
:
d3.selectAll("p") // 选择所有 <p> 网页元素
.transition("trans_1") // 定义一个transition,命名为"trans_1"
.delay(0) // 触发后延迟0毫秒后开始动画
.duration(500) // 渐变时间500毫秒
.ease(d3.easeLinear) // 使用线性渐变,并且....
.style("color", "pink"); // ...並且最终变为粉红色
资料绑定
D3.js有提供一高级应用
例如
设置与对象相关系,
或者将加载的资料直接绘成对象。
在D3.js中,
可以将资料与对象绑定,
如此一来,
当资料读入之后
根据资料产生对应具有相关的属性
(形状、颜色或数值等)
和行为(动画或事件等)
的SVG对象。
// 数据
var countriesData = [
{ name:"Ireland", income:53000, life: 78, pop:6378, color: "black"},
{ name:"Norway", income:73000, life: 87, pop:5084, color: "blue" },
{ name:"Tanzania", income:27000, life: 50, pop:3407, color: "grey" }
];
// 建立svg网页物件
var svg = d3.select("#hook").append("svg")
.attr("width", 120)
.attr("height", 120)
.style("background-color", "#D0D0D0");
// 从资料建立关联的svg网页元素
svg.selectAll("circle") // 建立还不存在的圆形样板
.data(countriesData) // 绑定资料
.enter() // 对每个数据......
.append("circle") // 绑定数据列中的...... 资料到圆形
.attr("id", function(d) { return d.name }) // 圆形的id为国家名
.attr("cx", function(d) { return d.income / 1000 }) // 圆形的x坐标位置为收入
.attr("cy", function(d) { return d.life }) // 圆形的y坐标位置为预期收入
.attr("r", function(d) { return d.pop / 1000 *2 }) // 圆形的半径为国家人口数
.attr("fill", function(d) { return d.color }); // 给表示不同国家的圆形不同颜色
资料读取
D3.js除了有提供将加载的资料直接绘成对象的功能之外,
也支持从文件读取资料
并直接生成SVG图像。
此应用使得D3.js
可以用简单的代码
完成与地理信息相关的资料可视化,
而新版本的D3.js也改善了
地理座标的转换系统,
因此能准确地呈现包含地理信息的图表,
例如“japan.json”中
存了日本的GeoJSON地理信息
,
则D3.js可以直接并加载
并显示日本地图:
d3.json("japan.json", function(topodata) {//載入JSON檔案
var features = topojson.feature(//从GeoJSON中取出日本地形
topodata,
topodata.objects["japan"]
).features;
var path = d3.geo.path().projection(
d3.geo.mercator()
.center([138,37]) //指定为日本经纬度的位置
.scale(6000) //放大至符合圆形大小
);
d3.select("svg")
.selectAll("path") // 建立还不存在的路径物件样板
.data(features) // 绑定日本地形资料
.enter() // 对所有的物件.....
.append("path") // 插入路径物件
.attr("d",path); // 路径物件的路径依照日本经纬度位置填入地形资料
});
然而许多政府机关提供的文件皆为Shapefile
,
而由于D3.js也可以透过自己写JavaScript函数
或引用他第三方程式库
来读取其他例如Shapefile的资料:
//需先引入Shapefile库
shapefile.open("japan.shp") //载入日本的Shapefile档案
.then(source => source.read()
.then(function log(result) { //若Shapefile载入完毕
if (result.done) return;
console.log(result.value); //印出载入到的地理资讯
//下同
}))
.catch(error => console.error(error.stack));
根据资料产生节点
当文件顺利读入并与D3.js对象绑定之后,
一般D3.js在使用上
基本上会
明确地用.enter()函数、
暗示更新的函数
以及
.exit()函数
来调用资料集中范围内的资料,
其中,
d3.js没有“update()”
函数,
需要自行时
做对应功能来完成
enter
、update
以及exit
流程。
接在.enter()函数
后方的指令
会作用在
所有资料上
并设置到
前一段指令selectAll()
选择的网页元素中
所有未就绪的网页元素。
其他特色
除了D3.js之外
亦有许多可以抓取并处理资料的程序库,
例如jQuery,
但D3.js与jQuery不同于,
D3.js使用了数据驱动化来更有效地处理资料,
例如,
原先使用循环来处理资料,
并且要预先把网页元素产生出来,
而D3.js则可以使用select或selectAll来批量完成资料处理,
并会
会视情况自动生成所需的网页元素,
而使得网页有更多的弹性,
也能支持
能动态地即时地作出反应的交互性功能。
相关程序库
D3.js可以与Three.js结合,
透过结合了
D3.js的资料可视化、图表产生
与Three.js的WebGL特性
可以实现三维资料可视化、图表的呈现。