Search code examples
html5-canvasstroke

How to remove a specific stroke in HTML5 canvas?


I make several strokes in a HTML5 canvas. To make animation with stroke, I clear the previous like this :

    // Notice : canvasWidth, canvasHeight, context are in a parent scope
    function echoLine( posLeftX, posLeftY, posRightX, posRightY) {
        context.beginPath();
        context.moveTo(posLeftX, posLeftY);
        context.clearRect(0, 0, canvasWidth, canvasHeight);
        context.bezierCurveTo(posLeftX, posLeftY, posRightX, posLeftY, posRightX, posRightY);
        context.stroke();
        context.closePath();
    }

My problem is when I want to do several animated lines, context.clearRect() will remove all and I did not find a other way to remove the specific stroke.

Is there a way to clear a specific stroke without workaround, or should I make context by stroke ?


Solution

  • You can keep an array of lines, and draw them all every time, then delete is a simple splice on the array, you just have to slightly change your draw function to clear then loop over the array that is where we do all drawings.

    Here is an example.

    var canvas = document.getElementById("canvas");
    var context = canvas.getContext("2d")
    var lines = []
    
    function draw() {
      context.clearRect(0, 0, canvas.width, canvas.height);
      lines.forEach((e, i) => {
        context.beginPath();
        context.moveTo(e.left.x, e.left.y);    
        context.fillText(i, e.left.x-7, e.left.y);
        context.bezierCurveTo(e.left.x, e.left.y, e.right.x, e.left.y, e.right.x, e.right.y);
        context.stroke();
      })
    }
    
    function animate() {
      lines.forEach((e) => { 
        if (e.right.y > 150 || e.right.y < 0) e.speed *= -1 
        e.right.y += e.speed      
      })
      draw()
    }
    
    document.getElementById('todelete').onkeyup = (event) => {
      if (event.keyCode == 13) {
        lines.splice(event.srcElement.value, 1)
        event.srcElement.value = ""
      }
    };
    
    for (var i = 2; i < 8; i++) {
      lines.push({ 
        left:  { x:10,   y:130 - i*16 }, 
        right: { x:i*30, y:50 - i*6 }, 
        speed: 0.2 + Math.random() 
      })
    }
    
    setInterval(animate, 40)
    input {
      width: 160px
    }
    <input id="todelete" type="number"  min="0" max="5" placeholder="enter number to delete" >
    Press enter to submit.
    <br>
    <canvas id="canvas" width=300 height=150></canvas>