svg fill-rule applied to two or more polygons - html

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.

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.)

Reverse effect of evenodd in Svg

I started learning SVG. Using polygons I have created a Star. While further reading I found a fill-rule property which can take two attributes first one is nonzero which will fill colour in whole the shape and another one is evenodd which will fill colour in odd points and even points will remain unfilled. When I used evenodd it filled the outer part of the star and left the centre blank.
How can I fill the centre or even points only of the star?
<!DOCTYPE html>
<html>
<body>
<svg height="210" width="500">
<polygon points="100,10 40,198 190,78 10,78 160,198" style="fill:lime;stroke:purple;stroke-width:5;fill-rule:evenodd;"/>
Sorry, your browser does not support inline SVG.
</svg>
</body>
</html>
This will generate a star ditto to the 1st imageSide-Filled star
and I want only center to be filled check 2ndimage.Cneter fill star only
evenodd which will fill colour in odd points and even points will remain unfilled.
That sounds to me like you are misunderstanding what even-odd fill is. The description from the SVG specification describes it this way:
This rule determines the "insideness" of a point on the canvas by drawing a ray from that point to infinity in any direction and counting the number of path segments from the given shape that the ray crosses. If this number is odd, the point is inside; if even, the point is outside.
So in the case of your star, an imaginary line from a point in the centre of the star to the outside of the star always crosses two lines. So the inside is not considered part of the fill.
How can I fill the centre or even points only of the star?
I don't know what you mean by this. What are the "even points" of the star?
Do you mean that you want to choose which of the six parts (center + 5 points) of the star get filled? If so, then fill-rule won't help you. You will need to create and fill those shapes yourself.
For example:
<svg height="210" width="500">
<!-- centre -->
<polygon points="78,78 122,78, 136,121 100,150 64,121" style="fill:lime;"/>
<polygon points="100,10 40,198 190,78 10,78 160,198" style="fill:none;stroke:purple;stroke-width:5;"/>
</svg>

How to fix gap between svg elements

The Problem
I noticed a strange gap between a rect and a path that, according to the coordinates, should look like this:
but instead looks like this:
It occurs in Firefox, Edge and IE, in Chrome only in certain zoom levels or when adding Stoke.
I tried to:
remove all white spaces (looks like the very same problem)
add attribute shape-rendering="crispEdges"
move the elements closer together so that they would overlap (jsfiddle)
Improved the problem, but didn't fix it and introduced new ones (like stroke not matching).
Result in Chrome(v64.0.3282.140):
Result in Firefox(v58.0.1):
Thanks for your consideration
Example
<svg>
<g transform="matrix(1,0,0,1,60,10)">
<rect width="60" height="10" x="-30" y="0" rx="5" ry="5"></rect>
<path d="M15,10 C0,10 15,25 0,25 C-15,25 0,10 -15,10" ></path>
</g>
</svg>
<style>
g{
stroke: red;
fill: black;
}
</style>
The rects outline seems to be rendered in color different from black.
Couldn't reproduce the behaviour on Chrome 63 (63.0.3239.132) without the style element, not even scanning through the zoom levels.
However, one possible fix is to close the path with the closepath specifier ( Z or z in the path spec; see here for the pertinent portion of the svg specs):
<path d="M15,10 C0,10 15,25 0,25 C-15,25 0,10 -15,10"></path>
In case this modification does not suffice, complement the path to paint over the rectangle's outline along the x interval covered by the path-defined shape:
<path d="M15,10 C0,10 15,25 0,25 C-15,25 0,10 -15,10 l0,-1 L15,9 Z"></path>

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

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.

Why do the following SVG paths produce dramatically different results in webkit?

I'm generating pie charts in SVG (using the ruby library svg-graph, but that isn't totally relevant), but there is a strange edge case where the chart is totally blank. This occurs in Chrome and Safari, but not in IE11 or Firefox.
I've narrowed it down to a certain path element whose d attribute varies slightly between the two. One produces a yellow circle while the other does not. My SVG knowledge is limited, so I don't understand why the second snippet isn't outputting anything. Any ideas?
Working:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g>
<path d="M109.0,109.0 L109.0,0.0 A109.0,109.0 0, 1,1, 108.99999000000007 0.0 Z"
transform="translate( -3.216245299353273e-15 10.0 )"
style="fill: #FFDC00" />
</g>
</svg>
Not working:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g>
<path d="M108.5,108.5 L108.5,0.0 A108.5,108.5 0, 1,1, 108.49999000000007 0.0 Z"
transform="translate( -3.216245299353273e-15 10.0 )"
style="fill: #FFDC00" />
</g>
</svg>
This may be a rounding issue. The path is trying to draw a circle using the arc path instruction "A". The beginning and ending points of the arc are very close together (< 0.0000001 units). If the SVG renderer thinks the two points are actually the same then it will draw an empty arc (0% of a circle) instead of a nearly complete (99.9999% of a circle).
You can try separating the beginning and ending points slightly further away (e.g., try 359 degrees instead of 360); as the Z instruction will close the path anyway and hide the tiny wedge left over. Also to see more of what's going on try stroking the path instead of filling it.
Or draw a circle using two half-circle arcs. See Circle drawing with SVG's arc path