用於鐵膽火車俠執行排班資料展示系統,一個基於Vue構建的Gantt-like 圖表元件

我是一勺氨基酸發表於2019-03-07

先看效果一哈效果

鐺鐺,新的鐵膽火車俠執行排班資料展示系統節目233 page1.png

用於鐵膽火車俠執行排班資料展示系統,一個基於Vue構建的Gantt-like 圖表元件

點選Demo看效果

使用說明的Githu地址

起因

剛剛畢業,初入新公司,就要求參與一個排班展示類的系統開發,前端系統方面的關鍵點就是排班資料的展示了。

  • 在設計獅和甲方一頓瘋狂的溝通
  • 啪噠,給我了一份設計稿
  • 偷偷瞄一眼,嗯哼,?這是啥子哦
  • 誒喲,這不是和學校裡學的甘特圖很像嘛
  • 一頓高興就開始百度谷歌起來,畢竟看著挺複雜的,如果能有開源元件直接用就好啦,比自己寫的靠譜又方便不是。
  • 但是一頓搜尋大概都是如下這些樣子

都是類似如下的 這些

用於鐵膽火車俠執行排班資料展示系統,一個基於Vue構建的Gantt-like 圖表元件

用於鐵膽火車俠執行排班資料展示系統,一個基於Vue構建的Gantt-like 圖表元件

功能很多,但是都不是需要的,暴風哭泣?。。。都是一行只有一條資料的甘特圖表,都不符合要求啊摔

用於鐵膽火車俠執行排班資料展示系統,一個基於Vue構建的Gantt-like 圖表元件

而且看github 上的相關程式碼很多都沒有註釋,或者看不懂啦(畢竟英語不好,太委屈?)

既然找不到相關符合要求,所以只能自己動手了啊,開啟vs code 準備一把梭了他。

用於鐵膽火車俠執行排班資料展示系統,一個基於Vue構建的Gantt-like 圖表元件
一梭程式碼爽,一直梭一直爽?。

但是想了一會沒有梭出來,一丟丟思路都磨的。而上面的那些,功能都很多很雜看了頭大,不知道那裡看起。

用於鐵膽火車俠執行排班資料展示系統,一個基於Vue構建的Gantt-like 圖表元件

翻了一會github 後,我在這裡推薦一個程式碼 jquery.ganttView

這個是用jquery 寫的,看了一哈程式碼也只有三百來行,相比其他看起來會輕鬆一點。推薦!!!

用於鐵膽火車俠執行排班資料展示系統,一個基於Vue構建的Gantt-like 圖表元件

比較笨哈,不是很懂怎麼看原始碼,看了半天才看懂他的原理,然後我就基於他的原理我就用vue 和react 抄了一個寫了一個,地址,加了個拖拽。

嗯,自己根據的理解寫了第一版本調研一哈,寫的非常非常差勁,程式碼寫的太少(我是去年1月轉的開始寫的前端,???其實後端也沒寫多少,程式碼量太少了),長這個樣子,表面看起來是很符合要求,但是裡面的程式碼就很臭了呀。如果有興趣看,大概就是前35次commit.

用於鐵膽火車俠執行排班資料展示系統,一個基於Vue構建的Gantt-like 圖表元件

然後就commit 就停在那裡很久了。因為公司要求的react的,所以我就跑去用react 寫了。

跑題了。。。跑題了。。。

實現大致思路

看了上面基於jquery 的原始碼後,甘特圖可以分成3塊來寫,加上自己的理解改造了一頓,上面的 時間軸區域,左側的描述行名區域,右側的甘特圖表區域。

來看時間軸區域

用於鐵膽火車俠執行排班資料展示系統,一個基於Vue構建的Gantt-like 圖表元件
時間軸這部分比較簡單,關鍵點就是上面那個箭頭部分,根據給定時間要算出時間軸的開始時間。 比如Start10:10

  • 刻度為60,時間軸的開始時間為 10:00
  • 刻度為5,時間軸的開始時間 為 10:10
  • 刻度為3,時間軸的開始時間為10:09

然後用你算出的開始時間一直加加加刻度,迴圈出刻度div 就可以啦,不難的,就是算起始時間可能有一點繞。

左側的描述行名區域,

用於鐵膽火車俠執行排班資料展示系統,一個基於Vue構建的Gantt-like 圖表元件

這個部分就比較簡單啦,迴圈生成列表就ok 的啦。

右側的甘特圖表區域。

用於鐵膽火車俠執行排班資料展示系統,一個基於Vue構建的Gantt-like 圖表元件

