別再比圖表套件了,該比的是繪製模式
ECharts、Highcharts 與 Chart.js 之間的差距通常在兩倍以內,而 SVG 與 canvas 的差別根本不是同一種形狀——一個隨資料成長,另一個不會。

問題大致上都長這樣:我們有十萬個點,該用 ECharts、Highcharts 還是 Chart.js? 這是個合理的問題,但它瞄準的是錯的變數。
套件的差距是常數,模式的差距是斜率
拿主流套件在同一份工作負載下互相跑分,結果大多落在兩倍以內。那是真實的差距, 但那是一個常數——換套件要花掉你一整天,換來一個固定的兩倍。
模式的選擇不是常數,它改變的是曲線的形狀。以下是寫這篇文章時,用這一頁自己的 工具在一台普通筆電上量到的:
| 點數 | SVG | Canvas |
|---|---|---|
| 500 | 28 毫秒 | 33 毫秒 |
| 2,000 | 32 毫秒 | 32 毫秒 |
| 5,000 | 33 毫秒 | 29 毫秒 |
| 10,000 | 49 毫秒 | 28 毫秒 |
| 20,000 | 80 毫秒 | 26 毫秒 |
這張表裡有兩件事比那個頭條數字更值錢。
五千個標記以內,根本沒有故事。 SVG 完全夠用。有人叫你在兩千點的時候就改用 canvas,那是在最佳化一個根本沒有在花錢的地方。
canvas 是平的,SVG 不是。 canvas 從五百點到兩萬點成本幾乎沒變,因為你付的是 像素的錢,而像素沒變多。SVG 一路往上爬,因為每個標記都是又一個要建立、要排版、 要套樣式、要繪製的 DOM 節點。那條斜率就是整個論點——重點不是 canvas 今天比較快, 而是你的資料長大時 SVG 會變慢,canvas 不會。
在你自己的機器上量
上面那張表是一台筆電。你的是另一台,交叉點會跟著移動。從兩千點開始往上加, 加到 SVG 那個數字開始爬升為止——那就是你自己的門檻。
你這台瀏覽器量到的結果
每次量測本身帶有約一到兩幀的底噪,所以低點數下的細微差距是雜訊。要看的是曲線的形狀,不是單一個數字。
還沒量過。
這裡的 SVG 模式是一個點一個 DOM 節點,那正是散點圖、長條圖與帶標記的折線圖
真正的長相。單純的 SVG 折線圖只有一個 <path>,一直都很便宜——會爆炸的是
節點數,不是 SVG 這個格式本身。
關於那些數字有一個必須講清楚的地方:每次量測本身帶有約一到兩幀的固定底噪, 這就是為什麼五百點那一列是 28 毫秒而不是接近零。要讀的是斜率,不是那條底線。
你的套件用的是哪一種?
| 套件 | 預設模式 | 怎麼切換 |
|---|---|---|
| D3 | SVG | 自己畫進 canvas context |
| Chart.js | Canvas | — |
| ECharts | Canvas(也支援 SVG) | renderer: 'svg' |
| Highcharts | SVG | boost 模組 → WebGL |
| Plotly | SVG(也支援 WebGL) | 用 scattergl 取代 scatter |
| Recharts | SVG | — |
| uPlot | Canvas | — |
把這張表跟你剛剛量到的數字擺在一起看。多數被說成「畫不動大量資料」的套件, 其實是預設走 SVG 的套件被要求做 canvas 的工作——而其中好幾個,切換只要一行。
這對決策代表什麼
- 用標記數量決定模式,不是用品牌。 幾千個標記以內,SVG 換給你真的 DOM 節點:可 hover、可用 CSS 設樣式、可檢視、螢幕閱讀器讀得到,而且量不出代價。 超過之後,節點數的代價就開始比那些互動更貴——而且它在每一次重排都要再付一次, 不是只有第一次繪製。
- 然後才是減少要畫的東西。 繪製前先降採樣是這個問題的另一半, 它與模式的選擇是相乘的,不是互相取代。
- 最後才挑套件,看 API、看生態系、看它在你的框架裡怎麼渲染。走到這一步時, 效能已經不是決定因素了——那才是正確的終點。
常見追問
SVG 是不是永遠都不該用?
不是。幾千個標記以內,SVG 很舒服,而且你拿到的是真的 DOM 節點—— 可以單獨 hover、可以用 CSS 設樣式、可以檢視、螢幕閱讀器讀得到。那些很值錢。 問題只在節點數成長得比洞察還快的時候才開始。
成本到底是從哪裡來的?
每個 SVG 元素都是一個真的 DOM 節點,要建立、要排版、要套樣式、要繪製, 而且之後每一次重排都還要再付一次。canvas 不管畫幾個標記都只是一個節點—— 你付的是像素的錢,不是結構的錢。
那我每個點都需要 tooltip 怎麼辦?
畫在 canvas 上,然後自己對底層資料做 hit-testing,通常用 quadtree 或直接把 比例尺反過來算。這就是那筆標準交易:放棄免費的 DOM 互動, 換回一個「不再隨資料筆數成長」的成本。
什麼時候該從 canvas 換到 WebGL?
大約在 canvas 也塞不進一幀的時候——很粗略地說是十萬個標記以上, 或是需要在拖曳與縮放時持續重繪。在那之前,canvas 簡單得多,而且夠快。