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
相关产品推荐
相关产品推荐

