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

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.

Related

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>

Adding event to svg elements in Phaser3

I have one SVG image file, having some paths. Something like:
<svg>
<g>
<path id="land" class="land" d="M108.114,402.043l0.683,1.604l-1.204.(truncated)">
<path id="ice" class="ice" d="M288.114,402.541l0.683,1.604l-1.204...........">
<path id="water" class="water" d="M038.114,402.543l0.683,1.604l-1.204........">
</g>
</svg>
I need to know which path was clicked. When I load SVG image file in Phaser using load.svg(), the event is triggered for the entire image and not just for the area (or path).
So, how can I detect which path was clicked? Any help is appreciated.
Might be using the wrong terms, but the SVG loader paints the projected SVG to a static bitmap texture. This eliminates the existence of these pathed objects. Even if you split these paths into their own SVG and layer them, the hitboxes for textures is going to be rectangular, based on the size of the texture.
If you separate these paths into their own SVGs, a more computationally expensive hitbox exists, with pixel-perfect enabled for the hitbox setup Docs Phaser3 #makePixelPerfect. This will look at the projected texture and apply a hitboxArea over the pixels that each SVG renders.
A less expensive hitbox for each SVG would be to implement a custom hit test function when the input manager tests for pointer-events. Docs Phaser3 HitAreaCallback. This is going to be more difficult, and its difficulty depends on the shape of the hitbox you are going for, and how accurate you need this hitbox to be. Basic geometries and contains methods for hit tests can be found in Phaser.Geom namespace, if those don't match your use case you would need to write/find a function yourself.

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>

Examples of polygons drawn by path vs polygon in 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

Transition of SVG circle position results in truncation while moving

I have a number of <circle> elements each inside their own <g>. To move the circles around I'm applying a "translate" transform on each <g>.
What I notice is that as the circles are moving, some of them seem to get slightly truncated. As soon as they come to rest they look just fine so it is just while they are in motion. The truncation effect looks something like what you'd see if you had a square viewport the same size as the circle and then moved the circle slightly out of centre. It just flattens slightly on one side.
This is what one of my element groups looks like:
<g class="datapoint dot" transform="translate(360,56)">
<circle class="rendering" style="fill: #3182bd; stroke: #225b84; stroke-opacity: 1; fill-opacity: 1; " r="7"></circle>
</g>
When I run the transition watching the debugger I can see the values in "translate" change but everything else stays the same. So it doesn't seem to be something I'm doing wrong, but you can never be sure of that. :)
One final comment is that I do see this in multiple browsers (tried Chrome and Firefox so far).
Has anybody encountered this kind of thing before?
Probably a bit late for you but I've noticed similar things when using transform: scale(). The SVG shape is limited to the files original size. If the shape gets enlarged bigger than this then it will be cropped.
My fix was to make the bounds of the SVG bigger than the shape itself so that it has some room to expand into.

Resources