Volv
Volv

Reputation: 73

Issue with slow updating of html 5 canvas after mousemove / mouseclick event

I have recently been experimenting for the first time with html 5 and specifically the canvas object.

I seem to be having some issue with mouse events.

The program is a grid of faces with different coloured backgrounds randomly changed. There is a cloud shape on top that I am using as a clipping region to be able to see only the parts of the grid under the cloud. (Think oddly shaped torch beam)

The issue is that I am trying to move the cloud region with the mouse and it does not update smoothly with either mousemove or mouseclick events. Seems to take a frame or two to catch up while the cycling colours appear to carry on.

I have tried:

Can be seen running here - http://jsfiddle.net/mXrNk/14/

Any help would be appreciated. Probably missing something obvious.

<script>

const FPS = 60;
var myimg = new Image();

window.addEventListener('click', clicked, true);

var mouseX = 170;
var mouseY = 80;

window.onload = init;

function init() {

    canvas = document.getElementById('myCanvas');
    context = canvas.getContext('2d');

    myimg.src = "smile.png";

    setInterval(draw, 1000/FPS);

}

function draw() {

    context.clearRect(0,0,canvas.width,canvas.height);
    // draw cloud
    context.beginPath(); // begin custom shape
    context.moveTo(mouseX, mouseY);
    context.bezierCurveTo(mouseX-40, mouseY+20, mouseX-40, mouseY+70, mouseX+60, mouseY+70);
    context.bezierCurveTo(mouseX+80, mouseY+100, mouseX+150, mouseY+100, mouseX+170, mouseY+70);
    context.bezierCurveTo(mouseX+250, mouseY+70, mouseX+250, mouseY+40, mouseX+220, mouseY+20);
    context.bezierCurveTo(mouseX+260, mouseY-40, mouseX+200, mouseY-50, mouseX+170, mouseY-30);
    context.bezierCurveTo(mouseX+150, mouseY-75, mouseX+80, mouseY-60, mouseX+80, mouseY-30);
    context.bezierCurveTo(mouseX+30, mouseY-75, mouseX-20, mouseY-60, mouseX, mouseY);
    context.closePath(); // complete custom shape
    context.lineWidth = 5;
    context.strokeStyle = "#0000ff";
    context.stroke();

    context.save();
    context.clip();

    for (i = 0; i<7; i++) {
        for (j = 0; j < 13; j++) {
            context.strokeRect(j*myimg.width,  i*myimg.height, myimg.width, myimg.height);
            context.fillStyle = rndColor();
            context.fillRect(j*myimg.width,  i*myimg.height, myimg.width, myimg.height);
            context.drawImage(myimg, j*myimg.width, i*myimg.height);
            context.fillStyle = "black";
            context.font = "italic 10pt Arial ";
            context.fillText((i*13)+j, j*myimg.width+5,i*myimg.width+15);
        }
    }   

    context.restore();

}

function rndColor() {
    return '#' + ('00000' + (Math.random() * 16777216 << 0).toString(16)).substr(-6);
}

function clicked(e) {
    mouseX = e.pageX;
    mouseY = e.pageY;
}

</script>

Upvotes: 0

Views: 2309

Answers (1)

Loktar
Loktar

Reputation: 35309

Live Demo

I used setTimeout rather than setInterval. When using an interval if it tries to run the function before its finished the events will build up and still continue to try and run while the calls are still building up.

A timeout however will only call the function once, then you can just set another timeout at the bottom of the function to call itself again. Doing it that way ensures the function has completed, and doesn't cause a buildup of calls waiting to be processed.

Also take a look at this article,

https://simonsarris.com/increasing-performance-by-caching-paths-on-canvas/

Its about caching your paths. Its actually by Simon Sarris who I bet will pop in and see this question as well.

Upvotes: 3

Related Questions