Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Canvas element with blurred lines

I wonder why the edges/lines of my canvas element are blurred (Chrome, IE, FF) and have a so-called "sawtooth-effect" (does this expression exist in english? :-)) as you can see here: enter image description here

It is just a quick first try - maybe I did something wrong? Here is the code:

c2 = document.getElementById('test').getContext('2d');
c2.fillStyle = '#f00';
c2.beginPath();
c2.moveTo(0, 0);
c2.lineTo(100, 0);
c2.lineTo(80, 50);
c2.lineTo(0, 50);
c2.closePath();
c2.fill();

c2.fillStyle = "#000";
c2.beginPath();
c2.moveTo(0, 50);
c2.lineTo(80, 50);
c2.lineTo(60, 100);
c2.lineTo(0, 100);
c2.closePath();
c2.fill();

I also added it to this JS Fiddle

like image 876
ho.s Avatar asked Jan 11 '23 00:01

ho.s


2 Answers

A canvas object has two "sizes": one is the size on the screen and the other is the size of the bitmap supporting the canvas.

You can access the first with offsetWidth / offsetHeight or using css width and height values (i.e. element.style.width and element.style.height). The second size instead is specified on the element itself <canvas width=100 height=200> or setting element.width and element.height.

If the bitmap size is smaller than the screen size then the browser will "upscale" the bitmap using bilinear interpolation, thus creating that blurry effect.

The best crisp graphic can be obtained by setting instead the screen size equal to the bitmap size or, only on devices that use bad tricks like retina displays, by setting the bitmap size to twice the screen size (this is necessary because the screen pixel size is faked in those devices).

If instead what you describe as "blurry" is just antialiasing then I'm sorry but there's no portable way to disable antialiasing when drawing on a canvas, short of drawing the pixels yourself with javascript by accessing the pixel data array.

A canvas with a proper bitmap size is rendered in the best possible way, exactly like an svg "vector graphic" would be. The following is a zoomed view of a screenshot of two lines, one drawn on a canvas and the other from an svg and clearly there's no way to say which is which.

enter image description here

like image 108
6502 Avatar answered Jan 22 '23 19:01

6502


You can oversample the canvas (fake double resolution):

Here's an illustration with standard resolution on top and "double" resolution on bottom:

A Demo: http://jsfiddle.net/m1erickson/M5NHN/

enter image description here

Html:

<canvas id="canvas1" width=300 height=150></canvas>
<canvas id="canvas2" width=600 height=300></canvas>

CSS:

#canvas1 {
    border:1px solid red;
    width:300px;
    height:150px;
}
#canvas2 {
    border:1px solid green;
    width:300px;
    height:150px;
}

JS:

var canvas = document.getElementById("canvas1");
var context1 = canvas.getContext("2d");
var canvas = document.getElementById("canvas2");
var context2 = canvas.getContext("2d");

draw(context1);

context2.scale(2, 2);
draw(context2);

function draw(c2){

c2.fillStyle = '#f00';
c2.beginPath();
c2.moveTo(0, 0);
c2.lineTo(100, 0);
c2.lineTo(80, 50);
c2.lineTo(0, 50);
c2.closePath();
c2.fill();

c2.fillStyle = "#000";
c2.beginPath();
c2.moveTo(0, 50);
c2.lineTo(80, 50);
c2.lineTo(60, 100);
c2.lineTo(0, 100);
c2.closePath();
c2.fill();
}
like image 32
markE Avatar answered Jan 22 '23 19:01

markE