以前有個網友問我了一個頗有價值的問題, 有關實現數據可視化的問題, 可是這個可視化問題不是通常的柱狀圖, 折現圖之類的,而是不規則刻度的數據可視化.因此筆者思考了一下決定本身實現一個動態刻度可視化組件的方案, 來解決這一類的需求.javascript
最初的需求是這樣的: css
咱們只須要輸入文字, 數值比例, 就能生成如上圖所示的刻度圖.可是做爲一名有追求的程序員, 須要對問題抽象化, 造成通用的解決方案,因此咱們開始重組需求: 由上圖咱們能夠拆解爲一下幾個需求點:以上就是筆者挖掘的通用需求,固然有其餘需求也能夠漸進的增長.前端
確認了以上需求以後,咱們開始選擇技術選型, 筆者以前經常使用的技術棧是vue和react,因此接下來咱們初步確認該組件採用以下技術方案:vue
若是你們擅長使用vue, 也能夠, 筆者以前也寫過如何搭建vue的組件庫相關的文章,感興趣能夠學習瞭解一下, 其本質思想是一致的.java
接下來咱們開始實現動態刻度可視化組件. 若是對umi不熟悉的,能夠參考筆者以前寫的文章從0到1教你搭建前端團隊的組件系統(高級進階必備).node
由以上需求分析咱們能夠定義以下的屬性類型:react
export interface TickerProps {
width: number;
maxHeight: number;
percent: number;
text: string;
value: number;
showValue: boolean;
unit: string;
lineNum: number;
defaultColor: string;
activeColor: string;
textStyle: object;
valueStyle: object;
}
複製代碼
const Ticker: React.FC<TickerProps> = function(props:TickerProps) {
const {
width = 100,
maxHeight = 10,
percent = 50,
value,
text = '瞬時能見度',
showValue = true,
unit = 'M',
lineNum = 12,
defaultColor = '#06c',
activeColor = 'red',
valueStyle,
textStyle
} = props
return (
<div className="ticker"> { showValue && <div className="value" style={valueStyle}> { value || 0 } <span className="unit">{ unit }</span> </div> } <div className="tickerGraph"> <div className="tickerLine"> </div> <div className="tickerBar"></div> </div> { !!text && <div className="text">{ text }</div> } </div>
);
};
export default Ticker;
複製代碼
有關刻度可視化咱們徹底採用dom實現, 因此這裏筆者具體分析一下如何實現刻度視圖: webpack
上圖的思路就是用一個個dom來組裝成隨機刻度圖形,因此咱們只要利用css實現這個形狀, 也就成功了一半.至於激活狀態,咱們會根據傳入的數據量來決定激活範圍,接下來會介紹如何渲染激活的刻度,也就是上圖的紅色區域.由於該組件不少功能在搭建結構以後已經實現了, 這裏咱們惟一關注的就是css和js長度計算的問題, css實現方案有不少, 這裏就不具體介紹了, 筆者這裏重點介紹一下如何實現指定範圍的隨機高度:css3
// 生成指定範圍的隨機高度
const random = (min:number, max:number):number => {
return min + Math.random() * (max - min)
}
複製代碼
動態刻度條的隨機高度咱們就是利用以上函數實現的, 刻度條內部實現以下:git
<div className="tickerLine" style={{borderBottomColor: defaultColor}}>
{
new Array(lineNum).fill(0).map((item:number, i: number) => {
let isActive = (i + 1) <= Math.floor(lineNum * percent / 100)
return <span
className="tick"
style={{
height: random(3, maxHeight) + 'px', left: (gap + 2) * i + 'px',
backgroundColor: isActive ? activeColor : defaultColor
}}>
</span>
})
}
</div>
複製代碼
gap爲刻度之間的間距, 因爲計算刻度的位置須要一點幾何知識, 公式以下:
W = Lw * lineNum + gap * ( lineNum - 1)
複製代碼
其中W表示刻度總寬度, Lw爲刻度線寬度, lineNum爲刻度線數量.
還有一個注意點就是激活態, 筆者使用以下函數來判斷刻度是否具備激活狀態:
let isActive = (i + 1) <= Math.floor(lineNum * percent / 100)
複製代碼
這塊也很是好理解, 也就是咱們傳入的比率乘以線的總數量,便可求出哪些刻度線是須要激活的.
以上細節實現完成以後,咱們就能夠來實現有點意思的刻度可視化方案啦, 以下展現的demo:
若是想學習更多H5遊戲, webpack,node,gulp,css3,javascript,nodeJS,canvas數據可視化等前端知識和實戰,歡迎在公號《趣談前端》加入咱們的技術羣一塊兒學習討論,共同探索前端的邊界。