Canvas画矩形路径为什么最后一条边不显示?

设计师淑然 阅读 26

我在用Canvas画矩形路径时,明明设置了closePath,但最后一条边总是断开的。比如这样画:


function drawRect(ctx, x, y, w, h) {
  ctx.beginPath();
  ctx.moveTo(x, y);
  ctx.lineTo(x + w, y);
  ctx.lineTo(x + w, y + h);
  ctx.lineTo(x, y + h);
  ctx.closePath();
  ctx.stroke();
}

运行后右边和底边连接处会有缺口,像被截断一样。试过把closePath换成ctx.lineTo(x,y)再stroke,反而正常了。这是不是路径绘制顺序的问题?

我来解答 赞 5 收藏
二维码
手机扫码查看
2 条解答
UX-淑萍
UX-淑萍 Lv1
这个问题大概率是浮点数精度导致的,Canvas在处理路径闭合时,最后的连接点可能会因为亚像素渲染出现偏差。换成手动连回起点的方式确实能解决,但更好的做法是调整坐标确保对齐像素网格。

给你个改进版,把坐标都取整,复制过去试试:

function drawRect(ctx, x, y, w, h) {
x = Math.floor(x);
y = Math.floor(y);
w = Math.round(w);
h = Math.round(h);

ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x + w, y);
ctx.lineTo(x + w, y + h);
ctx.lineTo(x, y + h);
ctx.closePath();
ctx.stroke();
}


这样处理后,路径的每个点都落在整数像素上,避免了亚像素渲染的问题。如果还要填充的话,效果会更明显。实在不行你也可以用rect方法,它底层做了优化处理:

function drawRect(ctx, x, y, w, h) {
ctx.beginPath();
ctx.rect(x, y, w, h);
ctx.stroke();
}


这两种方式都能解决问题,看你具体需求选一个用就行。
点赞 2
2026-02-15 12:17
迷人的柯一
这根本不是路径顺序的问题,是描边宽度和像素对齐搞的鬼。你用closePath的时候,Canvas会自动连接最后一个点到第一个点,但这个连接线可能落在非整数像素上,加上描边有一定宽度,边缘就被截断了。

最简单的解决方法是把起始坐标取整:

function drawRect(ctx, x, y, w, h) {
x = Math.floor(x);
y = Math.floor(y);
w = Math.floor(w);
h = Math.floor(h);

ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x + w, y);
ctx.lineTo(x + w, y + h);
ctx.lineTo(x, y + h);
ctx.closePath();
ctx.stroke();
}


或者更高效的做法,直接用ctx.rect(x, y, w, h),一行搞定,性能更好还不会出问题:

ctx.beginPath();
ctx.rect(x, y, w, h);
ctx.stroke();


rect方法底层做了优化,路径构建效率比手动四个lineTo高,而且闭合逻辑更可靠。别折腾moveTo和lineTo了,这种标准图形就用原生API。
点赞
2026-02-12 06:03