Reputation: 1255
How can i create the following widget in SVG?
I'm fine with the shapes itself but i'm struggling with the inset shadow on the back circle.
I've tried a radial gradient, which 'works' but it doesn't look that great and I have to fiddle with the stop values on the order of thousandths of a percent to get it exactly right and it just feels totally hacky.
Is there a better way?
Code to produce the SVG:
<svg width="180" height="180" version="1.1" xmlns="http://www.w3.org/2000/svg">
<circle cx="90" cy="90" r="72" fill="none" stroke="#ddd" stroke-width="18"></circle>
<path class="main-arc" d="M 90 18 A 72 72 0 1 1 85.47908259388944 18.142075553164446" fill="transparent" stroke-width="18" stroke="black" stroke-linecap="round" style="stroke-dasharray: 452.389; stroke-dashoffset: 366.435;">
</path>
</svg>
Upvotes: 5
Views: 5632
Reputation: 31715
Well you can do it the easy way with an inset shadow:
<svg width="180" height="180">
<defs>
<filter id="inset-shadow">
<feFlood flood-color="black"/>
<feComposite operator="out" in2="SourceGraphic"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite operator="atop" in2="SourceGraphic"/>
</filter>
</defs>
<circle filter="url(#inset-shadow)" cx="90" cy="90" r="72" fill="none" stroke="#ddd" stroke-width="18"></circle>
<path class="main-arc" d="M 90 18 A 72 72 0 1 1 85.47908259388944 18.142075553164446" fill="transparent" stroke-width="18" stroke="black" stroke-linecap="round" style="stroke-dasharray: 452.389; stroke-dashoffset: 366.435;">
</path>
</svg>
But if you really want a 3D effect, then you'll need a lighting effect:
<svg width="180" height="180" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="inset-shadow">
<feFlood flood-color="black"/>
<feComposite operator="xor" in2="SourceGraphic"/>
<feGaussianBlur stdDeviation="1"/>
<feComposite operator="in" in2="SourceGraphic" result="map"/>
<feDiffuseLighting lighting-color="white" surfaceScale="2" diffuseConstant="1">
<feSpotLight x="-30" y="-30" z="230"/>
</feDiffuseLighting>
<feBlend mode="multiply" in="SourceGraphic" />
<feComposite operator="in" in2="SourceGraphic"/>
</filter>
</defs>
<circle filter="url(#inset-shadow)" cx="90" cy="90" r="72" fill="none" stroke="#ddd" stroke-width="18"></circle>
<path class="main-arc" d="M 90 18 A 72 72 0 1 1 85.47908259388944 18.142075553164446" fill="transparent" stroke-width="18" stroke="black" stroke-linecap="round" style="stroke-dasharray: 452.389; stroke-dashoffset: 366.435;">
</path>
</svg>
Upvotes: 11
Reputation: 24577
Draw a pale grey stroked circle on a darker grey background, apply a gaussian blur filter, and clip the results with a clipPath:
<svg width="360" height="360" viewBox="0 0 180 180">
<defs>
<!-- Gaussian blur filter used to soften the shadow edges -->
<filter id="blur" filterUnits="userSpaceOnUse" x="-90" y="-90"
width="180" height="180">
<feGaussianBlur in="SourceGraphic" stdDeviation="1" />
</filter>
<!-- Annular clip path for the progress meter background -->
<clipPath id="ring" clip-rule="evenodd">
<path d="M0-81A81 81 0 0 1 0 81A81 81 0 0 1 0-81z
M0-63A63 63 0 0 1 0 63A63 63 0 0 1 0-63z" />
</clipPath>
</defs>
<!-- Set orgin to centre of drawing -->
<g transform="translate(90,90)">
<!-- Start with pale yellow background -->
<rect x="-90" y="-90" width="180" height="180" fill="#e8e0ce"
stroke="none" />
<!-- Draw the progress ring on top, and clip using the above clip path -->
<g clip-path="url(#ring)">
<!-- Dark grey background -->
<rect x="-85" y="-85" width="170" height="170" fill="#433"
stroke="none" />
<!-- Lighter grey circle with blur filter applied -->
<circle cx="0" cy="2.5" r="72" stroke="#655" stroke-width="18"
stroke="#655" fill="none" filter="url(#blur)"/>
</g>
<!-- Progress bar and text -->
<path class="main-arc" d="M 0 -72 A 72 72 0 1 1 -4.52 -71.86"
style="stroke-dasharray: 452.389; stroke-dashoffset: 366.435;"
fill="transparent" stroke-width="18" stroke="#b65"
stroke-linecap="round" />
<text x="0" y="0" font-size="40" font-family="'Trebuchet MS', sans-serif"
fill="#655" text-anchor="middle" dominant-baseline="central">
20%
</text>
</g>
</svg>
Upvotes: 4