Examples of polygons drawn by path vs polygon in SVG - svg

I would like to learn SVG, and am trying to learn how the same image can be rendered by using either the point (with polygon) or by dynamically by paths (path).
I would like a few examples of the SAME polygon (triangle, square, and pentagon are enough to begin) in BOTH SVG polygon AND SVG path, so that I can compare the code. I can find individual images drawn by either, but none that are the SAME.

It's trivial: You can basically take the points attribute of a polygon and turn it into a path's d attribute by prepending M and appending z.
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
<polygon points="20,20 100,20 100,100 30,110"/>
<path d="M20,20 100,20 100,100 30,110z" fill="green" transform="translate(100,0)"/>
</svg>

Both can create shapes.
Polygon will automatically close the shape for
you (by returning to the first point) after drawing at least three
sides, and is composed of a series of connected straight lines, which
means it does not scale well.
Paths can use straight OR curved lines, and do not auto-close the
shape for you. Path is probably the most powerful basic shape element
in SVG.
Source

Related

Shift all objects in an SVG down and to the right by a given number of pixels

Is there some kind of a wrapper object in SVG that I can use to shift all objects (lines, polygons, circles, text etc) down and to the right in a simple easy fashion? I realize now that I have not left enough space in the top left corner of my SVG definition.
Maybe there is a margin or padding element in SVG that I can use. Please note that I do not desire to wrap this inside HTML or use CSS trickery to achieve this, but ideally I would like to do this with pure SVG if possible.
You can either alter the viewBox attribute to reveal different portion of the infinite plane, i.e. changing e.g.
<svg viewBox="0 0 100 100">
to
<svg viewBox="-10 -10 110 110">
will bring extra 10 point rows and columns to top an left, effectively shifting content to bottom right (and shrinking it).
Or you can wrap all root elements of your SVG into <g> element and apply (add) single transform to all its children through it:
<g transform="translate(10, 10)">
<!-- content -->
</g>

SVG to PDF rendering goes wrong - are there errors in my header?

I have a couple of SVG images that I want to paste together to make a big graphic.
First, let me present you with my problem:
This is one of the symbols, placed in a grid. The grid is, for convenience, with unit-less 100 distance from line to line.
If I render it to pdf, it looks like this instead:
Those symbols have a completely wrong size for the grid (They are much larger, mostly) and they are badly positioned if I use them raw.
So my treatment is, I scale them and position them correctly in relation to the grid, then I make a rectangle around them that encompasses them completely and makes the symbol-handling easier.
That rectangle is perfectly fitting to my grid. In my case, for this symbol, it is a rectangle encompassing the six squares around the symbol. I did this, because the symbol can be rotated by the user and the rotation is done from symbol point of view; any transform after the rotation is from the rotated point of view. So I made an attempt to de-couple the transformations by wrapping them.
Finally, I move the rectangle to a user-defined place and rotate it as the user wants to have it. So far, so well, it was extensively tested in google chrome and works reliably. In Google Chrome.
Now I wanted to translate it to pdf for printing. And after conversion, the symbol is placed in the wrong position.
I am guessing (as I made several tests) that the error is somewhere in my header.
Could someone of you please check the headers that I add and tell me if and where I did something wrong? For example there is a view box starting at -100, otherwise the symbol would be cut and wrongly placed. Is there another way to "rectangularize" any arbitrary symbol? Or is it generally the wrong way to do these kinds of things?
Here are the changes that I added around the svg symbol code. Innermost changes are applied first.
<!-- move the rectangle to the right place and rotate it as the user wishes-->
<g transform="translate(300.0, 400.0) rotate(0,150.0, 50.0) ">
<!-- a rectangle around the symbol, perfectly fitting to the grid-->
<svg x="0" y="0" width="300.0" height="200.0" version = '2.0'
xmlns="http://www.w3.org/2000/svg" viewBox="-100.0 0 300.0 200.0">
<!-- scaled to correct size, placed inside the grid as it should be -->
<g transform = "translate(-10.000, 73.614) scale(0.229,0.229)" >
<!-- original symbol, wrong size -->
<svg width="523" height="230" version = '2.0' xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 523 230">
.... lots of svg paths here ...
</svg>
</g>
</svg>
</g>

Why are the SVG Text elements too high?

