使用平移和缩放 HTML Canvas 中的虚线
Glitch dotted lines in HTML Canvas using translate and scale
我正在尝试做一个 canvas,您可以在其中用鼠标画一条线,并且这条线在绘制时会被镜像。所以最后你得到了一个对称的绘图效果。我写了一个绘图函数并包含了变换和缩放属性。可悲的是现在这条线有一些小的缝隙并且不再流畅了。
function draw() {
ctx.beginPath();
ctx.moveTo(prevX, prevY);
ctx.lineTo(currX, currY);
ctx.translate(canvas.width, 0);
ctx.scale(-1, 1);
ctx.strokeStyle = x;
ctx.lineWidth = y;
ctx.stroke();
ctx.closePath();
}
See screenshot here
没有 translate() 和 scale() 属性,该行很清楚,如您所见 here。你知道为什么这条线是虚线的吗?我该如何解决这个问题?
这是因为每次移动鼠标时,您只画了一条线,不是“正常”就是“镜像”,但不是两者都画。你可以看到你的“点”实际上对应了另一边的破折号。
发生切换是因为您在每个绘制调用中应用了一次 canvas 变换,但没有重置它,所以在第一次鼠标移动时,您镜像了上下文,在第二次移动时,您最终将绘制镜像然后切换回来进行下一步。
要实现您想要的效果,您可以将所有点保存在一个数组中,在每一帧的开头清除上下文并完全重绘线条两次,一次正常,一次镜像。
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
// trace in normal mode
points.forEach(({x, y}) => ctx.lineTo(x, y));
// mirror
ctx.translate(canvas.width, 0);
ctx.scale(-1, 1);
// move to first point so we can paint in a single path
ctx.moveTo(points[0].x, points[0].y);
// trace all the points mirrored
points.forEach(({x, y}) => ctx.lineTo(x, y));
// paint
ctx.stroke();
// reset the context transform
ctx.setTransform(1, 0, 0, 1, 0, 0);
}
我正在尝试做一个 canvas,您可以在其中用鼠标画一条线,并且这条线在绘制时会被镜像。所以最后你得到了一个对称的绘图效果。我写了一个绘图函数并包含了变换和缩放属性。可悲的是现在这条线有一些小的缝隙并且不再流畅了。
function draw() {
ctx.beginPath();
ctx.moveTo(prevX, prevY);
ctx.lineTo(currX, currY);
ctx.translate(canvas.width, 0);
ctx.scale(-1, 1);
ctx.strokeStyle = x;
ctx.lineWidth = y;
ctx.stroke();
ctx.closePath();
}
See screenshot here
没有 translate() 和 scale() 属性,该行很清楚,如您所见 here。你知道为什么这条线是虚线的吗?我该如何解决这个问题?
这是因为每次移动鼠标时,您只画了一条线,不是“正常”就是“镜像”,但不是两者都画。你可以看到你的“点”实际上对应了另一边的破折号。
发生切换是因为您在每个绘制调用中应用了一次 canvas 变换,但没有重置它,所以在第一次鼠标移动时,您镜像了上下文,在第二次移动时,您最终将绘制镜像然后切换回来进行下一步。
要实现您想要的效果,您可以将所有点保存在一个数组中,在每一帧的开头清除上下文并完全重绘线条两次,一次正常,一次镜像。
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
// trace in normal mode
points.forEach(({x, y}) => ctx.lineTo(x, y));
// mirror
ctx.translate(canvas.width, 0);
ctx.scale(-1, 1);
// move to first point so we can paint in a single path
ctx.moveTo(points[0].x, points[0].y);
// trace all the points mirrored
points.forEach(({x, y}) => ctx.lineTo(x, y));
// paint
ctx.stroke();
// reset the context transform
ctx.setTransform(1, 0, 0, 1, 0, 0);
}