Equivalent of "background-repeat: round" in SVG? - html

CSS has a handy option for background images in HTML elements: If I have a pattern that is 20 pixels high, but my HTML element has a height that isn't evenly divisible by 20 (e.g. 150px or 35px), background-repeat: round will tile the pattern to make it appear seamless, stetching/squeezing the tiles as needed.
Is there an equivalent styling option for patterns within an SVG element? For example:
<defs>
<pattern id="myPattern" width="200" height="100" patternUnits="userSpaceOnUse">
... some pattern ...
</pattern>
</defs>
<rect width="200" height="230" fill="#myPattern"/>
I'd like to have two whole repetitions of the pattern in my rectangle (stretched to 115px each), not two whole repetitions and a partial third.
EDIT
The solution by ccprog (below) works fine for this particular example. However, it requires the pattern to define how many times it will be repeated. I'm still holding out hope for a general solution for cases where the elements using the pattern are of different heights (and hence will require different numbers of pattern repetitions).

You can set a viewBox for patterns and define pattern units in terms of the object bounding box:
<defs>
<pattern id="myPattern" width="50%" height="50%"
viewBox="0 0 200 100" preserveAspectRatio="none"
patternUnits="objectBoundingBox">
... some pattern ...
</pattern>
</defs>
<rect width="200" height="230" fill="#myPattern"/>
It's not completely equivalent to CSS round, as you implicitely give the absolute number of repetitions with the width/height attributes, no matter how large the filled area is.

Related

Where can I find transform-origin's definition and how does transform-origin work?

I have a simple html with svg as below:
<svg class="svg" style="border:1px solid black" width="200" height="200">
<rect transform="translate(100, 100)" width="20" height="20" fill="red"></rect>
<text transform="translate(100, 100) rotate(90)" transform-origin="0 0">TEST</text>
</svg>
The text element is rotated 90 degree in clockwise base on text's left-bottom corner (left-upper corner of red rect)
If I change text element to <text x="50" y="50" transform="translate(50, 50) rotate(90)" transform-origin="0 0">TEST</text>, the text is rotated to (0, 100) in svg. A reasonable guess is that transform-origin does not only affect "rotate" but also "translate". But I don't understand where "0 0" is in this situation, but it is not left-bottom corner of text element anymore.
I also don't understand how it works when I set "transform-origin" in percentage (e.g. 50% 50%) or text (e.g. left bottom). It doesn't work the way I thought it would. I have not been able to find a detailed tutorial on the definition of "transform-origin". Can someone with experience in this field give me some pointers? Thanks!
It is always easier in SVG contexts to read transformations as transformations of the coordinate system. Each of the steps builds on its predecessor. Your element
<text x="50" y="50" transform="translate(50, 50) rotate(90)" transform-origin="0 0">TEST</text>
can be understood as the following sequence:
translate(50, 50): Move the origin of the coordinate system to (50, 50) of the initial coordinate system
rotate(90) and transform-origin="0 0": Rotate the coordinate system found in the previous step by 90° clockwise around its own origin.
text x="50" y="50": Draw text at point (50, 50) of the coordinate system found in the previous step.
In relation to the initial coordinate system, the last one has its origin at (50, 50), the x-axis points left and the y-axis down. The blue lines show its position and orientation. Therefore, the point (50, 50) in that system is the same as (0, 100) in the initial coordinate system:
<svg class="svg" style="border:1px solid black" width="200" height="200">
<rect transform="translate(100, 100)" width="20" height="20" fill="red"></rect>
<text x="50" y="50" transform="translate(50, 50) rotate(90)" transform-origin="0 0">TEST</text>
<!-- draw the moved coordinate system -->
<path transform="translate(50, 50) rotate(90)" transform-origin="0 0"
d="M-5,0H100M0,-5V100" fill="none" stroke="blue" />
</svg>
So why does transform-origin="0 0" refer to the coordinate system? The CSS Transforms specification says:
The value for the horizontal and vertical offset represent an offset from the top left corner of the reference box.
The reference box is defined by property transform-box. If not explicitely set, its initial value is view-box:
Uses the nearest SVG viewport as reference box.
In your case, this is the box that defines the <svg> element and outlined by the black border, but with the defined sequence of transforms applied. (If there was a viewBox attribute present, it would represent a further implicit transform, to be applied first.)

svg fill-rule applied to two or more polygons