I noticed the the root coordinates for a text element are not at the top left corner like a rect element:
Is there a way to set it such that when a text element is at (0,0), it fits inside the parent element?
If I understood you well, you can use this:
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/dominant-baseline
A) Chromium browsers
svg {
dominant-baseline: hanging;
}
https://jsfiddle.net/e7vc4bqj/
B) Chromium and Firefox
.text {
dominant-baseline: hanging;
}
https://jsfiddle.net/3zskd148/
SVG text coordinates are used to define its left bottom corner by default:
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor
Hope this help :)
Why are the SVG Text elements too high?
The x and y coordinates of a <text> element specify the start of the baseline of the text. This makes complete sense. You wouldn't want it to be the top left of the first character - because it would then be a difficult job to get text of different sizes and styles to line up.
There is no global option in SVG that changes that behaviour. However see below for alternatives)
Is there a way to set it such that when a text element is at (0,0), it fits inside the parent element?
Normally you would just adjust the y coordinate based on the font size.
However there are a couple of alternatives you can use:
One is the xxx-baseline properties (as #gengns has pointed out), that can alter how the character glyphs are positioned relative to the baseline. Note however, that those attributes are not entirely reliable, due to mixed browser support. Plus they depend on the font containing the correct data tables. Not all fonts have those tables.
A better option IMO is to use the dy attribute. This adds a relative offset to the text position. Meaning the text is actually positioned at (x, y + dy). And it is supported by all browsers.
<svg width="200" height="150">
<rect x="0" y="0" width="200" height="150" fill="skyblue"/>
<text x="0" y="0"
font-size="25px" dy="1em">asd</text>
</svg>

how does fill-rule="evenodd" work on a star SVG

I saw the following svg shape when i was trying to understand fill-rule in SVG
<div class="contain-demo">
<svg width="250px" height="250px" viewBox="0 0 250 250">
<desc>Yellow star with intersecting paths to demonstrate evenodd value.</desc>
<polygon fill="#F9F38C" fill-rule="evenodd" stroke="#E5D50C" stroke-width="5" stroke-linejoin="round" points="47.773,241.534 123.868,8.466 200.427,241.534 7.784,98.208 242.216,98.208 " />
</svg>
</div>
Please note the following:
The SVG has just one path.
The SVG has intersecting points.
if i change fill-rule="nonzero" the entire SVG get the fill.
Currently with fill-rule="evenodd" applied the SVG's central area does't get the fill.
Why is it that with fill-rule="evenodd" the central portion of the star SVG is not filled ?
I did read the spec for fill-rule="evenodd"
This value determines the "insideness" of a point in the shape 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.
But i still don't understand why when i apply fill-rule="evenodd", the middle of the star is not filled. Can somebody please explain this ?
This is how the mechanism works. Pick a point in the center, draw lines to infinity in any direction - they always cross an even number of path segments -which means that they are "outside" and their areas don't get filled.
Pick a point in the filled triangles - if you draw lines to infinity in any direction - they always cross an odd number of path segments and thus, they are "inside" and their area should be filled.

stroke-width doesn't scale; aspect ratio problem?

I have one or more path elements inside a g element that I am scaling to fit inside a grid rectangle. The transform is applied to the g element. My transform works in that all the points end up at the right places, but I discovered that I have to adjust the stroke-width of the path to get a readable line.
The problem is that if the scale involves a large shift in the aspect ratio, I end up with some segments of the path being heavier weight than others, depending on their orientation.
Here is a typical transform that my code computed:
scale(0.1875, -0.010397820616798718) translate(-1149000, -96174)
In this case I end up changing the stroke-width from 9px to about 48px. Segments close to the horizontal end up thin, those close to the vertical are thick.
Is there any easy way to end with all the segments with the same rendered width?
Have you looked at setting the vector-effect attribute to non-scaling-stroke?
<line vector-effect="non-scaling-stroke" stroke="black" stroke-width="5"
x1="32" y1="50" x2="32" y2="350"/>
http://www.w3.org/TR/SVGTiny12/painting.html#NonScalingStroke
UPDATE
The best solution I can think of is to manually transform the coordinates of your path.
vector-effect="non-scaling-vector" is not consistently supported. My versions of Firefox and Safari do not support it, but my Chrome browser does.
In the SVG standard there is no way of specifying a transformation for the stroke independantly. (A stroke-transform attribute would be nice - like the windows GDI+ drawing system, where a Pen object has it's own local transformation).
Until this changes, the best solution I can think of is to manually work out the coordinates of your path - that is the svg has no transform elements; the coordinates are already transformed.

Resources