Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drawing grid with jQuery SVG produces 2px lines instead of 1px

Tags:

svg

I know it's not the jQuery SVG library causing this issue, but when rendering horizontal or vertical SVG lines on integral x,y coordinates, lines are 2px wide instead of 1px. This is probably to do with anti-aliasing In order to get them fixed, and draw a line that's perfectly 1px wide, I need to adjust coordinates by adding 0.5px.

Is there a way to get lines 1px thick without having to tweak them like this?

like image 416
josef.van.niekerk Avatar asked Sep 28 '11 21:09

josef.van.niekerk


2 Answers

A way to solve the problem is to apply some CSS to the lines:

.thelines{
    shape-rendering:crispEdges
}

The spec chapter on shape-rendering property.

Basically it turns off antialiasing for the lines, and the lines that are NOT straight horizontal or vertical may NOT look very pretty.

But probably you'd better stick to adding .5 to the lines' coordinates, because browsers do what they are told to: the line is on exact coordinates and the stroke is painted on both sides of the line, half pixel here and half pixel there.

like image 139
Spadar Shut Avatar answered Sep 28 '22 04:09

Spadar Shut


So you want one pixel wide horizontal and vertical lines to be displayed with sharp rather than fuzzy edges.

If all the co-ordinates in your SVG are integers, maybe you can offset the whole image by 0.5, by using a transform element:

// first group has no transform 
// lines appear blurred, because they are centered on boundary of two pixels
<g id = "blurred">  
    <line x1="10" y1="10" x2="110" y2="10" stroke="black" stroke-width="1"/>
    <line x1="10" y1="10" x2="10" y2="100" stroke="black" stroke-width="1"/>
</g>

    // second group has half pixel transform - 
    // lines will appear sharp because they are translated to a pixel centre
    <g id="sharp" transform="translate(0.5,0.5)">
    <line x1="120" y1="10" x2="220" y2="10" stroke="black" stroke-width="1"/>
    <line x1="120" y1="10" x2="120" y2="100" stroke="black" stroke-width="1"/>
</g>

svg renders like this

But this will not work for horizontal/vertical lines which are not defined with integer coordinates, or where another transformation moves them off the integer coordinates.

So if this idea cannot be used to solve your problem, then you probably need a 'pixel-snapping' technique. This would analyse a line before drawing it. If the line is vertical or horizontal (after transformation) then you need to adjust the coordinates so that they will end up in a pixel center after transformation.

You may be interested in looking at the WPF Pixel Snapping explanation for background information regarding this common problem.

like image 22
GarethOwen Avatar answered Sep 28 '22 05:09

GarethOwen