目录
D3是什么?
D3 的全称是(Data-Driven Documents),顾名思义可以知道是一个被数据驱动的文档。
D3的本质是JavaScript,所以用JavaScript可以实现它全部的功能,但是有这个函数库可以极大的减少工作量,尤其在数据可视化方面。
D3对JavaScript的简化
基本JavaScript代码实现文本替换:
<html>
<head>
<meta charset="utf-8">
<title>HelloWorld</title>
</head>
<body>
<p>Hello World 1</p>
<p>Hello World 2</p>
<script>
var paragraphs = document.getElementsByTagName("p");
for (var i = 0; i < paragraphs.length; i++) {
var paragraph = paragraphs.item(i);
paragraph.innerHTML = "I like dog.";
}
</script>
</body>
</html>
用D3简化;
<html>
<head>
<meta charset="utf-8">
<title>HelloWorld</title>
</head>
<body>
<p>Hello World 1</p>
<p>Hello World 2</p>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script>
d3.select("body").selectAll("p").text("www.ourd3js.com");
</script>
</body>
</html>
2.选择集与数据绑定
可以看到,D3的使用是链式语法,通过连续不断地调用函数来实现。
使用d3.select()
或 d3.selectAll()
选择元素后返回的对象,就是选择集。
选择集的常见用法如下:
var body = d3.select("body"); //选择文档中的body元素
var p1 = body.select("p"); //选择body中的第一个p元素
var p = body.selectAll("p"); //选择body中的所有p元素
var svg = body.select("svg"); //选择body中的svg元素
var rects = svg.selectAll("rect"); //选择svg中所有的svg元素
如何绑定数据
D3可以将数据绑定到DOM上。绑定之后,当需要依靠这个数据才能操作元素的时候,就会更加方便。
D3中是通过以下两个函数来绑定数据的:
datum()
:绑定一个数据到选择集上data()
:绑定一个数组到选择集上,数组的各项值分别与选择集的各元素绑定
假设现在有如下三个段落元素。
<p>Apple</p>
<p>Pear</p>
<p>Banana</p>
datum()的使用
将字符串“China”与段落元素<p>
绑定。代码如下:
var str = "China";
var body = d3.select("body");
var p = body.selectAll("p");
p.datum(str);
p.text(function(d, i){
return "第 "+ i + " 个元素绑定的数据是 " + d;
});
结果如下:
第 0 个元素绑定的数据是 China
第 1 个元素绑定的数据是 China
第 2 个元素绑定的数据是 China
在上面的代码中,用到了一个无名函数 function(d, i)
。当选择集需要使用被绑定的数据时,常需要这么使用。其包含两个参数,其中:
- d 代表数据,也就是与某元素绑定的数据。
- i 代表索引,代表数据的索引号,从 0 开始。
data()的使用
var dataset = ["I like dog","I like cat","I like snake"];
上述为一个数组,现在分别将数组中的三串字符与Apple、pear、banana绑定并替换,代码如下:
var body = d3.select("body");
var p = body.selectAll("p");
p.data(dataset)
.text(function(d, i){
return d;
});
3. 使用d3在SVG画布中绘图
SVG 有如下特点:
- SVG 绘制的是矢量图,因此对图像进行放大不会失真。
- 基于 XML,可以为每个元素添加 JavaScript 事件处理器。
- 每个图形均视为对象,更改对象的属性,图形也会改变。
- 不适合游戏应用。
Canvas是通过 JavaScript 来绘制 2D 图形,是 HTML 5 中新增的元素。 有如下特点:
- 绘制的是位图,图像放大后会失真。
- 不支持事件处理器。
- 能够以 .png 或 .jpg 格式保存图像
- 适合游戏应用
var width = 300; //画布的宽度
var height = 300; //画布的高度
var svg = d3.select("body") //选择文档中的body元素
.append("svg") //添加一个svg元素
.attr("width", width) //设定宽度
.attr("height", height); //设定高度
4. 比例尺的使用
比例尺的存在是为了调整比例差距悬殊的数据在同一个画布的显示。
我们需要一种关系,能够将某一区域的值映射到另一区域,其大小关系不变。
4.1 线性比例尺
// 有以下数组:
var dateset = [1.2, 2.3, 0.9, 1.5, 3.3];
//要求将dataset中最小的值映射成0;最大的映射成300
var min = d3.min(dataset); //使用d3计算最小值
var max = d3.max(dataset);
var linear = d3.scale.linear()
.domain([min, max])
.range([0, 300]);
linear(0.9); //返回0
linear(2.3); //返回175
linear(3.3); //返回300
其中,d3.scale.linear()
返回一个线性比例尺。domain()
和 range()
分别设定比例尺的定义域和值域。
4.2 序数比例尺
有时候定义域与值域不一定连续。
//有如下两个数组:
var index = [0, 1, 2, 3, 4];
var color = ["red", "blue", "green", "yellow", "black"];
//希望将数字与颜色对应起来,但这些值都是离散的,线性比例尺不适合,需要用到序列比例尺
var ordinal = d3.scale.ordinal()
.domain(index)
.range(color);
ordinal(0); //返回 red
ordinal(2); //返回 green
ordinal(4); //返回 black
4.3 给柱形图添加比例尺
var dataset = [ 2.5 , 2.1 , 1.7 , 1.3 , 0.9 ];
//使用线性比例尺映射
var linear = d3.scale.linear()
.domain([0, d3.max(dataset)])
.range([0, 250]);
//画一个矩形
var rectHeight = 25; //每个矩形所占的像素高度(包括空白)
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x",20)
.attr("y",function(d,i){
return i * rectHeight;
})
.attr("width",function(d){
return linear(d); //在这里用比例尺
})
.attr("height",rectHeight-2)
.attr("fill","steelblue");
5. 坐标轴
D3 提供了一个组件:d3.svg.axis()
,帮助我们完成SVG中复杂的坐标轴绘制。
//定义坐标轴
var dataset = [ 2.5 , 2.1 , 1.7 , 1.3 , 0.9 ]; //数据
var linear = d3.scale.linear() //定义比例尺
.domain([0, d3.max(dataset)])
.range([0, 250]);
var axis = d3.svg.axis() //坐标轴组件,在svg中生成组成坐标轴的元素
.scale(linear) //指定线性比例尺
.orient("bottom") //指定刻度的方向,bottom表示刻度在坐标轴的下方显示
.ticks(7); //指定刻度的数量
定义好坐标轴之后,需要在SVG中添加一个分组元素,再将坐标轴的其他元素添加到其中:
svg.append("g")
.call(axis);
6. 理解update、enter、exit
Update、Enter、Exit 是 D3 中三个非常重要的概念,它处理的是当选择集和数据的数量关系不确定的情况。
当元素数量与数组长度不一致时,进行绑定时就需要update、enter、exit的概念。
假设,dataset = [1, 2, 3, 4, 5]
,需要与三个<p>
元素绑定,那么就会有两个数据没有元素与之对应,这时候D3会建立两个空的元素与数据对应,这一部分就称为 Enter。而有元素与之对应的部分称为update。
假设,dateset = [1]
,这会出现两个元素没有数据与其绑定,啧没有数据绑定的部分称为exit。
总结:
元素数量 = 数组长度——update
元素数量< 数组长度——enter
元素数量 > 数据长度——exit
var dataset = [ 3 , 6 , 9 , 12 , 15 ];
//选择body中的p元素
var p = d3.select("body").selectAll("p");
//获取update部分
var update = p.data(dataset);
//获取enter部分
var enter = update.enter();
//update部分的处理:更新属性值
update.text(function(d){
return "update " + d;
});
//enter部分的处理:添加元素后赋予属性值
enter.append("p")
.text(function(d){
return "enter " + d;
});
var dataset = [ 3 ];
//选择body中的p元素
var p = d3.select("body").selectAll("p");
//获取update部分
var update = p.data(dataset);
//获取exit部分
var exit = update.exit();
//update部分的处理:更新属性值
update.text(function(d){
return "update " + d;
});
//exit部分的处理:修改p元素的属性
exit.text(function(d){
return "exit";
});
//exit部分的处理办法:通常是删除元素
// exit.remove();
7. 交互操作
在 D3 中,每一个选择集都有 on() 函数,用于添加事件监听器。
var circle = svg.append("circle");
circle.on("click", function(){
//在这里添加交互内容
});
鼠标常用的事件有:
click:鼠标单击某元素时,相当于 mousedown 和 mouseup 组合在一起。
- mouseover:光标放在某元素上。
- mouseout:光标从某元素上移出来时。
- mousemove:鼠标被移动的时候。
- mousedown:鼠标按钮被按下。
- mouseup:鼠标按钮被松开。
- dblclick:鼠标双击。
键盘常用的事件有三个:
- keydown:当用户按下任意键时触发,按住不放会重复触发此事件。该事件不会区分字母的大小写,例如“A”和“a”被视为一致。
- keypress:当用户按下字符键(大小写字母、数字、加号、等号、回车等)时触发,按住不放会重复触发此事件。该事件区分字母的大小写。
- keyup:当用户释放键时触发,不区分字母的大小写。