SVG scale absolute size - svg

I am trying to display multiple SVG items in the same size, but each SVG item seems to have completely arbitrary size. Setting width/height to the top element did not work. Only transform=scale() worked, but since the argument of scale is ratio, that means that I have to specify different ratio to each item to make them the same size. So, instead of scaling them by ratio, is there any way to scale them to absolute size? Something like "scale to width 100px and height 100px", instead of "scale to 10% width and 10% height".
Mr Michael Mullany, I had tried that before posting this, but it did not work. Did I miss something?
NZ flag was very big and setting size made only the top/left show up:
Swiss flag was very small and setting the size did not enlarge it:

Not an expert on SVG, but:
No, I don't think that's how SVG works, because that kind of scaling operation would require to first draw the thing in some "native" size, then see how much that differs from the desired size, then calculate a correction factor for all coordinates (which is effectively scaling to some percentage of the original size), and redrawing it. And SVG supports effects which are scale-invariant but affect an object's bounding box, so this is mathematically impossible, as far as I can tell!

I might not be understanding the question - but is there a reason why you wouldn't use SVG's built-in image element, specifying width and height? (And no preservation of the aspect ratio - which is what I think you want?)
<svg width="1000px" height="1000px" viewBox="0 0 1000 1000">
<image x="0" y="0" width="100" height-"100" xlink:href="http://yourdomain.com/yourimage.svg" preserveAspectRatio="none"/>
</svg>

Related

SVG: how to use 100% width/height but with fixed scale

I have an SVG that needs to be opened in a container of variable size but initially scaled down to exactly 4 times screen DPI (so that 1 pixel corresponds to 4 units of the SVG user space).
Here's the example SVG. When it is opened, it must occupy the whole viewport, without scrollbars, but with a fixed scale of 1/4 (in relation to screen DPI).
The only way I can specify SVG scaling is by specifying viewBox.
The only way I can use the whole container is by specifying width="100%" height="100%".
But when both of these are specified, the SVG is automatically scaled based on container size.
Is there no solution to this simple requirement, without resorting to JavaScript?

Multiple aspect ratios in a single SVG

I'm looking for a way to create an responsive image using SVG, where some sections maintain their aspect ratio when re-sized and others are distorted. This pencil, for example, could be resized so the two ends stay the same shape and only the body is stretched, like the image below:
I can do this in HTML5 using CSS3's border-image-slice, e.g.
border-image-source: url("cropped-pencil_clipart.svg");
border-image-slice: 25% 50% 25% 25% fill;
See this codepen for an example. However I can't think of a way to achieve it in a 100% external SVG file that I can use as an image or object. In effect, I want the outer and middle elements to have preserveAspectRatio="none" and the left and right elements to have ="... slice". I know this isn't possible in "conventional" SVG 1.1 and I don't want to use JavaScript or ForeignObject because these would limit the ways I can use the external file.
Are there any clever workarounds that could selectively preserve the aspect ratio for individual parts of an image? I can re-create the source elements as pure paths if that's necessary. I've tried using patterns and even custom markers but without success so far. Any suggestions would be welcome.

Number of dashes per circle the same - SVG

Let me start out by saying my end goal is something that resembles the image below. It has 36 circles in each of the rings, spaced such that each dot is mid way between two dots in the circle inside of it
I figured out I could use a stroke-dasharray with really small lengths (.001 in my case) and stroke-linecap="round" to make the borders circular dots. The way I have it set up now each circle has a radius 5 bigger than the last and an incremented percentage for the stroke-dasharray. Here is my jsFiddle. Currently My inner most ring only has 21 dots and my outermost ring has 29 dots
How can I get the same number of dots per circle? Is there a mathematical way to do this or an attribute that I am unaware of? What can be done to evenly space out the circles using the whole circumference equally (instead of having some on the right side of the what I perceive as the x-axis)?
It seems to me that I would have to simply guess and check with the values in order to get it the way I want but I would love to be proven wrong. The stroke-dasharray documentation on Mozilla and W3C aren't very useful
Since you're using stroke-dasharray on a circle, you need to use π (3.14159265) to get even spacing.
Given the formula spacing = (radius × 2) × 3.14159265 ÷ numberOfCircles, your SVG circle would be <circle r="{radius}" stroke-dasharray="0.001, {spacing}"/>.
To achieve the spiral effect, apply a rotation of 360 ÷ numberOfCircles ÷ 2 to every other ring. I used CSS to accomplish this, circle:nth-child(even) being the selector and -webkit-transform: rotate( {rotation} ); being the style applied.
I forked your JSFiddle1.
1 Note that the spiral is visible in webkit browsers only. Also, the rings are slightly misaligned on the right for, to my knowledge, unknown reasons.

Smoothing overlapping stroke edges

I'm using Raphael to draw the arcs as shown in the image below:
Z-index order is from lowest to highest: gray, blue, green.
Both the gray and the blue arcs start from the top, where the green one starts.
Is there any way to improve the edges? Especially the green over blue one.
Thank you.
I'm afraid there's not much you can do. How the shape is rendered depends on the viewer (browser, image viewer or importing application). You could play with the rendering properties and see if this gives you an improvement, but I believe hardly any SVG implementation supports them.
I am not sure exactly what you mean, and it is hard to know how you made the image without the raphael code. Are you talking about the way the outer edge of the green arc extends slightly beyond the outer edge of the blue arc? I would check that the corner points of the two paths are the same, and include the stroke-width in your calculations of the paths.
Perhaps you could try reducing the stroke-width to 0 to make things easier.
The problem is that you are overlapping the shapes. This causes some colors to spill out from underneath. To solve this you need to start each arc where the previous one ends.
You might get very faint gaps, this can easily solved by applying a 1px stroke to each arc.

Using an SVG feDisplacementMap filter, how do I anti-alias?

When using an feDisplacementMap svg filter, my smooth svg lines are getting all jagged. I could probably render it large and then shrink it down, but isn't SVG supposed to be able to anti-alias?
Okay, so I figured out the answer to my own question: the filterRes attribute: http://www.w3.org/TR/SVG/filters.html#FilterElementFilterResAttribute
In my testing, on Chrome, increasing the filterRes slows things down pretty dramatically.
SVG filters process inputs at the pixel level, not the vector level. As far as an SVG filter is concerned, it's been handed a big rectangle of RGBA pixels to work with. Results from a displacement map can look pixelated because a filter has no idea where the edges that have been displaced are - it's all just pixels as far as it is concerned. (The old semi-transparent pixels that used to be the anti-aliasing have been displaced as well.) However, sometimes you can add another filter or two to solve any problem that this creates. Creative ways to solve this problem:
Take the post-displacement graphic, blur it with a radius of a few pixels then blend the blur back into the original graphic.
Take the post-displacement graphic, do a luminance to alpha conversion, then use that alpha map with a diffuse lighting effect to add a fake anti-alias lighting effect.
Use a convolvematrix with edge detection values to extract edges from the graphic, blur that result and blend it back into the source graphic.
Depending on your graphic, you might be able to use an erode or dilate filter, but that tends to produce boxy highlights and might not work. And of course, you can always tweak your input in SVG (using stroke effects) to "pre-antialias" your source graphic so the result doesn't look so odd.

Resources