Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Canvas line behaviour when 0 < lineWidth < 1

Tags:

html

canvas

Out of curiosity I wanted to try to set the lineWidth < 1 because the 1px lines looked fat even with my resolution set correctly. Unsurprisingly it doesn't work but there is this weird behaviour on Chrome and Firefox (not tested elsewhere):

enter image description here

On the left is with lineWidth = 1, center is lineWidth = 0.5 and right is lineWidth = 0.1

They were generated with this code:

ctx.lineWidth = 0.1;

        lis.each(function(i) {

            sx = $(this).offset().left;
            sy = $(this).offset().top;

            ex = sx - (20 * (6-i));
            ey = wh - 80 - (20 * (i + 1));
            eey = ey - (20 * i);

            // Horizontal
            ctx.moveTo(sx,sy+7);
            ctx.lineTo(ex, sy+7);
            ctx.stroke();

            // Vertical
            ctx.moveTo(ex,sy+7);
            ctx.lineTo(ex, ey);
            ctx.stroke();

            // Horizontal
            ctx.moveTo(ex,ey);
            ctx.lineTo(ww - bg_img_width + 100, eey);
            ctx.stroke();
        });

They are printed in the order their children appear so it starts with Alpha each time and ends with Epsilon.

Can anyone explain why the lines get thiner as the loop progresses when 0 < lineWidth < 1? Is this intended? Can it be used for cool stuff?

like image 266
Juicy Avatar asked Jul 10 '14 06:07

Juicy


1 Answers

First thing to remind is that points in a canvas are centered on (0.5;0.5) , so ,to draw a clean 1px wide line, one has to draw at integer coordinates + (0.5, 0.5).

Then to emulate thickness, the renderer will play on opacity : a 0.5 line will be rendered less opacity to make it look 'weaker'.
Notice that this is the way the antialiasing works also : it diffuses the point on several neighbor points with a lower weight to simulate the thickness of the line.

You can play with the below fiddle were i compare several ways to draw a triangle.

I think we have same visual effect than with lineWidth=0.5 when we draw with 0.8 opacity for instance.

The two first lines are here to show the the difference in render when using integer coordinates vs when using integer + 0.5 coordinates. We see that when using integer coordinates, the lines overlap on two pixels and seems wider.
We see also that antialiasing is not that good since the diagonal always seems thicker (same on Chrome or Firefox here).

http://jsbin.com/voqubexu/1/edit?js,output

enter image description here

like image 177
GameAlchemist Avatar answered Oct 21 '22 16:10

GameAlchemist