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

Canvas连续线条绘制问题:快速绘制时线条呈分散圆点

Canvas自由画线快速绘制出现断点的解决方案

问题描述

我编写了一段模仿画图软件实现自由画线的Canvas代码,正常速度绘制能得到连续线条,但快速绘制时线条会变成分散的圆点,想知道有没有相关属性或函数可以解决该问题?

原代码

JavaScript

const canvas = document.getElementById("canv");
let mousedown = false;
const ctx = canvas.getContext("2d");
ctx.lineWidth = 5;
let x;
let y;
window.addEventListener("mousedown", (event) => {

  console.log('clicked');
  if (event.which == 3) {
    mousedown = false;

  } else if (event.which == 1) {
    mousedown = true;
  }

  window.addEventListener('contextmenu', (event) => {
    event.preventDefault();
  })

  window.addEventListener("mousemove", (event) => {
    if (mousedown) {
      document.body.style.cursor = "crosshair";
      console.log("MOVING");
      ctx.beginPath();
      x = event.clientX - 100;
      y = event.clientY - 100;
      ctx.moveTo(x, y);
      ctx.arc(x, y, 2, 0, 2 * Math.PI, false);
      ctx.strokeStyle = 'black';
      ctx.stroke();
      ctx.closePath();
    } else if (!mousedown) {
      document.body.style.cursor = "crosshair";
      console.log("MOVING");
      ctx.beginPath();
      x = event.clientX - 100;
      y = event.clientY - 100;
      ctx.moveTo(x, y);
      ctx.arc(x, y, 0.5, 0, 2 * Math.PI, true);
      ctx.strokeStyle = 'white';
      ctx.stroke();
      ctx.closePath();
    }

  })
})

CSS

canvas {
  position: absolute;
  top: 100px;
  left: 100px;
  border: 1px solid;
}

HTML

<canvas id="canv" width="700" height="700">
        Your Browser Doesn't Support Canvas.
    </canvas>

问题原因

原代码通过在鼠标移动的每个触发点绘制小圆点拼接线条,当鼠标快速移动时,mousemove事件的触发间隔会变大,点与点之间的距离超过圆点覆盖范围,就会出现断点。

解决方案

不要用圆点拼接线条,改为记录上一个鼠标位置,每次移动时用lineTo()连接当前位置与上一个位置,无论移动速度快慢,线条都会保持连续。

修改后的代码

JavaScript

const canvas = document.getElementById("canv");
let mousedown = false;
const ctx = canvas.getContext("2d");
ctx.lineWidth = 5;
ctx.lineCap = "round"; // 让线条端点和连接处更圆润
let lastX, lastY; // 记录上一个鼠标位置

// 提前绑定右键菜单阻止事件,避免重复绑定
window.addEventListener('contextmenu', (event) => {
  event.preventDefault();
});

window.addEventListener("mousedown", (event) => {
  if (event.which === 1) { // 左键按下开始绘制
    mousedown = true;
    // 记录初始位置
    lastX = event.clientX - 100;
    lastY = event.clientY - 100;
    document.body.style.cursor = "crosshair";
  } else if (event.which === 3) { // 右键按下停止绘制
    mousedown = false;
  }
});

window.addEventListener("mousemove", (event) => {
  if (!mousedown) return;
  
  const currentX = event.clientX - 100;
  const currentY = event.clientY - 100;
  
  ctx.beginPath();
  ctx.moveTo(lastX, lastY); // 从上一个位置开始
  ctx.lineTo(currentX, currentY); // 连接到当前位置
  ctx.strokeStyle = 'black';
  ctx.stroke();
  ctx.closePath();
  
  // 更新上一个位置为当前位置
  lastX = currentX;
  lastY = currentY;
});

// 鼠标松开时停止绘制
window.addEventListener("mouseup", () => {
  mousedown = false;
});

关键改进点

  • 新增lastX、lastY变量记录上一次鼠标位置,用lineTo()连接前后点,确保线条连续
  • 设置ctx.lineCap = "round",让线条的端点和转弯处更圆润,贴近画图软件的绘制效果
  • 调整事件监听结构,避免重复绑定右键菜单阻止事件
  • 增加mouseup事件监听,确保鼠标松开后立即停止绘制

内容的提问来源于stack exchange,提问作者IBdr

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 04:15:42