151

I would like to be able to set the stroke-width on an SVG element to be "pixel-aware", that is always be 1px wide regardless of the current scaling transformations applied. I am aware that this may well be impossible, since the whole point of SVG is to be pixel independent.

Context follows:

I have an SVG element with its viewBox and preserveAspectRatio attributes set. It looks something like this

<svg version="1.1" baseProfile="full"
    viewBox="-100 -100 200 200" preserveAspectRatio="xMidYMid meet"
    xmlns="http://www.w3.org/2000/svg" >
</svg>

This means that when I scale that element, the actual shapes inside it scale accordingly (so far so good).

As you can see, I have set up the viewBox so that the origin is in the center. I would like to draw an x- and a y-axis within that element, which I do thus:

<line x1="-1000" x2="1000" y1="0" y2="0" />

Again, this works fine. Ideally, though, this axis would always be only 1px wide. I have no interest in the axes getting fatter when i scale the parent svg element.

So am I screwed?

0

2 Answers 2

192

You can use the vector-effect property set to non-scaling-stroke, see the docs. Another way is to use transform(ref).

That will work in browsers that support those parts from SVG Tiny 1.2, for example Opera 10. The fallback includes writing a small script to do the same, basically inverting the CTM and applying it on the elements that shouldn't scale.

If you want sharper lines you can also disable antialiasing (shape-rendering=optimizeSpeed or shape-rendering=crispEdges) and/or play with the positioning.

Sign up to request clarification or add additional context in comments.

9 Comments

Unfortunately this is in a XUL app, and that doesn't seem to support vector-effect yet. Oh well.
This should appear in Firefox 15 all being well so you should be able to use it once you build your XUL app on gecko 15.
IE11 still doesn't support vector-effect property. Is it possible to achieve the same effect as vector-effect: non-scaling-stroke in IE11?
@merlin yes, with js it's possible to emulate this in IE.
@merlin clone the element (setting fill to none and vice versa for the stroke), compute & set the appropriate transforms (one for the fill part and one for the stroke part). It's going to be a little messy for sure, but there it is - you might also want to ask Microsoft to add support for it. In any case I think your question deserves to be a question of its own.
|
11

Here is a more concise answer based on Erik's answer to help you get started quickly.

<div style="background: blue; width: 100%; height: 130px;">
            <svg xml:id="root" viewBox="0 0 100 100" width="100%" height="100%" preserveAspectRatio="none">
                <rect xml:id="r" vector-effect="non-scaling-stroke" x="0" y="0" width="100" height="100" fill="none" stroke="#88CE02"
                      stroke-linecap="square" stroke-width="10" stroke-miterlimit="30"/>
            </svg>
        </div>

Adding the vector-effect="non-scaling-stroke" to the SVG rect makes the border size (or stroke size) fixed.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.