不要在事件處理程式中繪製動畫(一個簡單的草圖應用程式)

mousemove 期間,每秒鐘會有 30 個滑鼠事件被淹沒。你可能無法以每秒 30 次的速度重繪圖形。即使你可以,你也可能在瀏覽器未準備好繪製時浪費計算能力(浪費= =跨越顯示重新整理週期)。

因此,將使用者輸入事件(如 mousemove)與動畫繪圖分開是有意義的。

  • 在事件處理程式中,儲存控制圖形在畫布上的位置的所有事件變數。但實際上並沒有畫任何東西。

  • requestAnimationFrame 迴圈中,使用儲存的資訊將所有繪圖渲染到畫布。

通過不繪製事件處理程式,你不會強制 Canvas 嘗試以滑鼠事件速度重新整理複雜的繪圖。

通過在 requestAnimationFrame 中完成所有繪製,你將獲得此處描述的所有好處使用’requestanimationFrame’而不是’setInterval’來表示動畫迴圈

帶註釋的程式碼:

<!doctype html>
<html>
<head>
<style>
    body{ background-color: ivory; }
    #canvas{border:1px solid red; }
</style>
<script>
window.onload=(function(){

    function log(){console.log.apply(console,arguments);}

    // canvas variables
    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var cw=canvas.width;
    var ch=canvas.height;
    // set canvas styling
    ctx.strokeStyle='skyblue';
    ctx.lineJoint='round';
    ctx.lineCap='round';
    ctx.lineWidth=6;

    // handle windows scrolling & resizing
    function reOffset(){
        var BB=canvas.getBoundingClientRect();
        offsetX=BB.left;
        offsetY=BB.top;        
    }
    var offsetX,offsetY;
    reOffset();
    window.onscroll=function(e){ reOffset(); }
    window.onresize=function(e){ reOffset(); }

    // vars to save points created during mousemove handling
    var points=[];
    var lastLength=0;

    // start the  animation loop
    requestAnimationFrame(draw);

    canvas.onmousemove=function(e){handleMouseMove(e);}

    function handleMouseMove(e){
        // tell the browser we're handling this event
        e.preventDefault();
        e.stopPropagation();

        // get the mouse position
        mouseX=parseInt(e.clientX-offsetX);
        mouseY=parseInt(e.clientY-offsetY);

        // save the mouse position in the points[] array
        // but don't draw anything
        points.push({x:mouseX,y:mouseY});
    }

    function draw(){
        // No additional points? Request another frame an return
        var length=points.length;
        if(length==lastLength){requestAnimationFrame(draw);return;}
        
        // draw the additional points
        var point=points[lastLength];
        ctx.beginPath();
        ctx.moveTo(point.x,point.y)
        for(var i=lastLength;i<length;i++){
            point=points[i];
            ctx.lineTo(point.x,point.y);
        }
        ctx.stroke();
        
        // request another animation loop
        requestAnimationFrame(draw);
    }

}); // end window.onload
</script>
</head>
<body>
    <h4>Move mouse over Canvas to sketch</h4>
    <canvas id="canvas" width=512 height=512></canvas>
</body>
</html>