SVG path to create triangle with rounded corners - svg

I'm trying to create a simple svg path in the shape of a triangle with rounded corners.
I've started from this triangle:
<svg width="440" height="440">
<path d="M5,100 L70,5 L135,100 z" fill="none" stroke="black" stroke-width="3" />
</svg>
But I'm struggling to add in the corners - this is as far as I've got:
<svg width="440" height="440">
<path d="M5,100 a10,10 1 0 1 -5,-10 L70,5 L135,90 a10,10 1 0 1 5,10 z" fill="none" stroke="black" stroke-width="3" />
</svg>
What is the correct path coordinates to create the triangle with three smooth corners? Do I need to do some geometry to calculate the correct strart and end points or is there a tool I can use to configure the shape which will give me the coordinates the shape is made up of?

Inkscape has an option to convert the stroke of a path to a filled object. With that you can:
Draw a simple triangle and set fill to none.
Define a stroke with a width that is double the radius of the corner rounding you want to achieve.
Set stroke-linejoin:round (Fill and Stroke dialog -> Stroke style -> Round join).
Select from menu Path -> Stroke to Path.
Set to node selection mode. Now you can remove all nodes on the inner side.
Set fill to none again and select a stroke to your liking.

Related

svg viewBox strange behavior?

Im trying to figure out how svg viewBox work but the code below breaks all logic.
<svg width="100" height="100" viewBox="0 0 1 20">
<circle cx="10" cy="10" r="10" fill="red"/>
</svg>
In my reality viewBox is for defining the area of svg canvas to show in the viewport. The result of this code should be the left most little piece of circle is centered horizontaly with white space on both sides but chrome nor do firefox follow this logic.Can some one explain how this work? And sorry for my english, i hope you undestand what im trying to say.
The problems here are that most of the circle is outside the viewBox (it's only 1 unit wide and the circle is 20 units wide) and the viewBox aspect ratio is not the same as the aspect ratio of its container.
The default for preserveAspectRatio is to maintain the aspect ratio rather than distorting the shape so we still need to draw a circle rather than an ellipse. Since the drawing area is square the circle will therefore draw into that square area and as the height of the viewBox is 20 we'll have a 20 x 20 area to draw into to draw a circle.
What do we do with the 1 unit viewBox width then? How do we map 0-1 to 20 units? We need to keep the middle value of the viewBox so that's 0.5.
We need to solve these equations then for x and y: (x + y) / 2 = 0.5 (keep the centre the same) and y - x = 20 (keep the width the same as the height to preserve the aspect ratio)
Doing the maths here: x + y = 1 -> y - (1 - y) = 20 -> 2y - 1 = 20 -> y = 10.5 and x = -9.5.
So we're going to display 0 - 20 for height and -9.5 - 10.5 in width which means you'll see roughly (but not quite) half a circle. You actually see slightly more than half the circle.
The browsers are rendering your SVG correctly.
The viewBox just defines the area that should be scaled to fit the viewport. The content is not clipped to the viewBox. If there are elements outside of the viewBox, but still within the viewport, then those will be visible.
In your case, you have asked the browser to center the very left edge of the circle in the viewport. But there is enough room for much of the rest of the circle to be visible.
svg {
background-color: linen;
}
<svg width="100" height="100" viewBox="0 0 1 20">
<circle cx="10" cy="10" r="10" fill="red"/>
<rect width="1" height="20" fill="none" stroke="black" stroke-width="0.3" stroke-dasharray="0.5 0.5"/>
</svg>

SVG arc is not following the ellipse

I want to draw a part of the ellipse with the arc path. But it doesn't work, as I thought it should. This is the code:
<svg fill="none" stroke="#f00" height="24" viewBox="0 0 24 24"
width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M16 3.4a9.7 8.3 0 1 0-9.3 14.4"/>
<ellipse cx="12.2" cy="11" rx="9.7" ry="8.3" stroke="green" opacity=".5"/>
</svg>
The picture:
The red path should follow the green path.
According to the arc code a rx ry x-axis-rotation large-arc-flag sweep-flag dx dy it should correspond to the part of ellipse that can be drawn to satisfy the constrains, as the start and the end points and the two radii. As you can see, through the point A and point B passes a green ellipse with radii 9.7 and 8.3. Why the arc with the same radii and same points doesn't correspond to it?
Can you find what should be the points A and B and radii, so that the acr is exactly the same as the part of the green ellipse?
Here is the codepen: https://codepen.io/anon/pen/eRXWLq
This is the closest I could get with completely different radii: https://codepen.io/anon/pen/EXMXNN
It's because your are using a "sweep flag" set to 0 (anticlockwise), and a "large arc" flag set to 1 (draw the longer of the two ways around the ellipse). However the anticlockwise distance between the two points on the ellipse is actually the shorter of the two ways around the ellipse.
The solution is to change the "large arc" flag to 0:
<svg fill="none" stroke="#f00" width="400px" viewBox="0 0 24 24"
width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M16 3.4a9.7 8.3 0 0 0 -9.3 14.4"/>
<ellipse cx="12.2" cy="11" rx="9.7" ry="8.3" stroke="green" opacity=".5"/>
</svg>
If you are wondering why the arc is still not perfectly accurate, it'll be either:
Your start and end points are not accurate. I.e. not perfectly on the ellipse, or
Numerical inaccuracy. See this answer for more info: How to render a svg circle using start and endAngle

Create SVG triangle

I am trying to create an equilateral triangle that you can see in this fiddle:
<svg xmlns="http://www.w3.org/2000/svg"
width="22"
height="22"
viewBox="0 0 22 22">
<path d = "M0 0 L0 22 L20 11" stroke = "red" stroke-width = "3" fill = "red"/>
</svg>
My thinking was that I put the pen at (0, 0) and then draw lines to the (20, 11) but the triangle does not look correct.
Your triangle is stroked, and the stroke extends beyond the path points you supplied (as the stroke is centered on the path). This means that the stroke gets cut off at the edges of your image. Try making the image a bit larger and don't start at (0, 0). Furthermore, the path is not closed, so the stroke only covers two of the three sides (closing a path is not necessary when just filling it).
The following should look more like the triangle you envisioned:
<svg xmlns="http://www.w3.org/2000/svg"
width="28"
height="28"
viewBox="0 0 28 28">
<path d = "M3 3 L3 25 L23 14 z" stroke = "red" stroke-width = "3" fill = "red"/>
</svg>
Alternatively, get rid of the stroke and you can keep your view box and coordinates. It doesn't add anything here, except making the shape slightly larger.

Draw a custom shape using SVG path Bezier curve

Is it possible to draw a path like the image below? It is basically a circle with gaps in between.
I was just able to make a circle so far using SVG path -
http://jsfiddle.net/k6pgpze6/
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
width="500px" height="500px">
<path
d="
M 100, 250
a 150,150 0 1,0 300,0
a 150,150 0 1,0 -300,0
"
/>
</svg>
Yes is the basic answer. You could draw individual arcs (ie. one <path> per arc), or you can have a path with multiple subpaths.
<path d="M 100,250 a 150,150 0 1,0 300,0
M 300,0 a 150,150 0 1,0 -300,0" />
However these lines won't end with the oblique angles that your picture has. If you want those, then your best bet is to draw a complete circle and use a <clipPath> or <mask> to make the gaps.
Update
Here's an approximation of your picture.
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
width="500px" height="500px">
<path transform="translate(250,250)"
fill="none"
stroke="black"
stroke-width="6"
d="M 39,-145
A 150,150, 0,0,1, 106,106
M 0,150
A 150,150, 0,0,1, -106,106
M -123,86
A 150,150, 0,0,1, -150,0
M -149,-13
A 150,150, 0,0,1, -39,-145" />
</svg>
To make it easier for myself, I've centred the circle at (0,0) and used a transform to move it to the right place on the page. Because I used this trick, it is easier to make sure all my coordinates (the M vales and the last two values in the A) are on the circle's circumference. It's just a bit of simple trigonometry (sin(angle)*150 and cos(angle)*150).
The trickiest part of an arc command is the large arc flag and sweep flag. The following diagram from the SVG spec is useful to look at.
In your case, you will want to use the same value for all the sweep flags (fifth value in the arc command). Choose either 1 or 0 depending on whether you are going clockwise or anti-clockwise around the circle.
For the large arc flag (fourth value), use 0 if your arc covers less than 180 degrees, or 1 if it is greater than 180 degrees.

How can I cut one shape inside another?

Is there a way to cut one shape out of another in SVG? For example, I have a rect and an ellipse and I want to make a rect with a transparent hole in the middle. I would imagine it would look something like this:
<set operation="difference" fill="black">
<rect x="10" y="10" width="50" height="50/>
<ellipse cx="35" cy="35" rx=10 ry=10/>
</set>
The closest thing I can find is clipping, which will give me the intersection of two shapes. In my example that would result in just the hole being solid and the rest of the rect being transparent.
I looked through Inkscape and there is a difference option in the path menu, but this converts the shapes to paths and then creates a new path. The identity of the shapes is lost so there is no easy way to, for example go into the svg file and change the radius of the ellipse.
Is there any ideas for how I might do this?
You must use path element to cut a hole.
See the example from the SVG specification: (you can click this link or the following image to view the real svg file)
<g fill-rule="evenodd" fill="red" stroke="black" stroke-width="3">
<path d="M 250,75 L 323,301 131,161 369,161 177,301 z"/>
<path d="M 600,81 A 107,107 0 0,1 600,295 A 107,107 0 0,1 600,81 z
M 600,139 A 49,49 0 0,1 600,237 A 49,49 0 0,1 600,139 z"/>
<path d="M 950,81 A 107,107 0 0,1 950,295 A 107,107 0 0,1 950,81 z
M 950,139 A 49,49 0 0,0 950,237 A 49,49 0 0,0 950,139 z"/>
</g>
For your case:
<path d="M10 10h50v50h-50z M23 35a14 10 0 1 1 0 0.0001 z"
stroke="blue" stroke-width="2" fill="red" fill-rule="evenodd" />
M10 10h50v50h-50z will draw a rect.
M25 35a10 10 0 1 1 0 0.0001 z will draw a ellipse.
fill-rule="evenodd" will make the hole.
The key point is draw outer shape and inner shapes(holes) in different direction (clockwise vs anti-clockwise).
Draw the outer shape clockwise and draw the inner(holes) shapes anti-clockwise.
Or conversely, draw the outer shape(holes) anti-clockwise and draw the inner shapes clockwise.
Concat the path datas of outer shape and inner shapes(holes).
You can cut more holes by concat more hole path data.
This image explain how to cut a hole:
See w3c docs:
SVG Arc Commands
and
SVG fill-rule Property.
You should be able to use the fill-rule: evenodd property to achieve this effect, if you want to prevent the fill of the rectangle from painting where the circle is. See this example from the SVG specification (image below will only display if your browser supports SVG):
For some reason, I can't seem to get this to work with shapes like the rect and ellipse that you provided in the question. Here's my attempt:
You need to use a <path> if you want to use fill-rule. But it's certainly possible to change the radius of a circle that is a subpath of the <path>, you just need to master the arc path command.
Unfortunately it seems that there's no way to do this. Neither SVG 1.0 nor SVG 1.1 do not support boolean shape operations, clipping is supported for other reasons. The closest you can get is trying to get a "inverted" shape to do the clipping.

Resources