The blending of semitransparent lines on top of each other behaves differently depending on the used stroke width when viewed in Chrome or Firefox.
Example:
<svg xmlns="http://www.w3.org/2000/svg" width="300" height="300" version="1.1">
<path d="M 0 0 L 200 200 L 0 200 L 200 200 L 0 200 L 200 0" fill="none" stroke="#000000" stroke-width="0.80" stroke-opacity="0.75" shape-rendering="geometricPrecision"
</svg>
The line at the bottom is drawn three times on top of each other, therefore it should appear darker when blended. With a stroke width of <= 0.8, it behaves as expected. A width > 0.8 changes all lines to be uniform in color. Note that the behavior is also dependent on the zoom level used in the browser.
stroke-width="0.8"
stroke-width="0.81"
stroke-width="5"
The problem I'm facing is that I have a lot of overlapping semitransparent lines in my application and the resulting image should implicitly highlight which paths have been used more often than others (Example in codepen):
correct with stroke-width="0.8"
wrong with stroke-width="0.81"
Is there any approach for correct blending? shape-rendering does have an influence, but doesn't solve the problem.
Related
Is it possible to rotate an svg path without clipping it? I'm aware that I can increase the size of the container, but I don't want to do this. I tried to rotate the svg container at the same angle as the path, but it doesn't work.
This is my basic svg setup:
<svg width = {600} height = {600} viewBox = "0 0 600 600">
<svg x = {10} y = {10} height = {40} width = {100} viewBox = "0 0 100 40">
<path d= {"M0 0 L100 40 M0 40 L100 0"} />
</svg>
<svg>
If I add transform={rotate(90)} transform-origin="50% 50%" to the path element, then the element rotates, but gets cutoff by the svg.
If I instead add that same code to the parent svg (the 100 width one), then absolutely nothing happens.
You need to reserve enough space for your path to rotate in. Without changing the container size, you can define the viewBox to include all the coordinates where the rotated path could end at. That rectangle will then be fitted into your container.
If you rotate the path around its center at (50, 20), its upper limit with a rotation of 90deg will end at y=-30. The viewBox needs to include that value.
Your code also indicates you want to move the path +10, +10 away from the upper left corner. To achieve that and leave it at its original size, set viewBox="-10 -40 600 600". That rectangle will be fit into your outer <svg>, without the need to define an inner one.
<svg width="600" height="600" viewBox="-10 -40 600 600">
<path d="M0 0 L100 40 M0 40 L100 0" stroke="red" />
<path transform="rotate(90, 50, 20)" d="M0 0 L100 40 M0 40 L100 0" stroke="blue" />
</svg>
In general it depends on the use case.
Here are two examples that might help where I place the cross using the transform attribute.
The red cross is your original path where 0,0 is in the upper left corner.
Here I translate the first and then rotate.
The same happens with the blue cross, but here I have moved 0,0 to the middle of the cross.
This can help in cases where the element needs to rotate a lot or copied around.
svg {
border: solid thin black;
display: block;
}
<svg width="200" height="200" viewBox="0 0 100 100">
<path d="M0 0 L100 40 M0 40 L100 0"
transform="translate(70 0) rotate(90)"
stroke="blue" />
</svg>
<svg width="200" height="200" viewBox="0 0 100 100">
<path d="M -50 -20 L 50 20 M -50 20 L 50 -20"
transform="translate(50 50) rotate(90)"
stroke="red" />
</svg>
Thank you everyone for the great answers. I haven't tested all the solutions yet, but I bet that each answer works best for different situations. However, I figured out a way that worked best for me. As shown in my question, I do have a "parent" svg that is quite large, but I needed help rotating the smaller svg properly while making sure paths/polygons inisde the smaller svg don't clip. I ended up surrounding the "small" svg tag with a g tag, and then applied the rotation transform to the g tag. This made the svg as a whole rotate, and rotated the inner contents of the svg as well. The end result looked something like this:
<svg width = {600} height = {600} viewBox = "0 0 600 600">
<g transform = "rotate(90)">
<svg x = {10} y = {10} height = {40} width = {100} viewBox = "0 0 100 40">
<path d= {"M0 0 L100 40 M0 40 L100 0"} />
</svg>
</g>
<svg>
It did look a little bit different since I was using React.js, but that was the gist of it.
All browsers (Chrome, Opera, MS Edge, ...) based on Blink-engine have SVG rendering bug in feGaussianBlur filter by stdDeviation small values – less then 0.8
The blurring effect works in this browsers based on Blink-engine only if we set the attribute stdDeviation to "0.8" and higher.
On the following picture you could see how looks the blurring effect rendering in different browsers by stdDeviation different values:
I have the following code:
<svg width="18" height="18" style="margin:9px">
<defs>
<filter id="blurMe">
<feGaussianBlur stdDeviation=".3" in="SourceGraphic"/>
</filter>
<symbol id="BlinkBug" viewBox="0 0 18 18" filter="url(#blurMe)">
<path d="M9,3H10L14,7V8L8,14H7L3,10V9z" fill="#0af" stroke="#14c"/>
<path d="M1,1L16,16M1,16L16,1" fill="none" stroke="#14c"/>
</symbol>
</defs>
<use href="#BlinkBug"/>
</svg>
You could also find the same code on my codepen.
When I change the attribute stdDeviation to "0.8" then the blurring effect is to big for my small icon and lines in the center of my icon are unrecognizable (see picture above).
What I have tried: I had added the following filter to my filter:
<feColorMatrix type="matrix" values="1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1.5 0"/>
But it works only if the feGaussianBlur filter works.
I had also tried to use stroke-width="1.5" but it does not help without blurring effect.
I can not also change this SVG icon width and height attributes from 18 to 54 to have on this way the blurring effect because I need it in original size.
How can I replace this filter? Maybe we have another similar filter with matrix or combination of filters or something like this?
I would like to find a workaround.
I will also try to report this bug to Blink developers.
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>
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
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>