2012-12-17 67 views
10

我需要在HTML5畫布上繪製很多點,而且需要很長時間。我的代碼看起來像這樣:加快在HTML5畫布元素上繪製多個點的步驟

var points = getPoints() // Array of {x,y,color} 
var ctx = canvas.getContext("2d"); 

for (var i = 0; i < points.length; i++) { 
    ctx.fillStyle = points[i].color 
    ctx.beginPath() 
    ctx.arc(points[i].x, points[i].y, radius, 0, Math.PI * 2, true) 
    ctx.fill() } 

我想知道我可以做些什麼性能調整來加速它。我只有5種不同的顏色。例如,我是否可以通過即時排序積分列表來改變ctx.fillStyle,而不是每個積分一次?

+0

我覺得這是一個相當緩慢的一行:'ctx.arc( points [i] .x,points [i] .y,radius,0,Math.PI * 2,true)'嘗試繪製簡單的矩形,看看它是否加快速度。 (恕我直言,它應該...) – ppeterka

+1

我試過了,是的,它確實加快了速度。但我不明白這有什麼幫助。 – Nicolas

+1

我想如果你設置一個小提琴,人們可以更容易地調整它,下面是我可以想到的一些修改,使其更快一些(也許) - > [** FIDDLE **](http:// jsfiddle .net/4WTaQ /)... – adeneo

回答

13

例如,如果將點列表即時更改爲ctx.fillStyle,而不是每個點的一次更改ctx.fillStyle,我會受益嗎?

根據我的經驗,是的 - 更改.fillStyle通常是非常昂貴的。

我的代碼是在畫布上繪製大量的矩形,並且繪製只有兩個不常變化的顏色的矩形的繪製時間明顯優於繪製許多頻繁變化的顏色。

總之,因爲你只能有五種不同的顏色:

  1. 創建一個屏幕外的畫布,可以在其中汲取五週界
  2. 使用.drawImage()做塊正確的顏色圈到你的目的地的畫布,而無需重新計算圓弧座標
  3. points[i]分配給循環內部的局部變量,以避免反覆引用它。

在我的筆記本電腦這個代碼是借鑑3000個圓圈400x400的畫布在7毫秒:

var colours = ['red', 'green', 'blue', 'yellow', 'magenta']; 
var n = colours.length; 
var r = 10; 
var d = r * 2; 

var off = document.createElement('canvas'); 
off.width = n * d; 
off.height = d; 
var ctx = off.getContext('2d'); 

for (var i = 0; i < n; ++i) { 
    ctx.fillStyle = colours[i]; 
    ctx.beginPath(); 
    ctx.arc(i * d + r, r, r, 0, 2 * Math.PI); 
    ctx.closePath(); 
    ctx.fill(); 
} 

var canvas = document.getElementById('canvas'); 
var ctx2 = canvas.getContext('2d'); 
var t0 = Date.now(); 
for (var i = 0; i < 3000; ++i) { 
    var c = Math.floor(n * Math.random()); 
    var x = Math.floor(canvas.width * Math.random()); 
    var y = Math.floor(canvas.height * Math.random()); 
    ctx2.drawImage(off, c * d, d, d, x - r, y - r, d, d); 
} 
var t1 = Date.now(); 
alert((t1 - t0) + "ms"); 

http://jsfiddle.net/alnitak/Dpgts/

+0

哇,我的這個效果在3ms。令人印象深刻。非常感謝你! – Nicolas

+0

@Stewie順便說一句,如果你的圈子沒有重疊,你可以使用'.putImageData'加速很多。 – Alnitak

+0

他們沒有。你的意思不是.drawImage()? – Nicolas