2016-04-19 57 views
2

我有一個畫布,我在其中製作動畫。我聽取窗口大小調整事件,更新畫布大小並再次啓動遞歸繪圖。但它似乎像舊的draw()調用繼續,這導致動畫比預期的更快。 下面是代碼:調整大小後,HTML畫布更新太多次

HTML

<canvas id="myCanvas" width="1000" height="1000"></canvas> 

CSS

* { 
    margin: 0; 
    padding: 0; 
} 

html, 
body { 
    width: 100%; 
    height: 100%; 
} 

canvas { 
    display: block; 
} 

的JavaScript

var canvas = document.getElementById("myCanvas"); 
var context = canvas.getContext('2d'); 
var frameCount = 0; 
var count = 0; 

var rectDistance = 100; 
var rectSize = 72; 
var rectOffset = (rectDistance - rectSize)/2; 
var angleSpeed = 1; 

var draw = function() { 
    count++; 

    var xCount = canvas.width/rectDistance; 
    var yCount = canvas.height/rectDistance; 

    context.fillStyle = "rgba(255,255,255,1)"; 
    context.fillRect(0, 0, canvas.width, canvas.height); 

    for (var i = 0; i < xCount; i++) { 
    for (var j = 0; j < yCount; j++) { 

     context.save(); 

     var r = Math.round(i/xCount * 255); 
     var g = Math.round(j/xCount * 255); 

     xPos = i * rectDistance + rectOffset + Math.sin(j + frameCount/20) * 10; 
     yPos = j * rectDistance + rectOffset + Math.cos(i + frameCount/20) * 10; 

     context.translate(xPos + rectSize/2, yPos + rectSize/2); 
     context.rotate(frameCount/100 * angleSpeed * Math.sin(frameCount/500) * 5); 

     context.fillStyle = "rgba(" + r + "," + g + ",0,1)"; 
     context.fillRect(-rectSize/2, -rectSize/2, rectSize, rectSize); 
     context.restore(); 
    } 
    } 

    frameCount = frameCount + 1; 
    requestAnimationFrame(draw); 
}; 

window.addEventListener('resize', function() { 
    setTimeout(function() { 
    resizeCanvas(); 
    }, 500); 
}, false); 

function resizeCanvas() { 
    canvas.width = window.innerWidth; 
    canvas.height = window.innerHeight; 

    draw(); 
} 

// count the calls of draw() per second -> it's increasing on window.resize 
function drawCalls() { 
    setTimeout(function() { 
    console.log("draw() called " + count + " times"); 
    count = 0; 
    drawCalls(); 
    }, 1000) 
} 
drawCalls(); 

// start the loop 
resizeCanvas(); 

如何防止舊的平局()調用繼續在調整大小遞歸執行?

這裏是同一個問題一個codepen:http://codepen.io/Sebkasanzew/pen/GZGZVP

+1

如果你不停止你的循環,你爲什麼調用resize事件中的繪製? btw調整大小的事件可能會以比rAF更高的速度發射。 [分支筆](http://codepen.io/anon/pen/QNxEMN) – Kaiido

+0

在resize事件之外調用draw()可解決問題。但是,然後創建繪製的對象不會再次執行,對吧?但是這至少解決了這個例子的問題,謝謝。 是不是有另一種方式? – SebKas

+1

永久運行的動畫,我會在兩個單獨的步驟:一個應用程序更新一個和一個繪圖。在調整大小時,您只需調用應用程序更新,重置所有變量,並且繪圖函數將僅消耗每幀中的變量。 – Kaiido

回答

3

你忘記取消setTimeout() - 我建議如下:

var timer; 

window.addEventListener('resize', function() { 
    cancelAnimationFrame(timer);     // cancel previous request 
    timer = requestAnimationFrame(function() { // create a new request 
    resizeCanvas(); 
    }) 
}); 
+0

這就是我一直在尋找的。謝謝! – SebKas