You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何含特定代码行的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 21:47:06