html5-canvas Non disegnare animazioni nei gestori di eventi (una semplice app di schizzo)


Esempio

Durante il mousemove vieni sommerso di 30 eventi del mouse al secondo. Potresti non essere in grado di ridisegnare i tuoi disegni a 30 volte al secondo. Anche se è possibile, si sta probabilmente sprecando potenza di calcolo disegnando quando il browser non è pronto per disegnare (sprecato == tra i cicli di aggiornamento della visualizzazione).

Pertanto ha senso separare gli eventi di input dell'utente (come mousemove) dal disegno delle animazioni.

  • Nei gestori di eventi, salva tutte le variabili evento che controllano dove i disegni sono posizionati sulla tela. Ma in realtà non disegnare nulla.

  • In un ciclo requestAnimationFrame , visualizza tutti i disegni sulla tela utilizzando le informazioni salvate.

Non disegnando i gestori di eventi, non si sta costringendo Canvas per provare ad aggiornare i disegni complessi alla velocità degli eventi del mouse.

Facendo tutto il disegno in requestAnimationFrame ottieni tutti i vantaggi descritti qui. Usa 'requestanimationFrame' non 'setInterval' per i loop dell'animazione .

Codice annotato:

<!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>