梦入琼楼寒有月,行过石树冻无烟

D3 坐标轴与刻度

坐标轴(Axis)通常在一些学术图表中进行运用,通常很多的情况下图表中数据都是经过比例尺内计算的出的大小与坐标位置,这个时候就需要刻度尺来进行标注,来辅助读者进行观看,可以通过下图来明显感受到差距:

通常的情况下,读者可会对图标的美观性专业性都会选择有坐标轴和刻度的图表,通常在 d3.js 中绘画出一个坐标轴需要以下方法的支持:

ID DA FA
d3.svg.axis() 创建一个默认的新坐标轴
axis(选择集) 将此坐标轴绑定到指定的选择集中(需要具有<svg><g>元素)
axis.scale() 设定或获取坐标轴的比例尺
axis.orient(top[bottom、left、right]) 设定或获取坐标轴的方向
刻度
axis.ticks() 设置或获取坐标轴的分割数(默认为10
axis.tickValues() 设置或获取坐标轴的指定刻度
axis.tickSize() 设置或获取坐标轴内外的刻度长度(默认为6
axis.innerTickSize() 设置或获取坐标轴内刻度的长度
axis.outerTickSize() 设置或获取坐标轴外刻度的长度
axis.tickFormat() 设置或获取刻度尺的格式单位

坐标轴

定义


在上图中我们主要先通过定义坐标轴的基本高度与宽度以及最终的位置,其主要分为四个阶段,分别为位置、添加、比例尺、坐标轴以及一个坐标轴的外部方法通过四个阶段可以生成一个标准且带有刻度尺的一个坐标轴。

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
// 定义坐标轴高度与宽度以及(x,y)的位置
var padding = {
width: 600,
height: 600,
translate: "translate(20,20)"
}

/*
1.选择body元素,并添加一个<svg>元素
2.并设置<svg>的高\宽为 600.
*/
var svg = d3.select("body")
.append("svg")
.attr("width", padding.width)
.attr("height", padding.height)

/* 比例尺 */
var xScale = d3.scale.linear()
.domain([0,10]) /* 定义域范围 */
.range([0,500]) /* 值域即为刻度尺长度 */

/*
坐标轴选择比例尺,设置比例尺位置为 "bottom" 即底部
*/
var axis = d3.svg.axis()
.scale(xScale)
.orient("bottom")

/*
在 svg 元素中添加一个包含坐标轴的:
1. 位置/走向 @transform
2. 样式 @class
3. 参数传递
*/
var gAxis = svg.append("g")
.attr("transform", padding.translate)
.attr("class","axis")
.call(axis) /* 将自身作为参数,传递给某个参数 */

bottom and left

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
```js
/* 定义高度与宽度,其中包括 x和y轴的宽度 */
var padding = {
width: 700,
height: 700,
xAxisWidth: 500,
yAxisWidth: 500,
right: 30,
bottom: 30,
left: 130,
}

// 定义数据
var center = [[1,1]]

/*
1.选择body元素,并添加一个<svg>元素
2.并设置<svg>的高\宽为 600.
*/
var svg = d3.select("body")
.append("svg")
.attr("width", padding.width)
.attr("height", padding.height)

/* x/y 轴比例尺 */
var xScale = d3.scale.linear()
.domain([0, 1 * d3.max(center, function(d) {
return d[1];
})])
.range([0, padding.xAxisWidth])

var yScale = d3.scale.linear()
.domain([0, 1 * d3.max(center, function(d) {
return d[1];
})])
.range([0, padding.yAxisWidth])

/* x/y 坐标轴选择比例尺 */
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(5)

yScale.range([padding.yAxisWidth, 0]) /* 反向输出 */

var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.ticks(5)

/* 在 svg 元素中添加一个包含坐标轴的数据并计算出位置 */
svg.append("g")
.attr("class","axis")
.attr("transform", "translate(" + padding.left + "," + (padding.height - padding.bottom) + ")")
.call(xAxis)
svg.append("g")
.attr("class","axis")
.attr("transform", "translate(" + padding.left + "," + (padding.height - padding.bottom - padding.yAxisWidth) + ")")
.call(yAxis)

样式


除了生成 svg 坐标轴之外,我们还需要通过为path(路径)、line(刻度尺)、text(文本)这三个svg元素添加样式,让其变得简洁。

less

1
2
3
4
5
6
7
8
9
10
11
12
@color: #929292;
.axis path, /* 坐标轴路径设置 */
.axis line { /* 设置 坐标轴的线条 */
fill: none; /* 设置坐标轴宽度 */
stroke: @color; /* 坐标轴颜色 */
shape-rendering: crispEdges; /* 将形状渲染为清晰的边缘 */
}

.axis text {
font-size: 14px;
stroke: @color;
}

css

1
2
3
4
5
6
7
8
9
10
11
.axis path,   /* 坐标轴路径设置 */
.axis line { /* 设置 坐标轴的线条 */
fill: none; /* 设置坐标轴宽度 */
stroke: #929292; /* 坐标轴颜色 */
shape-rendering: crispEdges; /* 将形状渲染为清晰的边缘 */
}

.axis text {
font-size: 14px;
stroke: #929292;
}

刻度

刻度,主要依赖于坐标轴,是一个专业学术图表中较为重要的一部分。我们可以通过属性或方法来定义刻度的方向、间隔、长度、文字格式等。

刻度位置

ticks()


通常的情况下ticks()主要用于控制刻度尺的生成,在 d3.js 中 ticks的概念是指:“一个至到另一个分割的特定数量”,即分割的数量。如将ticks()设置为5,那么将会输出具有刻度为0,2,4,6,8,10的坐标轴。

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
// 定义坐标轴高度与宽度以及(x,y)的位置
var padding = {
width: 600,
height: 600,
translate: "translate(20,20)"
}

/*
1.选择body元素,并添加一个<svg>元素
2.并设置<svg>的高\宽为 600.
*/
var svg = d3.select("body")
.append("svg")
.attr("width", padding.width)
.attr("height", padding.height)

/* 比例尺 */
var xScale = d3.scale.linear()
.domain([0,10]) /* 定义域范围 */
.range([0,500]) /* 值域即为刻度尺长度 */

/*
坐标轴选择比例尺,设置比例尺位置为 "bottom" 即底部
*/
var axis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(5);

/*
在 svg 元素中添加一个包含坐标轴的:
1. 位置/走向 @transform
2. 样式 @class
3. 参数传递
*/
var gAxis = svg.append("g")
.attr("transform", padding.translate)
.attr("class","axis")
.call(axis) /* 将自身作为参数,传递给某个参数 */

tickValues()

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

```js
// 定义坐标轴高度与宽度以及(x,y)的位置
var padding = {
width: 600,
height: 600,
translate: "translate(20,20)"
}

/*
1.选择body元素,并添加一个<svg>元素
2.并设置<svg>的高\宽为 600.
*/
var svg = d3.select("body")
.append("svg")
.attr("width", padding.width)
.attr("height", padding.height)

/* 比例尺 */
var xScale = d3.scale.linear()
.domain([0,10]) /* 定义域范围 */
.range([0,500]) /* 值域即为刻度尺长度 */

/*
坐标轴选择比例尺,设置比例尺位置为 "bottom" 即底部
*/
var axis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.tickValues([0, 2.2, 4, 6, 8, 10])

/*
在 svg 元素中添加一个包含坐标轴的:
1. 位置/走向 @transform
2. 样式 @class
3. 参数传递
*/
var gAxis = svg.append("g")
.attr("transform", padding.translate)
.attr("class","axis")
.call(axis) /* 将自身作为参数,传递给某个参数 */

刻度长度

tickSize()

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

```js
// 定义坐标轴高度与宽度以及(x,y)的位置
var padding = {
width: 600,
height: 600,
translate: "translate(20,20)"
}

/*
1.选择body元素,并添加一个<svg>元素
2.并设置<svg>的高\宽为 600.
*/
var svg = d3.select("body")
.append("svg")
.attr("width", padding.width)
.attr("height", padding.height)

/* 比例尺 */
var xScale = d3.scale.linear()
.domain([0,10]) /* 定义域范围 */
.range([0,500]) /* 值域即为刻度尺长度 */

/*
坐标轴选择比例尺,设置比例尺位置为 "bottom" 即底部
*/
var axis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.tickSize(6,8)

/*
在 svg 元素中添加一个包含坐标轴的:
1. 位置/走向 @transform
2. 样式 @class
3. 参数传递
*/
var gAxis = svg.append("g")
.attr("transform", padding.translate)
.attr("class","axis")
.call(axis) /* 将自身作为参数,传递给某个参数 */

innerTickSize() and outerTickSize()

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
43

```js
// 定义坐标轴高度与宽度以及(x,y)的位置
var padding = {
width: 600,
height: 600,
translate: "translate(20,20)"
}

/*
1.选择body元素,并添加一个<svg>元素
2.并设置<svg>的高\宽为 600.
*/
var svg = d3.select("body")
.append("svg")
.attr("width", padding.width)
.attr("height", padding.height)

/* 比例尺 */
var xScale = d3.scale.linear()
.domain([0,10]) /* 定义域范围 */
.range([0,500]) /* 值域即为刻度尺长度 */

/*
坐标轴选择比例尺,设置比例尺位置为 "bottom" 即底部
*/
var axis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.innerTickSize(6)
.outerTickSize(8)

/*
在 svg 元素中添加一个包含坐标轴的:
1. 位置/走向 @transform
2. 样式 @class
3. 参数传递
*/
var gAxis = svg.append("g")
.attr("transform", padding.translate)
.attr("class","axis")
.call(axis) /* 将自身作为参数,传递给某个参数 */

文字格式

TickFormat

code 将会在刻度后加上一个```百分比```作为单位:
1
2
3
4
5
6

```js
var gAxis = svg.append("g")
.attr("transform", padding.translate)
.attr("class","axis")
.call(axis.tickFormat(d => d+ "%")) /* 将自身作为参数,传递给某个参数 */
⬅️ Go back