I want to put a simple loading indicator on my website that is triggered by a script. It should be a simple arc with a gradient and rotate while the user waits. I haven't tried the animation part yet, but am stuck on static styles now. This is what I've got so far:
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="100" height="100"> <defs> <linearGradient id="grad1"> <stop offset="0%" stop-color="red"/> <stop offset="100%" stop-color="red" stop-opacity="0" /> </linearGradient> </defs> <path d="M50 10 A40 40 0 1 0 90 50" stroke="url(#grad1)" stroke-width="10" fill="transparent"/> </svg>
It draws the arc counterclockwise from the top edge to the right edge (270°), but the gradient is wrong. The final image of the arc stroke is colored from left to right in screen space, rather than following the path such that the start point (top edge, 0°) is opaque and the end point (right edge, 270°) is transparent.
How do I make the gradient follow my arc path?
P粉4821083102023-10-19 13:06:33
Mike Bostock found a way, although it's not easy: https://bl.ocks.org/mbostock/4163057
Basically, this technique uses getPointAtLength
To split a stroke into many short strokes, specify an interpolation color stop for each stroke, and then interpolate the Apply gradient with each short stroke.
Good luck if you're up to the challenge ;)
Editor (July 3, 2019):
Now there is a library that can help you do exactly what you are looking for. Not required to use D3, but you can if you wish. This is a tutorial about Medium.
P粉5712335202023-10-19 09:37:43
CSS Image Module - Level 4 introduces conic-gradient. According to MDN, Supported in all major browsers except IE.
Although it's not technically a gradient along the path, since your path is circular, you can achieve the desired result by:
.loader { --size: 7.5rem; --stroke-size: .5rem; --diff: calc(calc(var(--size)/2) - var(--stroke-size)); background-image: conic-gradient(transparent 25%, red); width: var(--size); height: var(--size); border-radius: 50%; -webkit-mask:radial-gradient(circle var(--diff),transparent 98%,#fff 100%); mask:radial-gradient(circle var(--diff),transparent 98%,#fff 100%); animation: rotate 1.2s linear infinite; margin: 0 auto; } @keyframes rotate { from { transform: rotate(0); } to { transform: rotate(1turn); } } body { background: #f9fcfc url(https://picsum.photos/id/22/1323/880) 100% /cover; margin: 0; min-height: 100vh; padding-top: 2.5rem; } * { box-sizing: border-box; }
<div class="loader"></div>