如何繪製一個類甘特圖 (附原始碼)

螞蟻金服資料體驗技術發表於2018-04-13

作者簡介 Kid 螞蟻金服·資料體驗技術團隊

本文介紹如何從頭繪製一個業務圖表以及對於通用性上的一些思考。程式碼在最後也會給出。

效果演示

先看下元件的最後效果

xiaoguo.gif | left | 672x424

要畫圖,當然是先找找看有沒有能夠直接拿來用的。我需要繪製的是一個類甘特圖。主要是為了做時間基線上的任務耗時管理,並且能夠與過往耗時進行對比。與傳統的甘特圖定義有些區別。長相上與甘特圖類似。

找了AntV,echarts,和D3。AntV和echarts都沒有直接的甘特圖。D3上有一些甘特圖,但是和我想要的功能區別還是挺大的。基於他們修改的代價應該比自己畫的代價高。那麼挑哪種技術繪圖呢,canvas,svg和div。我的業務場景繪製的點不算多,而且canvas對於事件挺難處理的。svg畢竟有DOM元素,一些hover效果我可以直接借用antd來做。最後選擇了svg。(其實之前沒畫過圖,用啥都得學~)

功能列表

  • 圖表繪製
  • 上下滾動
  • 漫遊器控制左右滾動以及縮放比例
  • 節點hover顯示細節

整體設計

元件結構
未命名檔案.png | left | 414x433

元件的設計就如上圖所示了。圖表與Y軸區域做成一個整體,讓圖表上下滾動。由於windows上左右滾動很不好用,所以水平方向上沒有做滾動,而是設定了漫遊器進行滾動以及縮放的功能。

資料流向
未命名檔案 (1).png | left | 604x316

元件的資料流向很簡單,使用者傳入初始化配置以及真實資料。大部分元件只是單純負責渲染,只有漫遊器會修改圖表位置以及縮放的比例。然後圖表和X軸會相應的顯示對應區域。

結構和資料流向設計好,編碼開發其實很簡單了,不詳述,自己看github上的程式碼吧。然後就是一些細節的打磨。

細節打磨

自己從頭寫的好處就是一些小細節可以打磨的舒服些

名字滑動吸左

滑動過程中節點名字吸左顯示。

getTop.gif | left | 644x304

X軸放置不下隱藏

超出一定的比例之後按單雙數隱藏了X軸的部分顯示。其實既可以選擇隱藏,也可以旋轉一定的角度,自己做,隨便定~

chaochang.gif | left | 776x120

漫遊器防抖

antv和echart漫遊器都是會抖動的,而且可拖拽區域都是隻在漫遊器內部。雖然echarts做了動畫的優化,其實還是不太舒服。截個antv的效果好了。

doudong (1).gif | left | 611x253

我把漫遊器設計成百分比的,所以滑動順滑,而且滑動的時候事件加到了document上,可拖拽區域就變成整個頁面了。

doudong (2).gif | left | 690x306

編碼做完了,細節也打磨的差不多了。對於產品的可用性已經可以交差了。也get了svg畫圖的技能,可是,沉澱下了啥呢....別人會需要繪製一模一樣的圖麼?感覺不太可能。仔細一想,自己做的東西複用性太差。那麼問題來了,複用性差跟白做了有什麼區別..

很欣賞<黑客與畫家>裡的一句話,“程式設計就跟畫油畫一樣,永遠沒有完工的那一天,你只是不再畫下去了而已”

複用性

在工程方面,可能複用性是自己一直以來比較忽視的點。但是其實思考複用性方面的問題,既是對你的設計以及程式碼質量的考驗,也能為後續的工作提高效率。還能培養你面對問題的直覺,思考複用性其實就是在思考問題的共性。這一個個共性就是一個個點,一個個的點多了,你的知識結構才能被串聯起來,形成一張網。

定義場景

如何提高複用性呢?首先明確定義業務使用場景:這個圖是為了做時間基線上的任務耗時管理,並且能夠與過往耗時進行對比。至少讓別人在相同需求的時候能夠複用,但是能重用的可能性太小了,不行。

二次開發

要不我降低二次開發的門檻?如果別人就想改一點圖表的渲染,我是不是該支援定製化渲染。仔細想想感覺不用。因為圖形繪製都改了,那離重畫一張圖也沒啥區別,畢竟技術難度也算很高。為了增加這一點靈活性,要給元件加太多的複雜度了,而且拍腦袋決定哪裡開放繪製肯定做不好。畢竟靈活性和複雜度是成正比的。為了得到一些的靈活性而需要付出的代價是非常需要權衡的。二次開發這樣的事情交給antV來做更好。

抽象通用能力

那怎麼辦?再看看能不能抽象出有一些複雜度的可重用的部分。重新審視整個設計,可用性較強的是漫遊器元件。也就是下圖內紅色虛線框的位置:

未命名檔案 (3).png | left | 659x402

共用性的理由也很充分,畢竟windows上左右拖拽不方便是事實,圖表配上漫遊器是正常的能力,而且echarts和antv,漫遊器都沒有單獨提供。

想明白了,做其實並不難。花些時間將漫遊器的業務邏輯摘乾淨。將依賴全部以引數方式注入。然後定義好對外的介面,想想如何降低使用者的門檻。這個過程其實很能提高你的程式碼質量。你會抱怨自己為什麼最開始寫的時候沒有解耦他們。可能更好的方式不應該是做完了之後進行抽象,而是設計階段就能夠意識到這是個通用能力而在設計層面就解耦掉。

具體的漫遊器我也抽成了一個元件,如何使用可以參照我寫在github上的demo。我抽成了幾個裝飾器和一個元件,感覺已經無力再抽了,如果有好的思路能夠把他們合到一起的話歡迎告知我。

總結

文章主要是分享如何手工畫一個自定義的圖表,以及在這個過程中如何提高元件複用性來沉澱通用能力。更多的是分享下做業務元件應該去思考的角度,建議大家培養這樣的習慣。畢竟習慣這種東西很可怕,我們可以先培養出一些習慣,然後等著習慣來推動你就好了。最後放上程式碼地址,圖表地址漫遊器地址

對我們團隊感興趣的可以關注專欄,關注github或者傳送簡歷至'tao.qit####alibaba-inc.com'.replace('####', '@'),歡迎有志之士加入~

原文地址:github.com/ProtoTeam/b…

相關文章