简体   繁体   中英

increase performance on html canvas mousemove image mask

I have a canvas that is drawing an image and clipping to create the effect that the image is being revealed. I have the code working properly I have tried using a debouce method and also rAF to increase the canvas rendering performance but I only saw small gains if any.

I suspect the way I am iterating through my array of x and y coordinates could be the issue. It seems to lag quite a bit when it is out putting the array in console about the same rate as the circle appear on the screen.

Here is the redraw function:

  function redraw(mouse) {
     m.push(mouse);
     m.forEach(function (a) {
        ctx.drawImage(img, 0, 0);
        ctx.beginPath();
        ctx.rect(0, 0, 500, 500);
        ctx.arc(a.x, a.y, 70, 0, Math.PI * 2, true);
        ctx.clip();
        ctx.fillRect(0, 0, 500, 500)
      })
    }

I guess what I am looking for is some advice to speed up my code so the rendering of the circles seems more like drawing.

Here is the working demo -> http://jsfiddle.net/naeluh/4h7GR/

There are several issues here :
• Your mouse code is a nightmare, traversing the DOM on every move.
• You are redrawing everything on each move.

So i suggest a way more efficient solution :
• stack two canvases, the one below is your image, the one on top is the mask.
• Deal efficiently with the mouse.
• Only clear part of the mask canvas on mouse move : just one circle drawn on the mask canvas for each move.
(for that i used a globalCompositeOperation = 'destination-out' )

Result is perfectly smooth either on Firefox, Chrome, or Safari .

(tested on mac OS).

the fiddle : (you have to click to clear)

http://jsfiddle.net/gamealchemist/4h7GR/22/

html

<canvas   style='position: absolute; top: 0;left: 0;' id="canvas1" width="500" height="500"></canvas>
<canvas style='position: absolute;top: 0;left: 0;' id="canvas2" width="500" height="500"></canvas>

js

var can = document.getElementById("canvas1");
var ctx = can.getContext("2d");
var can2 = document.getElementById("canvas2");
var ctx2 = can2.getContext("2d");

var img = new Image();
img.onload = function () { ctx.drawImage(img,0,0); };
img.src = "http://placekitten.com/500/500";

ctx2.fillStyle='#000';
ctx2.fillRect(0,0,500,500);
ctx2.globalCompositeOperation = 'destination-out';

function clearThis(x,y) {
    console.log('toto');
    ctx2.fillStyle='#F00000';
    ctx2.beginPath();
    ctx2.arc(x, y, 70, 0, Math.PI * 2, true);
    ctx2.fill();
}

var mouse = {
    x: 0,
    y: 0,
    down: false
};

function setupMouse(canvas, onMouseMove, preventDefault) {
    var rectLeft, rectTop;
    var hook = canvas.addEventListener.bind(canvas);
    var mouseDown = updateMouseStatus.bind(null, true);
    var mouseUp = updateMouseStatus.bind(null, false);
    hook('mousedown', mouseDown);
    hook('mouseup', mouseUp);
    hook('mousemove', updateCoordinates);
    hook('scroll', updateRect);
    // var mouseOut = function() { mouse.down=false ; } ;
    // hook('mouseout', mouseOut); 
    function updateMouseStatus(b, e) {
        mouse.down = b;
        updateCoordinates(e);
        if (preventDefault) {
            e.stopPropagation();
            e.preventDefault();
        }
    }

    function updateCoordinates(e) {
        mouse.x = (e.clientX - rectLeft);
        mouse.y = (e.clientY - rectTop);
        onMouseMove(mouse.x, mouse.y);
    }

    function updateRect() {
        var rect = canvas.getBoundingClientRect();
        rectLeft = rect.left;
        rectTop = rect.top;
    }
    updateRect();
};    
setupMouse(can2, clearThis, true);

The Above Code will do Fine .. But nEed some Editing I have Edited the Code in Fiddle ..and i beleive there Is some Improvement in perforamnce

  1. So I looked a little more and found a bug as expected. The main problem is the accumulation of the drawing path.

Why Need to add clip and fillRect at every go ..Do it at last... the Major issue solved,Like

can.addEventListener("mousemove", function (e) {
var mouse = getMouse(e, can);
requestAnimationFrame(function () {
    redraw(mouse);
            ctx.clip();
    ctx.fillRect(0, 0, 500, 500);
    console.log(mouse);
});
}, false);

  • 2.The Updated JSFiidle is

UpdatedFiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM