HTML5, canvas, and strokeRect: lines narrower?

Go To


A stupid simple canvas usage:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

ctx.strokeStyle = "#CCCC00";
ctx.lineWidth = 3;
ctx.strokeRect(0, 0, width, height);

Yields a rectangle with narrower lines along top and left:

enter image description here

Why does this happen? Do I need to offset with padding? It's annoying.

2012-04-04 00:44
by Wells


2 things.

First, odd lineWidths (1, 3, 5, ...) will never apply cleanly with drawn on integer pixel values. This is because X and Y refer to the space between pixels rather than their centers. So a stroke of 1 that runs from [1,1] to [1,10] spills half into the pixel on the left column of pixels and half into right. If you instead draw that line from [1.5,1] to [1.5,10] then it fills half to the left, and half to the right, filling up the whole pixel column perfectly.

Any odd number width will show this behavior, but even numbers will not because they fill a full pixel on each side looking clean.

Second, the box is obscured by the top of the canvas. When you center your 3px stroke on [0,0] it spills as far up and left as [-1.5,-1.5] which is outside of the visible range of the canvas. So it appears half as thick as it should be.

See the proof of difference here:

enter image description here

The first one is like your code. The second is moved away from the top left edge to show its uniform in width. And the third shows how to render a 3px stroke without subpixel blurring.

2012-04-04 00:59
by Alex Wayne
Very interesting response-- thank you - Wells 2012-04-04 05:29


Because you told it to draw a line with the width of 3 at 0... so 1/3rd of it is going to be off your canvas... vs

2012-04-04 00:49
by Langdon
Actually it wouldn't be 1/3 of the line, but half - Alex Wayne 2012-04-04 01:27
@AlexWayne Isn't line width in pixels? How can something render only 1.5 pixels? Edit- oh god, gross, is anti-aliases the hell out of a 3px line... wt - Langdon 2012-04-04 02:30