前言 需求是實現一個生命體徵的體溫單,x軸是時間線,y軸有多個體徵項。效果不是特別複雜,但是行業特殊性,所以也沒有現成可用的,所以用 d3.js 實現了一個多y軸的折線圖。 基礎 這張圖只用了d3.js的一些最基本用法,數據量也比較小,所以也用不到多麼牛逼的用法,只涉及到了比例尺 ,軸 ,畫線和點, ...
前言
需求是實現一個生命體徵的體溫單,x軸是時間線,y軸有多個體徵項。效果不是特別複雜,但是行業特殊性,所以也沒有現成可用的,所以用 d3.js 實現了一個多y軸的折線圖。
基礎
這張圖只用了d3.js的一些最基本用法,數據量也比較小,所以也用不到多麼牛逼的用法,只涉及到了比例尺scale
,軸axis
,畫線和點,最後我添加了一個縮放效果。
效果
具體實現
1.初始化一個svg作為容器,之後所有的點線面都是在這個容器裡邊畫了
svg.select('#id')
.append('svg')
.attr('width', width)
.attr('height', height)
2.定義比例尺scale
,定義域domain
顯示的刻度範圍,值域range
實際數據刻度
// x軸以時間為刻度
this.x = d3
.scaleTime()
.domain([this.beginTime, this.endTime])
.range([0, this.width]);
// y軸按照像素值為刻度,所有數據需按照比例轉換計算
this.y = d3
.scaleLinear()
.domain([0, this.height])
.range([this.height, 0]);
3.定義軸 axis
,axis
需要和scale
結合使用,作為參數傳入axis(scale)
。
其中,ticks
表示刻度數量,傳入數值即可,註意一點,ticks
預設會取 2,5,10
這三個數中的一個,如果你傳入一個其他的數,它會根據實際尺寸找一個接近的值(這裡還涉及到倍數情況下,詳細瞭解可查閱官方api);
如果刻度想要自定義需要利用tickValues([NO1,NO2,NO3...])
實現;tickSize
表示刻度尺寸,設置為容器svg的寬高即實現了全圖標尺效果。
this.xAxis = d3
.axisTop(this.x)
// .ticks(d3.timeHour.every(4))
.tickValues(d3.timeHour.range(this.beginTime, this.endTime, 4))
.tickSize(this.height)
.tickFormat(function (d, i) {
// return d.getHours();
return;
});
this.yAxis = d3
.axisLeft()
.scale(this.y)
.tickValues(d3.range(0, this.height, this.height / 40))
.tickSize(-this.width)
.tickFormat(function (d, i) {
return;
});
4.定義折線模板
// 折線模板
this.line = d3
.line()
.x(function (d) {
return that.x(d.datetime);
})
.y(function (d) {
return that.y(d.svgValue);
});
5.以上就完成了畫布的基本框架,剩下的事情就是數據渲染。
該表中,頂部的時間軸和左側y軸是自定義加上的,首先在容器中分配出來兩塊區域用來畫軸;再根據容器的寬高按比例具體實現。
源代碼地址:
https://github.com/zhangxiongcn/multiple-Y-axis-line-chart