I am trying to apply the svg evenodd fill-rule in two or more polygons that one is inside/intersects the other.
In the example i would like the small polygon cube to be white.
<svg height="500" width="500" style="fill:lime;stroke:purple;stroke-width:5;fill-rule:evenodd;" >
<polygon points="100,100,300,100,300,300,100,300"/>
<polygon points="150,150,200,150,200,200,150,200" />
</svg>
How can I achieve this using the fill-rule attribute?
Should I use another shape?
Please keep in mind that in order to construct any shape I will have to use the points attribute to provide coordinates of shapes.

Trying to apply a relative transform matrix to a fabricjs PathGroup

Using FabricJS, I have a vector that like this:
https://jsfiddle.net/sb63df47/
As you can see, the viewBox is set 0 0 100 100, even though if the vector were trimmed of whitespace, the viewBox would be set to 0 0 30 30. So to make the bounding box appear closer to the icon, I set the width / height to 30 and 30. However when I do that, the sub-paths in the PathGroup object are off (by 35 on the top and 35 on the left).
To deal with this, I applied a transformation matrix to "move" the paths back up to where they need to be. But doing this introduces a whole bunch of other problems. Specifically, when I rotate the vector, the transformation is off (see here: https://i.imgur.com/RxoMBdj.png)
Is there a more elegant way of narrowing the viewBox of a PathGroup if I know the exact width / height that I want it to be set to?
Every SVG is a particular situation,
In any case if you want to modify the objects you have to pay attention to transform Attribute.
Here there is a translate transform that is moving the object of 35x and 35y.
Remove the transform attribute from the group containing paths and the cross will be positioned in the top left corner of the bounding box.
Then if you want to make the bounding box shrink, change the viewbox to 0 0 30 30
An equivalent transformation is to set up the viewbox to 35 35 30 30 that will apply both a movement in the corner and a shrink.
There are so many ways to obtain the same effect.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" viewBox="0 0 30 30" version="1.1" x="0px" y="0px"><title>add</title><desc>Created with Sketch.</desc><g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage"><g sketch:type="MSArtboardGroup" fill="#000000"><g sketch:type="MSLayerGroup" ><path d="M0,14 L30,14 L30,16 L0,16 L0,14 Z" sketch:type="MSShapeGroup"></path><path d="M14,0 L16,0 L16,29.94 L14,29.94 L14,0 Z" sketch:type="MSShapeGroup"></path></g></g></g></svg>

SVG + Chrome + filter + negative scale

I've found Google Chrome is not displaying SVG elements which have both a negative scale and a filter (e.g. Gaussian blur). Is this a bug?
Minimum non-working example:
<filter id="blur-norm">
<feGaussianBlur stdDeviation="1 3" />
</filter>
<g id="norms" transform="scale(-0.5)">
<rect x="-40" y="-50" width="100" height="100" fill="#50aea9" stroke="#355270" stroke-width="5" />
</g>
Comparing this JSFiddle in
Firefox 32 / Win7: element is visible and blurred
Chrome 37 / Win7: element is not visible
In chrome, setting the scale to be a positive number will make the element appear (although incorrectly scaled); alternatively, removing the filter reference will make the element appear (although not blurred).
Am I doing something wrong, or is this a Blink bug?
Looks like it was reported a few days ago.
https://code.google.com/p/chromium/issues/detail?id=409602
I couldn't get Chrome to display any filters until I removed the out of the head section then presto, got all filters displayed.

Embed SVG into HTML

I need to embed a SVG file into HTML file, the SVG's dimensions are bit larger. so, I need the SVG to be re-sized to the screen resolution. Is there any way to do that? Thanks.
If you want an SVG file to fit in a container the first thing to do is to set a viewBox attribute and remove width and height attributes from the root <svg> element:
<svg viewBox="0 0 100 200" ... >
The values of a viewBox are: x y width height. Read more in the SVG specification.
I dont know how complex is that SVG, but at least you can put whole description under one group , and then use transform="scale(SF)" whereas "SF" stands for scaling factor. Default is 1 (100%), so use little script:
TransFrm = "scale(" + SF + ")";
yourElement.setAttributeNS(null, "transform", TransFrm);
Or if you mean resizing by viewBox then <rect x="0" y="0" width="100%" height="100%"/>.
Or if you mean something else take a look at: http://janistoolbox.typepad.com/blog/2009/12/svgauto-resize-svg-on-an-html-page.html
Good luck.