Glitch dotted lines in HTML Canvas using translate and scale

Viewed 134

I'm trying to do a canvas where you can draw a line with your mouse and this line is being mirrored while drawing. So at the end you got a symmetry drawing effect. I wrote a draw function and included the transform and scale attribute. Sadly now the line has small little gaps and is not fluent anymore.

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

Without the translate() and scale() attribute the line is clear, as you can see here. Do you have any idea why the line is dotted and how I can fix that?

1 Answers

This is because every time you move the mouse, you are only drawing one line, either "normal" or "mirrored" but not both. You can see that your "dots" actually correspond to the dashes of the other side.

The switching happens because you apply the canvas transform once per draw call, but don't reset it, so at first mouse move, you mirror the context and at second one you'll finally draw mirrored and then switch back for the next move.

To do what you want, you could keep all your points in an Array, clear your context at the beginning of every frame and redraw the lines completely twice, once normal, and once mirrored.

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);
}
Related