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>
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.
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.
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
I have been struggling for a little while with SVG's and clip paths.
I'm trying to create a triangle clip path that will overlay a photo to give the top a "triangle" edge.
I am trying to achieve exactly the same as the photo, but the triangle "reversed". Imagine that same triangle at the top of the photo instead of the bottom.
How would i achieve this? I am able to create the triangle itself with a fill color, but it will still display the image "above" the triangle.
Found this online, it does exactly what i want but it's the wrong way.
<svg class="bigTriangleColor2" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="3 0 97 102" preserveAspectRatio="none">
<path fill="rgba(255,255,255,1)" d="M0 0 L51 102 L0 103 Z M0 205 L100 103 L100 2 Z"></path>
</svg>
Try using an SVG editor, like "Inkskape" (it's free); then:
drag & drop your images, clip & mask what-ever you wish, then
save as "plain SVG"
open the saved SVG file in your favorite text editor and remove the excess code, like the "XML" declaration at the top, and any other extras.
copy & paste the code where-ever you want it
Quick, simple, easy ;)
I am attempting to draw a number of lines on a map- basically, walking directions to subway stations. Many of these walking directions are the same for 50% or more of the journey (as you'd expect, coming from the same start point), so when I draw them, they draw on top of each other, obscuring each other- like so:
In this example, the red line is partly obscured by the yellow line- I would like to move the yellow e.g. at a 45 degree angle to place it parallel to the red line. I initially tried offsetting the X and Y coordinates by a few pixels, but any lines that aren't on 90 degree angles look wrong. I started playing around with calculating the degrees that a line is travelling on and to be honest I started to get lost- get the programming side of it, just not the geometry/trig/math of it.
Does anyone have some advice of what keywords I should even be looking for, or what paths I should be going down with this? Thanks in advance.
One trick is to stagger the lines when it overlaps. Here's 4 lines overlapping and staggered so that all lines are visible. Human eye is well trained to follow a color.
Example: http://jsbin.com/ovacar/1/edit
<svg>
<path stroke="skyblue" stroke-width="4" stroke-dasharray="5,15" d="M0 20 l215 0" />
<path stroke="cyan" stroke-width="4" stroke-dasharray="0,0,5,15" d="M5 20 l215 0" />
<path stroke="pink" stroke-width="4" stroke-dasharray="0,5,5,10" d="M5 20 l215 0" />
<path stroke="green" stroke-width="4" stroke-dasharray="0,10,5,5" d="M5 20 l215 0" />
</svg>
I would try just moving each corner on line 2 a couple of metre to the North East by adding a small fraction (try .00001 but experiment) to both lat and long values. This should give parallel lines when zoomed in.
You could also try reducing the opacity of the lines so they blend rather than overlay.