Kirdeika
Kirdeika

Reputation: 237

Canvas image leaves weird trail when moving left

I have an HTML5 Canvas where I need to move 2 copies of main object to right and left. Right side seems to be working fine, but left one starts to leave weird greenish trail. jSfiddle link here

Here is the code. Assignment requires me to write word using various canvas shapes and also frame it into 3 different cubes. I think I missed something ad can't really figure it out. Any help is appreciated

var c = document.getElementById("cId");
    var ctx = c.getContext("2d");

    var cWidth = c.width;
    var cHeight = c.height;

    var xOff = 1;

    var direction = 1;

    function playAnimation() {
        ctx.clearRect(0, 0, cWidth, cHeight);

        ctx.save();
        ctx.translate(xOff, 0);
        drawName();
        ctx.restore();

        ctx.save();

        ctx.translate(-1*xOff, 0);
        drawName();
        ctx.restore();

        ctx.save();
        drawName();
        ctx.restore();

        xOff++;

        window.requestAnimationFrame(playAnimation);
    }

    function fDrawRect() {
        ctx.beginPath();
        ctx.fillStyle = "red";
        ctx.rect(5, 5, 80, 60);
        ctx.fillRect(5, 5, 80, 60);
        ctx.stroke();
        ctx.beginPath();
        ctx.fillStyle = "blue";
        ctx.rect(85, 5, 80, 60);
        ctx.fillRect(85, 5, 80, 60);
        ctx.stroke();
        ctx.beginPath();
        ctx.fillStyle = "yellow";
        ctx.rect(165, 5, 80, 60);
        ctx.fillRect(165, 5, 80, 60);
        ctx.stroke();
    }

    function draw(x, y, xTo, yTo, color) {
        ctx.beginPath();
        ctx.lineWidth= 2;
        ctx.strokeStyle=color;
        ctx.moveTo(x,y);
        ctx.lineTo(xTo,yTo);
        ctx.stroke();

    }

    function drawName() {
        //Draw rect around
        fDrawRect();
        //L
        draw(10, 10, 10, 60, "black");
        draw(10, 60, 30, 60, "black");
        //A
        ctx.beginPath();
        ctx.arc(60, 25, 15, 1*Math.PI, 0);
        ctx.stroke();
        draw(45, 25, 45, 60, "black");
        draw(75, 25, 75, 60, "black");
        draw(45, 35, 75, 35, "black");
        //U
        ctx.beginPath();
        ctx.moveTo(90, 45);
        ctx.quadraticCurveTo(105, 75, 125, 45);
        ctx.stroke();
        draw(90, 45, 90, 10, "black");
        draw(125, 45, 125, 10, "black");
        //R
        draw(140, 10, 140, 60, "black");
        ctx.beginPath();
        ctx.arc(140, 25, 15, 1.5*Math.PI, 0.5*Math.PI);
        ctx.stroke();
        draw(140, 40, 155, 60, "black");
        //I
        draw(170, 10, 170, 60, "black");
        //S
        ctx.beginPath();
        ctx.moveTo(210, 10);
        ctx.bezierCurveTo(170, 10, 250, 60, 190, 60);
        ctx.stroke();

    }
    ctx.translate(450, 150);
    //drawName();
    playAnimation();

Upvotes: 4

Views: 1785

Answers (2)

ArneHugo
ArneHugo

Reputation: 6489

Problem

When you attempt to clear the canvas in the beginning of playAnimation (using ctx.clearRect(0, 0, cWidth, cHeight)), you don't clear the entire area visible in the canvas.

Proof: If you draw a rect to cover the area you clear in playAnimation, you see that it does not start in the upper left corner like it should (fiddle).

The reason it does not work is this line, that translates the context once before you start rendering:

ctx.translate(450, 150);

When you remove it, you see that the the entire visible area is cleared (fiddle). However, now you don't get the name in the middle of the canvas.

Solution

The solution is to do the translation at the beginning of each playAnimation(), and to undo the translation at the end of the function (fiddle).

Upvotes: 1

DNKROZ
DNKROZ

Reputation: 2852

You need to clear the canvas in your fDrawRect function:

    function fDrawRect() {
        ctx.clearRect(0, 0, c.width, c.height); //Clear canvas
        ctx.beginPath();
        ctx.fillStyle = "red";
        ctx.rect(5, 5, 80, 60);
        ctx.fillRect(5, 5, 80, 60);
        ctx.stroke();
        ctx.beginPath();
        ctx.fillStyle = "blue";
        ctx.rect(85, 5, 80, 60);
        ctx.fillRect(85, 5, 80, 60);
        ctx.stroke();
        ctx.beginPath();
        ctx.fillStyle = "yellow";
        ctx.rect(165, 5, 80, 60);
        ctx.fillRect(165, 5, 80, 60);
        ctx.stroke();
    }

Upvotes: 2

Related Questions