为何含特定代码行的JS绘图程序在Chrome新版本中异常?
Canvas矩形绘制被覆盖问题(Chrome 119版本兼容)
问题现象
- 核心问题代码位于
handleLineEnd函数内:保留ctx.getImageData(3, 3, 5, 5)行时,新绘制的矩形会覆盖主画布上所有之前的内容;移除该行则可正常叠加多个矩形 - 代码在Chrome 118.0.5993.71中运行正常,Chrome 119.0.6045.106中出现异常
问题代码片段
function handleLineEnd(evt) { { startDrawing = false; var dummy = ctx.getImageData(3, 3, 5, 5); // 引发问题的代码行 ctx.drawImage(canvaslayer, 0, 0); ctxlayer.clearRect(0, 0, el.width, el.height); } }
完整代码示例
JavaScript
var el = document.getElementById("canvasID"); var elcontainer = document.getElementById("containerID"); var ctx = el.getContext('2d'); var startpuntX, startpuntY, eindpuntX, eindpuntY; var startDrawing = false; var container = el.parentNode; var containerHandletje = document.getElementById('containerID'); var ongoingTouches = new Array(); var huidigeKleur = 'black'; var huidigeDikte = 2; var selectie = document.getElementById('drawingtoolID'); elcontainer.setAttribute("style", 'width: ' + (window.innerWidth - 12) + 'px; height: ' + (window.innerHeight - 80) + 'px; overflow: auto;'); el.height = window.innerHeight - 90; el.width = window.innerWidth - 42; canvaslayer = document.createElement('canvas'); canvaslayer.id = 'imageTemp'; canvaslayer.width = el.width; canvaslayer.height = el.height; canvaslayer.style = 'touch-action:none;'; container.appendChild(canvaslayer); ctxlayer = canvaslayer.getContext('2d'); ctxlayer.lineCap = 'round'; ctx.lineWidth = 1; ctx.lineJoin = 'round'; ctx.lineCap = 'round'; ctx.fillStyle = 'white' ctx.fillRect(0, 0, el.width, el.height); ctx.lineWidth = huidigeDikte; canvaslayer.addEventListener('pointerdown', handleLineStart, false); canvaslayer.addEventListener('pointerup', handleLineEnd, false); canvaslayer.addEventListener('pointermove', handleLineMove, false); function handleLineStart(evt) { startpuntX = evt.clientX - el.offsetLeft + pageXOffset + containerHandletje.scrollLeft; startpuntY = evt.clientY - container.offsetTop + pageYOffset + containerHandletje.scrollTop; ctxlayer.lineWidth = huidigeDikte; ctxlayer.strokeStyle = huidigeKleur; ctxlayer.fillStyle = huidigeKleur; startDrawing = true; ctxlayer.stroke(); ctxlayer.beginPath(); handleLineMove(evt); } function handleLineMove(evt) { var x, y, w, h, hokDx, xi, yi, asX, asY, asXeind, asYeind, fontsize, dzx, dzy, situatie; if (startDrawing) { eindpuntX = evt.clientX - el.offsetLeft + pageXOffset + containerHandletje.scrollLeft; eindpuntY = evt.clientY - container.offsetTop + pageYOffset + containerHandletje.scrollTop; ctxlayer.clearRect(0, 0, el.width, el.height); ctxlayer.beginPath(); ctxlayer.moveTo(startpuntX, startpuntY); x = Math.min(startpuntX, eindpuntX); y = Math.min(startpuntY, eindpuntY); w = Math.abs(startpuntX - eindpuntX); h = Math.abs(startpuntY - eindpuntY); ctxlayer.strokeRect(x, y, w, h); ctxlayer.stroke(); ctxlayer.beginPath(); } } function handleLineEnd(evt) { { startDrawing = false; var dummy = ctx.getImageData(3, 3, 5, 5); // 问题行 ctx.drawImage(canvaslayer, 0, 0); ctxlayer.clearRect(0, 0, el.width, el.height); } }
CSS
#containerID { position: relative; } #canvasID { border: 1px solid #000; } #imageTemp { position: absolute; top: 1px; left: 11px; }
HTML
<div id="containerID" style="touch-action:none; width: 100px; height: 500px; overflow: auto;"> <canvas id='canvasID' width='80' height='80' style='margin-left:10px;background:white;border:solid black 1px; touch-action:none; '> Your browser does not support canvas element. </canvas> </div>
问题原因
Chrome 119版本对Canvas API内部实现做了调整:getImageData调用会触发主画布的缓冲区重置或状态刷新,导致后续drawImage操作不再是叠加绘制,而是直接覆盖整个画布内容。旧版本Chrome中该操作不会影响绘制叠加逻辑。
解决方案
方案1:移除冗余的getImageData调用
该行代码仅获取小块图像数据但未使用,属于冗余代码。移除后drawImage会正常将临时画布内容叠加到主画布:
function handleLineEnd(evt) { startDrawing = false; ctx.drawImage(canvaslayer, 0, 0); ctxlayer.clearRect(0, 0, el.width, el.height); }
方案2:重置画布路径状态(若有隐含需求)
如果原代码中getImageData是为了触发画布状态同步,可替换为beginPath()重置路径状态,避免覆盖问题:
function handleLineEnd(evt) { startDrawing = false; ctx.beginPath(); // 替代原问题行 ctx.drawImage(canvaslayer, 0, 0); ctxlayer.clearRect(0, 0, el.width, el.height); }
验证
修改后在Chrome 119.0.6045.106中测试,可正常绘制并保留多个矩形,与Chrome 118版本表现一致。
内容的提问来源于stack exchange,提问作者Stefan Hesman
相关产品推荐
相关产品推荐

