23rfew
23rfew

Reputation: 31

How come the canvas drawing is blurry, and how do I sharpen it?

The code is as follows:

const vs = document.getElementById("vs");
const vs_ctx = vs.getContext("2d");

vs_ctx.strokeStyle = "purple";
vs_ctx.lineWidth = 3;
vs_ctx.strokeRect(50, 50, 20, 20);
#vs {
    background-color: rgb(17, 17, 17);
}
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>template</title>
        <link rel="stylesheet" href="css.css" />
    </head>
    <body>
        <canvas id="vs"></canvas>
        <script type="module" src="main.js"></script>
    </body>
</html>

I'm using no css to scale or set the canvas, as I read that will make stuff blurry. However, my simple square still is. How do I sharpen this?

Upvotes: 1

Views: 1192

Answers (2)

obscure
obscure

Reputation: 12891

To make everything look a bit cleaner, lines drawn onto the canvas get antialiased.

If you magnify your purple rectangle you can see the effect:

Unfortunately there is no switch built-in to turn-off this behaviour. Though the CanvasRenderingContext2D has a property called imageSmoothingEnabled, it does not work in this case as it just affects stuff drawn using drawImage(). Also the CSS property image-rendering won't fix the problem.

Luckily there is a little trick you can use. By offseting your path by a half-pixel you can get no anti-aliasing.

Here's an example:

const vs = document.getElementById("vs");
const vs_ctx = vs.getContext("2d");

vs_ctx.strokeStyle = "purple";
vs_ctx.lineWidth = 3;
vs_ctx.strokeRect(50.5, 50.5, 20, 20);
vs_ctx.strokeRect(100, 50, 20, 20);
#vs {
  background-color: rgb(17, 17, 17);
}
<body><canvas id="vs"></canvas>

Upvotes: 1

Konrad
Konrad

Reputation: 24661

Use image-rendering: pixelated; css property to turn off antialiasing

document.querySelectorAll('canvas').forEach(canvas => {
  const ctx = canvas.getContext('2d')
  ctx.fillStyle = 'magenta'
  for (let i = 0; i < canvas.width; i += 1) {
    ctx.fillRect(i, i, 1, 1)
  }
})
canvas {
  width: 100px;
  height: 100px;
  border: 1px solid black;
}

.pixelated {
  image-rendering: pixelated;
}
<canvas width="10" height="10"></canvas>
<canvas class="pixelated" width="10" height="10"></canvas>

There is also this answer, but I'm pretty sure it doesn't work

Upvotes: 3

Related Questions