再論HTML散點圖(Scatter Plot)的SVG實現方式
阿新 • • 發佈:2019-02-05
介紹
在上一篇《HTML散點圖(Scatter Plot)的三種不同實現方式效能比較》中,重點比較了散點圖的SVG實現方式和HTML5 Canvas實現方式的不同。這兒再詳細看看使用SVG,預先生成節點和實時載入資料之間的區別。
這兒為了在效能上有所比較,因此將散點數目增加到250,000,並且用於繪製散點的csv檔案由data-generator.py統一生成。原始碼可在此處下載。
data-generator.py
import pandas as pd import numpy as np df = pd.DataFrame(np.random.randint(0,500,size=(250000, 2)), columns=list('xy')) df.to_csv('./data.csv',index=False)
實現方式
1. 預先用後端程式碼在HTML頁面中生成250000個<circle>節點
pre-render-with-csv.js
var el = window.document.querySelector('#dataviz-container') , body = window.document.querySelector('body') , circleId = 'a2324' // say, this value was dynamically retrieved from some database //load data from csv file //d3.csv('data.csv', function(data){ fs.readFile('data.csv', 'utf8', function (err, data) { data = d3.csvParse(data); data.forEach(function(d){ d.x = +d.x; d.y = +d.y; }); console.log(data.length); // generate the dataviz var svg = d3.select(el) .append('svg:svg') .attr('width', 500) .attr('height', 500); svg.selectAll('.circle') .data( data ) .enter() .append('circle') .attr('r', 1) .attr('fill', '#26963c') .attr('cx', function(d){return d.x;}) .attr('cy', function(d){return d.y;}); // save result in an html file, we could also keep it in memory, or export the interesting fragment into a database for later use var svgsrc = window.document.documentElement.innerHTML; fs.writeFile('index-svg-d3-csv-pre-render.html', svgsrc, function(err) { if(err) { console.log('error saving document', err); } else { console.log('The file was saved!'); } }); });
2. 預先用後端程式碼在HTML頁面中生成100000個<circle>節點。剩餘的節點用d3.js程式碼在頁面載入時實時生成
index-svg-d3-csv-partial-render.html
程式碼除了有預先存在的100000個<circle>節點之外,其他程式碼與index-svg-d3-csv.html相同。
3. 所有250000個<circle>節點用d3.js程式碼在頁面載入時實時生成
index-svg-d3-csv.html
//load data from csv file d3.csv('data.csv', function(data){ data.forEach(function(d){ d.x = +d.x; d.y = +d.y; }); // generate the dataviz var svg = d3.select('#dataviz-container') .append('svg:svg') .attr('width', 500) .attr('height', 500); svg.selectAll('.circle') .data( data ) .enter() .append('circle') .attr('r', 1) .attr('fill', '#26963c') .attr('cx', function(d){return d.x;}) .attr('cy', function(d){return d.y;}); });
結果比較
由於三種實現的最後呈現效果一樣,主要就是看一下效能,即頁面的載入時間,見圖1。
如果從最終載入完畢的時間來看,第3種實現用時最短,第1種用時最長。與上一篇部落格裡的觀察一致。由於伺服器就在本地,因此載入csv檔案的時間可以忽略不計。
如果從一開始出現散點來看,則是第1種用時最短,第3種用時最長。
從總體效能來看,如果將散點的數量增加到1,000,000,則載入用時將會達到40秒以上。顯然,從使用者體驗來看,幾十萬的散點圖效能將會超過個人所能忍受的程度。但如果能像第1種實現和第2種實現那樣提前顯示一部分散點,將會有效改善使用者體驗。
第2種實現和第1種相比,犧牲了一部分提前顯示散點的時間,但降低了HTML頁面的大小。
圖1