動態效果圖(動畫開頭有延遲,稍等...):css
細看上面的動態效果圖,能夠發現:html
一開始,我是用 Echarts 來實現儀表盤,可是它沒法知足上面的兩點需求。因此後來改爲用D3.js。 D3.js
能夠完美地實現圖表的定製,從細節上,完美地知足咱們的需求。git
首先定義一個svg
元素:github
<svg id="myGauge" width="80" height="108" ></svg>
複製代碼
而後,聲明一些變量用於初始化:app
var width=80,
height=108, //svg的高度和寬度,也能夠經過svg的width、height屬性獲取
innerRadius = 22,
outerRadius = 30, //圓弧的內外半徑
arcMin = -Math.PI*2/3,
arcMax = Math.PI*2/3, //圓弧的起始角度和終止角度
複製代碼
建立一個 arc
方法,並設置全部的屬性,除了 endAngle
。在建立圓弧的時候,傳遞一個包含 endAngle
屬性的對象到這個方法,就能夠計算出一個給定角度的 SVG path
。svg
var arc = d3.arc()
.innerRadius(22)
.outerRadius(30)
.startAngle(arcMin)
複製代碼
圓弧角度怎麼設置呢? 把一個圓圈對應到一個時鐘,那麼12點鐘對應的角度就是0
,順時針3點鐘的角度是Math.PI/2
,逆時針6點鐘的角度是-Math.PI
。所以-Math.PI*2/3
到Math.PI*2/3
的圓弧形狀如上面的效果圖所示。更多參考API文檔中的arc.startAngle
。動畫
獲取SVG
元素,而且轉換原點到畫布的中心,這樣咱們在以後建立圓弧時就不須要再單獨指定它們的位置了ui
var svg = d3.select("#myGauge")
var g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
複製代碼
添加儀表盤中的文字(標題,數值,單位)this
//添加儀表盤的標題
g.append("text").attr("class", "gauge-title")
.style("alignment-baseline", "central") //相對父元素對齊方式
.style("text-anchor", "middle") //文本錨點,居中
.attr("y", -45) //到中心的距離
.text("CPU佔用率");
//添加儀表盤顯示的數值,由於以後還要更新,因此聲明一個變量
var valueLabel = g.append("text").attr("class", "gauge-value")
.style("alignment-baseline", "central") //相對父元素對齊方式
.style("text-anchor", "middle") //文本錨點,居中
.attr("y", 25) //到中心的距離
.text(12.65);
//添加儀表盤顯示數值的單位
g.append("text").attr("class", "gauge-unity")
.style("alignment-baseline", "central") //相對父元素對齊方式
.style("text-anchor", "middle") //文本錨點,居中
.attr("y", 40) //到中心的距離
.text("%");
複製代碼
D3
製做的SVG
圖,與Echarts
繪製的Canvas
比起來,很重要的一個優勢是,能夠用CSS
定義SVG
的樣式。好比,此處儀表盤標題的樣式以下:spa
.gauge-title{
font-size: 10px;
fill: #A1A6AD;
}
複製代碼
添加背景圓弧
//添加背景圓弧
var background = g.append("path")
.datum({endAngle:arcMax}) //傳遞endAngle參數到arc方法
.style("fill", "#444851")
.attr("d", arc);
複製代碼
添加表示百分比的圓弧,其中percentage
是要表示的百分比,0到1的小數。
//計算圓弧的結束角度
var currentAngle = percentage*(arcMax-arcMin) + arcMin
//添加另外一層圓弧,用於表示百分比
var foreground = g.append("path")
.datum({endAngle:currentAngle})
.style("fill", "#444851")
.attr("d", arc);
複製代碼
在圓弧末尾添加一個指針標記
var tick = g.append("line")
.attr('class', 'gauge-tick')
.attr("x1", 0)
.attr("y1", -innerRadius)
.attr("x2", 0)
.attr("y2", -(innerRadius + 12)) //定義line位置,默認是在圓弧正中間,12是指針的長度
.style("stroke", "#A1A6AD")
.attr('transform', 'rotate('+ angleToDegree(currentAngle) +')')
複製代碼
rotate
中的參數是度數,Math.PI
對應180
,所以須要自定義一個angleToDegree
方法把currentAngle
轉換一下。
至此,一個SVG
儀表盤就製做出來了,不過是靜止的,那怎麼更新這個儀表盤呢?
須要更新:表示新的百分比的圓弧;圓弧下方的數值。 修改圓弧下方的數值很簡單:
valueLabel.text(newValue)
複製代碼
更新圓弧則稍麻煩一點,具體思路是:修改圓弧的endAngle
,以及修改圓弧末尾指針的transform
值。 實現的過程當中,須要使用的API:
selection.transition
:github.com/d3/d3-trans…transition.attrTween
:github.com/d3/d3-trans…d3.interpolate
:github.com/d3/d3-inter…angle
爲新圓弧的結束角度。//更新圓弧,而且設置漸變更效
foreground.transition()
.duration(750)
.ease(d3.easeElastic) //設置來回彈動的效果
.attrTween("d", arcTween(angle));
複製代碼
arcTween
方法定義以下。它返回一個d
屬性的補間(漸變)動畫方法,使一個圓弧從當前的角度漸變到另外一個新的角度。arcTween(newAngle) {
let self=this
return function(d) {
var interpolate = d3.interpolate(d.endAngle, newAngle); //在兩個值間找一個插值
return function(t) {
d.endAngle = interpolate(t); //根據 transition 的時間 t 計算插值並賦值給endAngle
return arc(d); //返回新的「d」屬性值
};
};
}
複製代碼
這個方法更詳細的說明能夠參考Arc Tween中的註釋。oldAngle
是舊圓弧的結束角度。//更新圓弧末端的指針標記,而且設置漸變更效
tick.transition()
.duration(750)
.ease(d3.easeElastic) //設置來回彈動的效果
.attrTween('transform', function(){ //設置「transform」屬性的漸變,原理同上面的arcTween方法
var i = d3.interpolate(angleToDegree(oldAngle), angleToDegree(newAngle)); //取插值
return function(t) {
return 'rotate('+ i(t) +')'
};
})
複製代碼
至此,咱們就成功製做了一個動態刷新的簡介美觀的SVG
儀表盤。
每次使用D3.js
都會忍不住以爲它真是太強大、太有意思了~它就像是一個百寶箱,讓咱們最大限度地知足需求。