javascripthtmlhtml5-canvas

Simultaneous Canvas - Ball Disappears in First Canvas


So, I have this situation where I need to change 2 or more canvas at the same time.

In my code, I generate the canvas by code and modify it. It is a very extense code, so I'll simplify it:

let canvasDiv = document.getElementById("canvasDiv")
let canvasId = 0

function runCode(canvasId){

    let canvas = document.getElementById(`myCanvas${canvasId}`)
    let ctx = canvas.getContext("2d")
    
    let steps = 10000

    function update(){

        steps -= 1

        ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
        ctx.beginPath();

        ctx.fillStyle = "rgb(145, 209, 255)"
        ctx.arc(50, 50, 10, 0, 2 * Math.PI);
        ctx.fill();
            
        ctx.closePath()
        
        if(steps > 0){
            setTimeout(update, 100)
        }
    
    }
    
    update()

}

for(i = 0; i < 2; i++){

    let myCanvasId = i

    setTimeout(function(){

        console.log(myCanvasId)

        canvasDiv.innerHTML += `<canvas class="canvas" id="myCanvas${myCanvasId}"></canvas><p>${myCanvasId}</p>`

        runCode(myCanvasId)

    }, 1000*i)

}


(Btw, if you want the extense version, let me know!)

So, the problem is: everytime I run this code, it creates 2 canvas (as expected), but the ball (which I want to appear in both canvas) disappear on the first one and reappear on the second? How can I solve it so both canvas have the ball?

I have already search on google, but nothing similar appears. I'm trying lots of ways, but nothing works.


Solution

  • You should never call canvasDiv.innerHTML when appending elements. Use document.createElement('canvas') and canvasDiv.appendChild(newCanvas) so that the ref to the old ctx will persist.

    let canvasDiv = document.getElementById("canvasDiv")
    
    
    function runCode(canvasId){
    
        let canvas = document.getElementById(`myCanvas${canvasId}`)
        let ctx = canvas.getContext("2d")
        
        let steps = 10000
    
        function update(){
    
            steps -= 1
    
            ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
            ctx.beginPath();
    
            ctx.fillStyle = "rgb(145, 209, 255)"
            ctx.arc(50, 50, 10, 0, 2 * Math.PI);
            ctx.fill();
                
            ctx.closePath()
            
            if(steps > 0){
                setTimeout(update, 100)
            }
        
        }
        
        update()
    
    }
    
    for(i = 0; i < 2; i++){
    
        let myCanvasId = i
    
        setTimeout(function(){
    
            console.log(myCanvasId)
            
            var newCanvas = document.createElement('canvas');
            newCanvas.id = 'myCanvas' + myCanvasId;
    
            canvasDiv.appendChild(newCanvas)
    
            runCode(myCanvasId)
    
        }, 1000*i)
    
    }
    <div id='canvasDiv' />