I am new to SVG and want to have a curve with pointed ends like the following image in svg code (using a python svg library):
Is there any way to achieve this using a bezier curve, or is there a possibility to draw a normal bezier curve and modify the ends with css to become pointed? I would appreciate a code example.
CodePudding user response:
You can just use a closed path with two curves, one slightly "bulgier" than the other:
<svg height="100" width="500" viewBox="0 40 100 60">
<path d="M 0 60 Q 50 40 100 60 Q 50 45 0 60 Z" />
</svg>
In this, the first curve is M 0 60 Q 50 40 100 60
, i.e. a quadratic curve from 0,60 to 100,600 over the control point 50,40, and the second curve is the ... 100 60 Q 50 45 0 60
part, defining a curve starting at "wherever we already were", i.e. 100,60 (the end point of our first curve), ending at 0,60 (the start point of our first curve) and controlled by 50,45
The Z
is technically not necessary here, but since this is a closed path, we might as well explicitly encode that this is a closed path.
And if you want "tapered ends" then you can use two cubic curves instead, with the control points near the end points.
<svg height="100" width="500" viewBox="0 40 100 60">
<path d="M 0 60 C 10 40 90 40 100 60 C 80 45 20 45 0 60 Z" />
</svg>
Of course, this is only an approximation, but it'll get you pretty much what you need in almost all cases. And for the few cases where this doesn't suffice, solve those on their own.
CodePudding user response:
It's possible to generate something like this by using a gooey filter on a line that's been filled with an appropriate alpha gradient to get a variable width. But the results take quite a bit of fiddling with the gradient alphas, blur radius, gooey parameters in the filter, and then the "fix-up" feComponentTransfer. I would recommend explicitly drawing it with a filled shape.
<svg width="400px" height="400px" viewBox="0 0 55 55">
<defs>
<filter id="taper" filterUnits="userSpaceOnUse" width="55" height="55">
<feGaussianBlur stdDeviation="0.8"/>
<feColorMatrix type="matrix" values="
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 9 -2"/>
<feComponentTransfer>
<feFuncA type="table" tableValues="0 1 1 1 1 1"/>
</feComponentTransfer>
</filter>
<linearGradient id="myGradient">
<stop offset="0%" stop-color="rgba(0,0,0,0.3)" />
<stop offset="50%" stop-color="rgba(0,0,0,1)" />
<stop offset="100%" stop-color="rgba(0,0,0,0.3)" />
</linearGradient>
</defs>
<path d="M 10 10 C 20 20, 40 20, 50 10" stroke="url(#myGradient)" stroke-width="2" fill="none" filter="url(#taper)" stroke-linecap="round"/>
</svg>