多Canvas同步渲染问题:首个Canvas内球体消失的解决咨询
多个Canvas元素更新时首个球体消失的修复
问题原因
核心问题出在canvasDiv.innerHTML +=的使用方式:每次执行该操作时,浏览器会重新解析并渲染canvasDiv容器内的全部HTML,这会直接销毁原有Canvas元素及其对应的绘图上下文对象(ctx)。第一个Canvas的update函数后续操作的是已经失效的上下文,因此球体无法继续显示。
解决方案
改用DOM API创建元素并通过appendChild追加,避免破坏已存在的DOM元素及其上下文。
修改后的代码
方式一:通过容器包裹元素后追加
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) // 创建容器包裹canvas和p标签 let container = document.createElement('div'); container.innerHTML = `<canvas class="canvas" id="myCanvas${myCanvasId}"></canvas><p>${myCanvasId}</p>`; // 追加到容器末尾,不影响已有元素 canvasDiv.appendChild(container); runCode(myCanvasId) }, 1000*i) }
方式二:直接创建单个元素并追加
如果想更精细地控制DOM元素,可以分别创建Canvas和p标签:
// 其余runCode函数部分不变 for(i = 0; i < 2; i++){ let myCanvasId = i setTimeout(function(){ console.log(myCanvasId) // 创建Canvas元素 let canvas = document.createElement('canvas'); canvas.className = 'canvas'; canvas.id = `myCanvas${myCanvasId}`; // 创建文本标签 let p = document.createElement('p'); p.textContent = myCanvasId; // 依次追加到canvasDiv canvasDiv.appendChild(canvas); canvasDiv.appendChild(p); runCode(myCanvasId) }, 1000*i) }
原理说明
使用appendChild只会将新元素追加到容器的末尾,不会触发已有DOM元素的重新渲染,第一个Canvas的绘图上下文(ctx)保持有效,update函数能持续对其进行绘图操作,因此两个Canvas的球体都能正常显示。
内容的提问来源于stack exchange,提问作者Caetano Leal
相关产品推荐
相关产品推荐

