使用平移和缩放 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);
}