動態刻度可視化組件實現

前言

以前有個網友問我了一個頗有價值的問題, 有關實現數據可視化的問題, 可是這個可視化問題不是通常的柱狀圖, 折現圖之類的,而是不規則刻度的數據可視化.因此筆者思考了一下決定本身實現一個動態刻度可視化組件的方案, 來解決這一類的需求.javascript

正文

最初的需求是這樣的: css

咱們只須要輸入文字, 數值比例, 就能生成如上圖所示的刻度圖.可是做爲一名有追求的程序員, 須要對問題抽象化, 造成通用的解決方案,因此咱們開始重組需求:
由上圖咱們能夠拆解爲一下幾個需求點:

  • 支持數值自定義
  • 數值單位自定義
  • 支持刻度組件寬度自定義
  • 支持刻度線數量自定義
  • 支持刻度變化幅度自定義
  • 傳入已有進度比例,即激活區範圍
  • 支持刻度樣式自定義
  • 支持數值樣式自定義
  • 支持自定義說明文本以及說明文本自定義

以上就是筆者挖掘的通用需求,固然有其餘需求也能夠漸進的增長.前端

確認了以上需求以後,咱們開始選擇技術選型, 筆者以前經常使用的技術棧是vuereact,因此接下來咱們初步確認該組件採用以下技術方案:vue

  • react + typescript + umi-library

若是你們擅長使用vue, 也能夠, 筆者以前也寫過如何搭建vue組件庫相關的文章,感興趣能夠學習瞭解一下, 其本質思想是一致的.java

接下來咱們開始實現動態刻度可視化組件. 若是對umi不熟悉的,能夠參考筆者以前寫的文章從0到1教你搭建前端團隊的組件系統(高級進階必備).node

1. 定義基本屬性類型

由以上需求分析咱們能夠定義以下的屬性類型: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;
}
複製代碼

2. 組件總體結構

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;
複製代碼

3. 視圖搭建

有關刻度可視化咱們徹底採用dom實現, 因此這裏筆者具體分析一下如何實現刻度視圖: webpack

上圖的思路就是用一個個dom來組裝成隨機刻度圖形,因此咱們只要利用css實現這個形狀, 也就成功了一半.至於激活狀態,咱們會根據傳入的數據量來決定激活範圍,接下來會介紹如何渲染激活的刻度,也就是上圖的紅色區域.

4.特殊功能實現

由於該組件不少功能在搭建結構以後已經實現了, 這裏咱們惟一關注的就是cssjs長度計算的問題, 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:

    1. 可見度測量
    1. 正態分佈模型
    1. 標尺
    1. 光柵
    1. 自定義文本樣式

github地址

一個基於react的輕量級刻度線可視化組件

更多開源體驗地址

最後

若是想學習更多H5遊戲, webpacknodegulpcss3javascriptnodeJScanvas數據可視化等前端知識和實戰,歡迎在公號《趣談前端》加入咱們的技術羣一塊兒學習討論,共同探索前端的邊界。

更多推薦

相關文章
相關標籤/搜索