0

How can I prevent the stroke on Canvas to stop from breaking

Zoom into the below image with (mouse scroll)

pixels break on the black rectangle drawn enter image description here

Edit : adding lineWidth/2 pixels to start coordinates fixes the problem

// grab the DOM SVG element that you want to be draggable/zoomable:
const element = document.getElementById('scene');

// and forward it it to panzoom.
panzoom(element);

const c = document.getElementById("myCanvas");
const ctx = c.getContext("2d");
ctx.strokeRect(20.5, 20.5, 150, 100);
.imageContainer {
  overflow: hidden;
  border: 3px solid red;
  height: 300px;
  margin: 0 auto
}

img {
  display: table;
  margin: 0 auto;
  height: 300px;
}

canvas {
  display: table;
  margin: 0 auto;
  height: 300px;
  width: 533px;
  border: 1px solid gold;
  z-index: 2;
  position: absolute;
  top: 0;
  left: 126px;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://unpkg.com/panzoom@8.1.0/dist/panzoom.min.js"></script>

<body>

  <div class='imageContainer '>
    <div id="scene">
      <img id='imageHD' src="https://cdn.wallpapersafari.com/57/46/dY3eN1.jpg">
      <canvas id='myCanvas'></canvas>
    </div>

  </div>

</body>
dota2pro
  • 7,220
  • 7
  • 44
  • 79
  • 3
    What do you mean by "pixels breaking"? – Bergi Jul 26 '19 at 14:40
  • 1
    Looks like the rect has an opacity – ssten Jul 26 '19 at 14:42
  • Possibly related: [CanvasRenderingContext2D.strokeRect still tries to antialias my values, instead of drawing one pixel](https://stackoverflow.com/a/51381558/691711) – zero298 Jul 26 '19 at 14:45
  • if you want to stroke a thick 1px lineWidth vertical or horizontal line, you need to set it's coords to n.5 – Kaiido Jul 26 '19 at 14:59
  • @Kaiido i don't think any of the duplicates tagged answer my question or maybe i didn't understand the other questions propoerly, what does `n.5` mean ? – dota2pro Jul 26 '19 at 14:59
  • @Kaiido wouldnt that move the rectangle? i mean on a small laptop screen it wouldnt make a difference, but my app willl run on Big store Tvs – dota2pro Jul 26 '19 at 15:02
  • That means [`strokeRect(20.5, 20.5, 150, 100);`](https://jsfiddle.net/35ta1g76/) Read the dupe targets carefully. stroke bleeds on both sides of the path. so when you stroke a 1px line at coords x1, y1 , x2, y1 you are actually drawing a rectangle x0.5 y0.5 x1.5y0.5 x1.5y1.5 x0.5y1.5 this is not possivle to draw, so you'll have less opaque pixels on all these coords – Kaiido Jul 26 '19 at 15:13
  • @Kaiido so basically I add `lineWidth/2` to start coordinates everytime ? Am I correct ? – dota2pro Jul 26 '19 at 15:42

1 Answers1

1

You could try turning anti-aliasing off for your canvas using

canvas {
    image-rendering: optimizeSpeed;
    image-rendering: pixelated;
}

The line seems more solid now.

// grab the DOM SVG element that you want to be draggable/zoomable:
const element = document.getElementById('scene');

// and forward it it to panzoom.
panzoom(element);

const c = document.getElementById("myCanvas");
const ctx = c.getContext("2d");
ctx.strokeRect(20, 20, 150, 100);
.imageContainer {
  overflow: hidden;
  border: 3px solid red;
  height: 300px;
  margin: 0 auto
}

img {
  display: table;
  margin: 0 auto;
  height: 300px;
}

canvas {
  display: table;
  margin: 0 auto;
  height: 300px;
  width: 533px;
  border: 1px solid gold;
  z-index: 2;
  position: absolute;
  top: 0;
  left: 126px;
}
canvas {
    image-rendering: optimizeSpeed;
    image-rendering: pixelated;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://unpkg.com/panzoom@8.1.0/dist/panzoom.min.js"></script>

<body>

  <div class='imageContainer '>
    <div id="scene">
      <img id='imageHD' src="https://cdn.wallpapersafari.com/57/46/dY3eN1.jpg">
      <canvas id='myCanvas'></canvas>
    </div>

  </div>

</body>
zero298
  • 25,467
  • 10
  • 75
  • 100