[ 生活需要仪式感 ]

0%

D3.js学习笔记

D3全称是数据驱动文档,是一个js库,用于数据可视化。基本上都是基于svg来实现的。写法与js语法类似,同时使用的还是链式语法。

开发准备

在D3的[官网]可以下载到最新版的压缩包,然后get到解压到文件目录,开发时调用就好。

1.把压缩包解压后除了授权许可外,还有一个d3.js和d3.min.js。这2个文件其实是一样的,只是d3.js有空格区分方便阅读,而实际开发中可以引用d3.min.js,因为体积更小,用户更易加载。
2.注意引用的时候,除了src,还要加上charset="utf-8,不然一些特殊字符会显示不出来。

做一个完整的柱状图中的重点

选择集

d3.select():选择该元素的第一个
d3.selectAll():选择该元素的全部
主要是这2个函数,作用是选中括号中的元素,选中的集合(可以是空集)就叫做选择集。

实例

1
2
3
4
5
6
7
8
//选择<body>中所有的<p>,并把内容改为or2.in,选择集保存在变量 p 中
var p = d3.select("body")
.selectAll("p")
.text("or2.in");

//修改段落的颜色和字体大小
p.style("color","red")
.style("font-size","72px");

数据绑定

D3一个特性是把数据绑定到元素上,如把整数5与段落<p>绑定。这个特性的一个简单应用是后面能够把数据绑定到矩形上,从而形成以数据定义高度的柱形图。

datum():绑定单一数据到整个选择集上。
data():绑定一个数组到选择集上,数组中每一个值分别与各元素绑定。

提出一个配合数据绑定功能的常用无名函数function(d,i):
d:代表数据,也就是与某元素绑定的数据。
i:代表索引,代表数据的索引号,从 0 开始。

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//原页面代码
<p>One</p>
<p>Two</p>
<p>Three</p>

//D3.js部分的代码
var body = d3.select("body");
var p = body.selectAll("p");
var dataset = ["hi","hello","aha"];
p.data(dataset)
.text(function(d,i){
return "第"+i+"个元素绑定的数据是"+d;
});

------------<显示的效果>------------
1个元素绑定的数据是hi
2个元素绑定的数据是hello
3个元素绑定的数据是aha

读取数据

d3.json(url[, callback]): 读取json数据
d3.text(url[, mimeType][, callback]): 读取txt数据

比例尺

比例尺(Scale)是D3中极为重要的基础函数。数据可视化时,实际数据转换成图像中合适的数据。比如数据A是15,占了总数据的**5%**,那么比例尺的作用就是把15转换为5%,这种自动转换在复杂数据可视化中显得极为必要和重要。
d3.scale.ordinal():序数比例尺
d3.scale.linear():线性比例尺

比例尺的转化就像函数的y=f(x),我们设定定义域(原始数据)值域(转换后数据的范围),D3为我们自动运行这个函数,并从原始数据中得出目标数据。

序数比例尺的值域尝试使用.rangeRoundBands来代替.range,因为.rangeRoundBands是用几个离散区间来分割一个连续的区间,区间边界和宽度会取整。这样子就避免了值域是离散的

实例

1
2
3
4
5
6
7
8
9
10
11
12
var xScale = d3.scale.ordinal()//序数比例尺
.domain([0, 1, 2, 3, 4, 5, 6])//定义域
.rangeRoundBands([0,300]);//定义值域

var yScale = d3.scale.linear()//线性比例尺
.domain([100, 0])//定义域
.range([0, 250]);//值域

console.log(xScale(6));
------------<显示的效果>------------
控制台显示的效果就是->300

坐标轴

SVG中本身并没有提供坐标轴功能,但是D3为我们提供了这个函数使得我们可以方便创建坐标轴后以Group形式在svg中添加。

d3.svg.axis():创建新的坐标轴。

实例

1
2
3
4
5
6
7
8
9
10
11
12
//创建新的坐标轴
var axis = d3.svg.axis()
.scale(linear) //指定比例尺
.orient("bottom") //指定刻度的方向
.ticks(7); //指定刻度的数量

//在SVG中添加坐标轴
svg.append("g") //添加一个group(组合)元素
.attr("class","axis") //给坐标轴赋予一个样式
.attr("transform","translate(20,130)")//在svg中平移
.call(axis);//调用axis函数渲染

