Canvas or SVG?一張好圖,兩手準備,就在 ECharts 4.0

ECharts發表於2019-03-02

Canvas 和 SVG 是兩大基於瀏覽器的渲染方案,在選擇圖表庫的時候,使用者有時也會在這兩者之間糾結。但是糾結的時候,你是否真的明白這兩者在哪些方面有優劣?

ECharts 4.0 推出 Canvas、SVG 雙引擎渲染方案,使用者可以使用一個配置項一鍵切換,成為我們所知的第一個支援雙引擎的視覺化工具。同樣的介面,同樣的渲染視覺效果,不一樣的精彩!

那麼,Canvas 與 SVG 分別適用於什麼樣的場景呢?本文將詳細介紹我們提供測試多種平臺、多種資料量、多種圖表型別等維度的渲染效能,給出在不同場景下的推薦方案。


首先,放出結論大圖——

Canvas or SVG?一張好圖,兩手準備,就在 ECharts 4.0

圖中,綠色表示推薦使用 SVG,紅色表示推薦使用 Canvas,↑箭頭越多表示推薦程度越強烈,“-”表示兩者差別不大,或者根據不同情況有不同選擇。

我們應該如何讀懂上圖呢?在實際的使用場景中,可能對於同一個圖表多個維度的結論是相反的(比如圖表個數多的時候 SVG ↑↑↑,但是如果資料量也很大又會 Canvas ↑)。這時候,一方面是參考箭頭多少決定哪種影響更大,另一方面如果確實對效能要求比較高,可以參考這個結論自行做更細緻的測試。

因為圖表本身的屬性和展示平臺的變化性可能非常豐富,所以很難簡單地根據某個維度直接給出結論。本文能做的就是儘可能把一些比較確定性的結論告訴大家(比如移動平臺優選 SVG),作為官方給大家指一條相對明確的方向。而使用者在實際的使用過程中,如果碰到了效能瓶頸,可以根據這個進一步測試改進。

另外需要注意的是,本文的結論都是針對 ECharts 4.0 版本的實現測試得出的,不同視覺化工具的實現方式可能並不一定完全適應。後期效能優化後,也可能會引起其他的變動。

下面,我們就一些重要的結論作說明。


移動平臺優選 SVG

在移動端(尤其是低端安卓機)上,由於記憶體和 CPU 資源的限制,Canvas 的表現可能非常差,而相比之下 SVG 就會有很大優勢。

在我們測試的三星 Note 3 和紅米 1s 上,一個包含 10 個資料點的折線圖,用 Canvas 渲染的初始動畫 FPS 分別是 20 與 5;而使用 SVG 渲染,則可以達到 44 與 20。這樣的差異是很明顯可以感知出的。

SVG 在 iOS 平臺的表現也常常優於 Canvas,只是因為 iOS 配置相對更好,這一優勢不太顯著。比如我們測試的 iPhone 7 上,包含 10 個資料點的折線圖在 SVG 和 Canvas 渲染時都是 60 FPS。當資料量達到 1000 時,差異才表現出來,SVG 和 Canvas 分別是 60 與 32 FPS。

因此,我們強烈建議在移動平臺優先選擇 SVG 進行渲染。


圖表個數很多時優選 SVG

當圖表個數很多時,佔用的記憶體很大程度上造成了頁面是否卡頓的體驗差異。在這一情況下,SVG 表現出非常明顯的優勢。

“圖表個數很多”相對電腦端一般需要十來個圖表以上,相對手機端則個位數也會體現出差異。佔對於圖表個數達到 100 個這樣比較極端的情況,Canvas 的記憶體佔用量相比 SVG 可以達到十倍以上。

當你感覺到滾動螢幕頁面卡頓時,可能是因為記憶體佔用較多引起的,這時候可以考慮使用 SVG 渲染。

匯出小檔案高清晰時使用 SVG

SVG 渲染匯出的 SVG 檔案更小,卻可以保持向量無限清晰放大。我們接到使用者反饋經常有在 PDF 中插入圖表的需求,這時如果插入 SVG,不僅可以使圖片更清晰,也可以使 PDF 的尺寸更小。

對於設計師而言,也可以使用匯出的 SVG 進行二次編輯。


部分特殊渲染效果只有 Canvas 支援

除了某些特殊的渲染可能依賴 Canvas:如炫光尾跡特效帶有混合效果的熱力圖等,絕大部分功能 SVG 都是支援的。此外,目前的 SVG 版中,富文字、材質功能尚未實現。

炫光尾跡特效:

Canvas or SVG?一張好圖,兩手準備,就在 ECharts 4.0

帶有混合效果的熱力圖:

Canvas or SVG?一張好圖,兩手準備,就在 ECharts 4.0


資料量特別大時推薦使用 Canvas 渲染

如果資料量比較大(>1000)、和大量圖形高頻率互動時,推薦使用 Canvas 渲染。搭配使用 ECharts 4.0 推出的漸進式渲染,可以有更好的效能表現。


如何指定以 Canvas 或 SVG 渲染

ECharts 預設使用 Canvas 渲染。如果想使用 SVG 渲染,ECharts 程式碼中須包括有 SVG 渲染器模組。

import 'zrender/lib/svg/svg';
複製程式碼

然後,我們就可以在程式碼中,初始化圖表例項時,傳入引數 選擇渲染器型別:

// 使用 Canvas 渲染器(預設)
var chart = echarts.init(containerDom, null, {renderer: 'canvas'});
// 等價於:
var chart = echarts.init(containerDom);

// 使用 SVG 渲染器
var chart = echarts.init(containerDom, null, {renderer: 'svg'}); 
複製程式碼

是不是特別簡單呀?趕緊用起來吧~\(^o^)/~


相關文章