本篇大纲:轴线的组成、建立轴线的必备工具、绘制轴线的API、ticks 刻度、XY 轴范例
讲了好久终於进到轴线与刻度
了!!!前面的章节看完比例尺之後,接下来就轮到绘制轴线啦~轴线也是图表中很重要的一部分,几乎所有图表都会有X轴跟Y轴
今天我们就来讲讲要怎麽绘制轴线吧!
首先,我们先来看看轴线是由哪些DOM元素组成的。图表的座标轴其实是一个复杂的结构,一条座标轴包含了
< path >
一条直线,标示轴线< line >
一组沿着轴的刻度记号(ticks)< text >
每个刻度记号的标签通常我们会使用 < g >
这个 svg 的结构标签把整条轴线的元素包在一起,之後对 < g > 元素进行一些操作(例如:移动的时候,就能将整条轴线一起移动。)
了解轴线的组成结构後,我们来看看要建立轴线的两大必备工具
DOM 元素 (path、line、text 等等)
我们必须要有一整组DOM元素,才能绘制出轴线
比例尺
除了 DOM 元素,也要搭配比例尺去计算出轴线的最大与最小值,才知道轴线要画多长、刻度要怎麽计算
有了这两个工具,我们就可以简单来建立一条轴线了,我们先画一条X轴试试看
// html
<div class="demo1"></div>
// js
d3.select('.demo1')
.append('svg')
.attr("width", 500)
.attr("height", 200)
.append('g')
// 设定比例尺
const scale = d3.scaleLinear()
.domain([0, 100])
.range([0, 500]);
// 建立轴线
let axis = d3.axisBottom(scale);
d3.select('svg g')
.call(axis);
建立好的轴线长这样
你一定会说:天啊这不是我要的轴线~这不是我要的轴线!为什麽会这样呢?那是因为 svg 都是从左上方的原点由上往下绘制,因此轴线长这样很正常。如果想要把轴线左右留点空间、移到下方的位置,我们就要 margin
跟 transform
来进行一些设定。
let width = 500,
height = 200,
margin = 10;
// 轴线建立
d3.select('.demo1')
.append('svg')
.attr("width", width)
.attr("height", height)
.append('g')
.attr('transform', `translate(${margin}, ${height-(margin*2)})`)
const scale = d3.scaleLinear()
.domain([0, 100])
.range([0, `${width-(margin*2)}`]);
let axis = d3.axisBottom(scale);
d3.select('svg g')
.call(axis);
这样建立出来的轴线就是完美的X轴啦!
特别要注意的是,建立轴线时,我们会使用 selection.call( )
这个方法来呼叫轴线的方法,那D3提供哪几种绘制轴线的方法呢? 我们一起来看一下
一样先来看看官方文件~D3 提供了这些方法让我们能绘制轴线
axisTop(scale)
、axisBottom(scale)
、axisRight(scale)
、axisLeft(scale)
这四个 API 是主要拿来建立轴线的方法,它们都是带入 scale比例尺 作为参数,接着根据带入的比例尺生成一个 axis generator,并包含预设的 ticks刻度设定。
Scale 参数
轴线会因为带入的 scale比例尺 不同,而产生不同的刻度间距,例如:
如果不知道每种 scale 怎麽设定,欢迎看看上一篇的 scale 讲解
刻度位置
这四个 API 之所以又分成 Top、Bottom、Right、Left 四种,只是因为生成的 ticks 方向不同~
axisTop ⇒ ticks 刻度在轴线上方
axisBottom ⇒ ticks 刻度在轴线下方
axisRight ⇒ ticks 刻度在轴线右方
axisLeft ⇒ ticks 刻度在轴线左方
除了预设好的刻度之外,D3也提供了不少让我们能自订 ticks 刻度的 API
我们能进行的设定包含:
现在就让我挑几个常用的API来讲解吧!
axis.ticks( ) => 调整ticks数量
这个方法可以让我们自行调整刻度的数量。
let scale = d3.scaleLinear().domain([0, 100]).range([0, 500]);
let axis = d3.axisBottom(scale);
axis.ticks(20);
d3.select('svg g')
.call(axis);
但要注意的是,即使我们定义好想要的特定刻度数量,如果刻度的值并非完整的数值的话,D3会自行调整刻度数量,让 ticks value 是漂亮的数字 (例如以5为单位间隔),例如:
let scale = d3.scaleLinear().domain([0, 100]).range([0, 500]);
let axis = d3.axisBottom(scale);
axis.ticks(27); // 改成要27个ticks
d3.select('svg g')
.call(axis);
出来的结果是一样的
axis.tickValues( ) => 指定想呈现的 ticks value
这个方法可以用来指定只想呈现哪些 tick values。这个方法超方便,如果我们想呈现某些特别奇怪的刻度,就可以用它来设定~
let scale = d3.scaleLinear().domain([0, 100]).range([0, 500]);
let axis = d3.axisBottom(scale);
axis.tickValues([0, 25, 53, 77, 81, 95]);
d3.select('svg g')
.call(axis);
axis.tickFormat( ) => 调整 tick label 的文字
这个也是非常好用的一个API,它可以协助我们调整想要呈现的刻度文字
let scale = d3.scaleLinear().domain([0, 100]).range([0, 500]);
let axis = d3.axisBottom(scale);
axis.tickFormat(function(d) {
return d + "元";
});
d3.select('svg g')
.call(axis);
axis.tickSize( )
、axis.tickSizeInner( )
、axis.tickSizeOuter( )
再来介绍的这三种方法是用来设定刻度线的长度,D3的刻度线分为 inner 跟 outer 两种
而这三种 API 分别能设定
预设的刻度线长度是6,但我们可以透过 tickSize 的设定来加长或缩短刻度线的长度,而且会自订把 tick value label 排到线段之後
let scale = d3.scaleLinear().domain([0, 100]).range([0, 500]);
let axis = d3.axisBottom(scale)
.tickSize(30);
d3.select('svg g')
.call(axis);
接着我们也可以进行一些漂亮的设定,像是使用css 跟 tickSize 搭配,去画出这种虚线段的轴线
我们先建立轴线
// js
let scale = d3.scaleLinear().domain([0, 100]).range([0, 400]);
let axis = d3.axisRight(scale)
.tickSize(400); // 把tick的尺寸设定成跟range的最大值一样,就能得到满版的轴线
d3.select('.demoDashed')
.append('svg')
.attr('width', '500')
.attr('height', '400')
.append('g')
.attr('class', 'dashed')
.attr('transform', 'translate(20, 20)')
.call(axis);
接着再设定CSS,将轴线设定为隐藏,刻度线设定为dashed
// css
g.dashed path {
display: none;
}
g.dashed line {
stroke-dasharray: 1 1;
}
这样就完成拉~如果再用一样的方式设定X轴,就能得到棋盘状的格线罗!
再来如果我们想单独设定 tickSizeOuter 或 tickSizeInner 也可以,但就要一起设定 tickPadding,否则轴线就会变成这样
let scale = d3.scaleLinear().domain([0, 100]).range([0, 500]);
let axis = d3.axisBottom(scale)
.tickSizeOuter(60);
d3.select('svg g')
.call(axis);
看到这张图,知道接下来的 tickPadding 是做什麽用了吗?
axis.tickPadding( ) ⇒ 调整刻度线与文字标签的距离
你没猜错!tickPadding( ) 就是用来调整刻度线跟文字标签的距离,预设的距离是3,但我们可以依照自己的需求去设定
let scale = d3.scaleLinear().domain([0, 100]).range([0, 500]);
let axis = d3.axisBottom(scale)
.tickPadding(60);
d3.select('svg g')
.call(axis);
哇赛好不容易把轴线跟刻度的API 都大致讲完了,我们现在来用资料实际画完整的 XY 轴吧!
我们这次要建立的轴线是这样
由於有两条轴线,因此两条轴线都要分别设定要使用的 scale 跟 axis。我们先看到手上拥有的资料
// html
<div class="XY_Axis"></div>
// js
const svg = d3.select(".XY_Axis")
.append("svg")
.attr("width", 500)
.attr("height", 200);
// data
const data = [{x:100, y:20}, {x:18, y:30}, {x:90, Y:250}]
一般来说我们都会拿到这种阵列包物件的资料,里面带有多笔数值。我们把要设定X轴的资料跟设定Y轴的资料分别整理出来
// map 资料集
xData = data.map((i) => i.x); // 预期套资料後会得到 [100, 18, 90] 的阵列
yData = data.map((i) => i.y); // 预期套资料後会得到 [20, 30, 250] 的阵列
接着我们先来设定 X 轴线
// 设定要给 X 轴用的scale 跟 axis
const xScale = d3.scaleLinear()
.domain([0, d3.max(xData)])
.range([20, 480]); // X 轴绘制的viewport起点终点(宽度)
const xAxis = d3.axisBottom(xScale)
.tickFormat(function (d) {
//调整标签样式
return `${d} 元`;
})
// 呼叫绘制x轴、调整x轴位置
const xAxisGroup = svg.append("g")
.call(xAxis)
.attr("transform", "translate(0,180)")
再来设定 Y 轴线
// 设定要给 Y 轴用的 scale 跟 axis
const yScale = d3.scaleLinear()
.domain([0, d3.max(yData)])
.range([20, 180]); // Y 轴绘制的viewport 起点终点(高度)
const yAxis = d3.axisLeft(yScale)
.ticks(5)
// 呼叫绘制y轴、调整y轴位置
const yAxisGroup = svg.append("g")
.call(yAxis)
.attr("transform", "translate(20,0)")
这时候座标轴已经画出来了,但你会发现Y轴的刻度跟我们平常看到的不一样,是颠倒的?
这是因为轴线是从 svg 左上方的原点,由上往下绘制,所以当我们把 range 设定成 ([20, 180]) 时,Y轴线就是正常的从离原点20px的地方开始由上方往下建立。
为了要让Y轴的数值能颠倒过来,我们要把 range 的值也颠倒设定
const yScale = d3.scaleLinear()
.domain([0, d3.max(yData)])
.range([180, 20]); // 颠倒
这样就完成啦!要注意的是,由於 X 跟 Y 轴的长度分别是看 svg 宽度跟 svg 高度,因此它们两个的 range 范围设定也会有所不同,不要设定错罗!
终於完整介绍完座标轴跟刻度啦!!大家明天见~
最後一样附上本章的程序码与图表 Github 、 Github Page,需要的人请自行取用~
>>: Material UI in React [ Day 29 ] Customization Component 自订组件 (part2)
为什么选择 C# 正如简介里面介绍的一样,作为一名运维人员,你应该懂一门开发语言,那么那么多语言中,...
Microsoft Defender for Endpoint的威胁与弱点管理(TVM)功能 会根据...
学习内容 这一篇的内容,是纪录阅读官方文件 tutorial: A Hero Editor 的笔记,...
在debian下使用alien转换MegaRAID Storage Manager的RPM到deb过...
环境 Windows 10 21H1 Visual Studio 2019 前情提要 在【Day 0...