title: Drawing crisp 1px lines on HTML5 canvas when using transformations
body: <p>I'm drawing a lot of 1px lines on an HTML5 canvas element in my code. The drawing code looks roughly like the following, the <code>transform</code> variable in this case is set using <a href="https://github.com/d3/d3-zoom" rel="nofollow noreferrer">d3-zoom</a>. <code>instructions.f32</code> is a Float32Array that contains the coordinates I use for drawing the lines. </p>
  
  <pre><code> context.setTransform(
      transform.k,
      0,
      0,
      transform.k,
      transform.x,
      transform.y
    );
    context.lineWidth = 1 / transform.k;
    context.beginPath();
    for (let i = from; i &lt; to; ++i) {
  
      let v1 = instructions.f32[i * 4 + 1];
      let v2 = instructions.f32[i * 4 + 2];
  
      // execute some moveTo/lineTo commands using v1 and v2 as coordinates
    }
    context.stroke();
  </code></pre>
  
  <p>One issue with this code is that the 1px lines are blurry because I'm drawing across pixel boundaries. I tried to adapt the code to snap the lines to the nearest pixels like the following:</p>
  
  <pre><code>let v1 = (Math.round(instructions.f32[i * 4 + 1] * transform.k) + 0.5) / transform.k;
  let v2 = (Math.round(instructions.f32[i * 4 + 2] * transform.k) + 0.5) / transform.k;
  </code></pre>
  
  <p>But that still results in blurry lines like the following image (screenshot of a zoomed in image):</p>
  
  <p><a href="https://i.stack.imgur.com/ue85B.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/ue85B.png" alt="enter image description here"></a></p>
  
  <p>If I didn't have any transformation set, as far as I understand I would simply have to round the coordinates to the nearest pixel and add 0.5 to get crisp lines. But I'm not sure how to achieve this when my entire canvas is transformed, and I'm not drawing into the final coordinate system. As my attempts to correct for this have failed so far, it looks like I'm missing something here, or making some other mistake on the way.</p>
  
  <p>How can I draw crisp 1px lines in canvas when transforming my entire canvas with setTransform? How exactly do I have to round the coordinates to snap the resulting lines to pixels?</p>