這邊的思路是這樣的,

  1. 先生成一行帶有表格線的div,用一個L形狀的png做背景重複background-repeat就好啦LLLLLLLLLL這樣是不是就是表格線啦。

    用於鐵膽火車俠執行排班資料展示系統,一個基於Vue構建的Gantt-like 圖表元件
    上面的jq 版本的辦法是生成一個個div 然後用border來畫線,大家最好不要學哦,因為這樣會生成太多div了,效能會很差勁,除非你要訂製每一個格子(但是也有其他方法訂製哦)

  2. 然後就要開始生成甘特條的容器了。

    用於鐵膽火車俠執行排班資料展示系統,一個基於Vue構建的Gantt-like 圖表元件

生成容器的關鍵點就定位他的位置了,定位的起點就是前面生成時間軸算出來的時間軸的開始時間。方法就是

(容器時間-開始時間)/刻度值* 刻度的寬度,

這樣就算出距離了,接著用絕對定位就可以了,很easy 哦。

  1. 還有滾動的同步需要處理,時間軸和甘特圖表區 是X軸滾動關聯,左側的描述行名區域是和甘特圖表區Y軸關聯。這裡個純Css的滾動方案,但是有缺陷,它Y軸滾動條要滾動到末尾才可以看到。所以只能自己去實現滾動條啦,很簡單哦。思路是一個父div 包裹一個子div,其中父div 設定為一屏gantt 頁面的高度,同時設定寬度為17px(滾動條的寬度,但是不同瀏覽器滾動條寬度好像不一樣),設定overflow:scroll子div 設定為gantt 圖表行高度的總和。X軸同理,然後去同步滾動就好了。

交差時間

公司用的版本是用react 寫的,當把測試資料帶入時,10000條資料。。。

用於鐵膽火車俠執行排班資料展示系統,一個基於Vue構建的Gantt-like 圖表元件

畫面大概卡了十幾秒才出來,漫長的白屏。滾動起來的效果還是可以看的。

給甲方看,甲方說可以接受這個渲染速度

用於鐵膽火車俠執行排班資料展示系統,一個基於Vue構建的Gantt-like 圖表元件

甲方說他們舊系統也是要這樣卡很久才出畫面的,等習慣了沒關係。。。而且稱新的甘特圖好看很多嘛,樣式效果是比我目前這個Demo 差別很多哦,這個demo是猴版滑稽?。

不行,對自我的要求,我要改進它!!!

優化時間

?點名表揚chrome ,雖然十多秒出來了,但是滾動還是很流暢的,頁面大概佔用600MB吧。

?點名批評IE,可能有一分鐘?出來後滾動也是一卡一卡像幻燈片一樣。

沒有思路就在zhihu 上逛了一會,機緣巧合遇到了曾建凱寫了一個回答提到了大量資料的問題,遂請教了它,得知了react-virtualized,這裡再次謝謝?。

於是查詢了一些相關文章,需要的自查。

用於鐵膽火車俠執行排班資料展示系統,一個基於Vue構建的Gantt-like 圖表元件

具體原理是很簡單,簡化版本大致說一下(注意,這裡每一行高度固定哦):

根據滾動條滾動的距離除以行高算出渲染的第一行的firstIndex

scrollTop/cellHeight

再根據螢幕高度算出要渲染的最後一行的endIndex

screenHeight/cellHeight - scrollTop/cellHeight,

然後去原始陣列中擷取需要渲染定位需要的部分就可以了(注意定位的問題哦)。

⌨️⌨️略去一番操作,就優化到了大概1.5秒左右就可以載入出頁面啦 ? ? ?

但是還不夠,還可以再快一點,逮蝦戶~~~

用於鐵膽火車俠執行排班資料展示系統,一個基於Vue構建的Gantt-like 圖表元件

上面的方案都只解決了Y軸方向的動態渲染,說到這裡你肯定明白了,X軸我們同樣可以做手腳的呀。思路很簡單,就是算出當前的螢幕顯示的時間範圍,然後渲染時判定甘特內容條容器的時間在不在這個範圍之內就可以了,具體實現就留給大家了。

⌨️⌨️再略去一番操作,能有大概0.5秒的速度提升,現在1秒左右就可以載入出頁面啦 ? ? ?

通過以上相信大家也可以做出一個基本gantt圖元件了

最後

就是我自己實現的玩具程式碼啦 v-gantt-chart 元件啦,demo 就是用他做的,支援多個甘特圖組合哦。支援自定義渲染內容。

用於鐵膽火車俠執行排班資料展示系統,一個基於Vue構建的Gantt-like 圖表元件

具體的使用 可以看Github 上的readme,歡迎大家提出意見,提issue???

這裡再貼一邊地址 ???,喜歡的話點個star 或者贊再走哦~~~

Demo的Githu地址

相關文章