一個基於D3.js的橫向柱狀圖的動態數據可視化工具css
首先感謝原做者Jannchie https://github.com/Jannchie/
以及原項目Historical-ranking-data-visualization-based-on-d3.jshtml
寫這個東西是由於學校某項目的一個練手題目選定了這個
那我爲啥要寫前端呢?由於前端那位,我好像聯繫不到:)
沒辦法時間挺緊的,這小項目就我一人寫了
幾乎全部的代碼都是來自原項目的,考慮到整個項目可能不斷須要魔改動態可視化,因而就另開了一個新repo ColumnsAnimation
期待這個repo之後的變化吧前端
順便寫了這個隨筆,本意是給本身前端看的,但今天有位同窗問優化問題,因此就寫的詳細點了git
簡單的html+js+css,其中html和css沒什麼要說的,簡單提一下github
<meta name="viewport" content="width=device-width">
CSS部分
設置顏色類:這個點子很是好,能夠方便的修改顏色數據
設置各類元素寬度,文字描邊和座標樣式:這裏有個問題,若是SVG變寬高,這裏的各類元素寬度就會略有問題後端
JavaScript部分
動態可視化核心代碼,主要就是標籤的組織和更新
首先講清楚SVG內部標籤構造,和動態更新的原理
運行代碼能夠簡化分析SVG內部標籤的設置數組
SVG內部標籤dom
g group標籤包含其餘全部svg標籤 g x軸(由d3生成) text x軸標籤(d3生成) path x軸(d3生成) g*n n個時間豎線(英文是Tick不知道怎麼翻譯) line 豎線 text x軸數字 g 這個組不知道幹嗎的,多是y軸,之後考慮去掉? text 這個是timer,改源代碼時忘記留下來了,最後本身加上的 g*n n個bar,這是動態的主題 g 這是標記顏色的,好像沒用? rect 這是柱子,只有顏色類 text y軸上的柱後文字,label類顏色類 text 柱前數字,value類顏色類 text 柱上文字,barInfo類
動態更新原理
就是不斷的綁定新數據:
在Enter裏初始化新數據
在upate裏更新新元素
在exit下刪除舊元素
關鍵在於d3提供了按索引綁定數據的方法,這樣的操做才得以簡單進行,詳細說明在下面svg
利用setInterval()來控制整個時間變化
首先輸入數據data,按時間push到date數組裏
再定義一個iter,同於控制總時間函數
得到顏色類
做者使用了一個簡單的hash函數,作了一個name到hash值的映射,然取模color.length()取得顏色類
\[ Hash(name)=\sum name[i] \]
獲取當前時間下的數據
這裏原做者是枚舉data數組,返回對應時間下的數據(修改的代碼中順便維護了Timer)
有一個同窗也是寫了這個項目,但老是有卡頓(win10),那麼咱們順便講一下優化
其實這裏能夠二分達到O(logn),但首先須要預處理數據排序O(nlogn),其次咱們設置了MaxNumber用來控制顯示柱子的數量,就是說這裏還能優化
最好的方法是在後端處理好數據(排序+切片)後傳給前端,這種一勞永逸的方式何樂而不爲
刷新圖表
這裏是核心部分,咱們拆開來看
注意做者將interval間隔時間分紅了三份( interval/=3 )
首先維護yScale, xScale, xAxisG, yAxisG和Timer
原做者在初始化刻度尺時並無給出domain, range這是很讓人舒服的地方,很是優雅
設置座標系的更新動畫,注意還要添加.call(xAxis),順便刪除原有tick
維護Timer,這裏有兩個要點。其1、在第一次顯示Timer時停頓。其2、數字的過分動畫d3中沒有直接的實現,只能是用tween調d3.interpolate本身寫
綁定bar的數據
注意.data(data, [key])中的key是每一個元素的鍵值,對應原有元素的鍵值進行更新。若是沒有設置的話就從頭至尾覆蓋
Enter元素的過渡動畫
在綁定了數據後,按道理全部元素的數據都是當前時間下最新數據。
Enter部分指新加入數據,這裏應該是帶有新鍵值的數據。
這裏的更新就像是初始化。
注意設置如下屬性:
transform, x, y, width, height, fill-opacity, class(帶有顏色類), text, stroke-width
Update元素的過渡動畫
Update元素就是數據被更新的元素,這裏的過渡動畫的屬性就不多,由於一些屬性不須要變化(好比顏色類)
Exit元素的過渡動畫
Exit元素就是上一次時間的數據,在當前時間的數據中沒有出現的元素。
這裏的過渡動畫就更簡單了,過渡裏直接remove(),設置fill-opacity爲0便可
更新y座標
最後咱們更新每一個bar元素的y座標便可,這裏使用了一開始設置的yScale