1.D3中某些变量被赋予D3属性后,它能够作为函数来使用。
2.Call函数就是被调用函数请求目标函数把其作为变量来调用

关于选择集与数据量不对应的情况

关于Update、Enter、Exit这3个概念,是D3为了处理当选择集与数据的数量关系不确定的情况。

update:有数据,也有足够图形元素。一一绑定的部分是update
enter:有数据,可是没有足够图形元素相匹配。增加补充用于绑定数据的部分是enter
exit:有数据,但是图形元素过多时。没被绑定的是部分是exit

D3做柱形图的常用办法是:选择一个矩形空集,然后通过enter来后续自动添加足够数量的矩形元素,并且绑定数据。

实例

1
2
3
4
svg.selectAll("rect")   //选择svg内所有的矩形
.data(dataset) //绑定数组
.enter() //指定选择集的enter部分
.append("rect") //添加足够数量的矩形元素

实现完整的柱状图

1.创建一个SVG画布

1
2
3
4
5
6
7
8
9
10
11
//定义画布大小
var width = 400;
var height =400;
//创建一个svg画布
var body = d3.select("body")
.append("svg")
.attr("width",width)
.attr("height",height);

//给画布周围留白,默认单位是px
var padding = {left:30,right:30,top:20,bottom:20};

2.定义数据与比例尺

1
2
3
4
5
6
7
8
9
10
11
//定义一个数据数组
var dataset=[20,30,40,50,42,25];

//X轴的比例尺:序数比例尺
var xScale = d3.scale.ordinal()
.domain(d3.range(dateset.lenth))//d3.range获得一个数组([0,1,2,3,4,5])
.rangeRoundBands([0,width-padding.left - padding.right]);
//Y轴的比例尺:线性比例尺
var yScale = d3.scale.linear()
.domain([0,d3.max(dataset)])
.range([height-padding.top - padding.bottom,0]);//注意大数先写,因为y轴转换后,上到下是从大到小

3.定义坐标轴

1
2
3
4
5
6
7
8
9
//定义X轴
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")//刻度朝向下
//定义Y轴
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")//刻度朝向左

4.添加矩形和文字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//间隔矩形的留白
var rectPadding=4;

//添加矩形
var rects = avg.selectAll(".MyRect")
.data(dataset)
.enter()
.append("rect")
.attr("class","MyRect")
.attr("transform","translate("+padding.left+","padding.top+")")
.attr("x",function(d,i){
return xScale(i)+rectPadding/2;
})
.attr("y",function(d){
return yScale(d);
})
.attr("width",xScale.rangeBand()-rectPadding)//rangeBand()获取离散区间的宽度
.attr("height",function(d){
return height - padding.top = padding.bottom - yScale(d);
});

//添加文字
var texts = avg.selectAll(".MyText")
.data(dataset)
.enter()
.append("text")
.attr("class","MyText")
.attr("transform","translate("+padding.left+","padding.top+")")
.attr("x",function(d,i){
return xScale(i)+rectPadding/2;
})
.attr("y",function(d){
return yScale(d);
})
.attr("dx",function(){
(xScale.rangeBand()-rectPadding)/2});
.attr("dy",function(d){
return 20;
})
.text(function(d){
return d;
});

5.添加坐标轴的元素

1
2
3
4
5
6
7
8
9
10
11
//添加x轴
svg.append("g")
.attr("class","axis")
.attr("transform","translate("+padding.left+","+(height - padding.bottom)+")")
.call(xAxis);

//添加y轴
svg.append("g")
.attr("class","axis")
.attr("transform","translate("+ padding.left +","+padding.top +")")
.call(yAxis);

6.别忘了把渲染代码加上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<style>
.axis path,
.axis line{
fill: none;
stroke: black;
shape-rendering: crispEdges;
}

.axis text {
font-family: sans-serif;
font-size: 11px;
}

.MyRect {
fill: steelblue;
}

.MyText {
fill: white;
text-anchor: middle;
}
</style>

本教程是学习了OurD3JS的文章&视频所受到启发写的笔记,推荐一下这个网站,写的的确很好,[链接跳转]