Can I apply a gradient along an SVG path?

2019-01-07 19:18发布

I'd like to put a simple loading indicator on my website that's triggered by a script. It should be a simple circle arc that's got a gradient and is spinning while the user is waiting. I haven't tried the animation part, but got stuck on the static styling for now. Here's 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="transparent"/>
        </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, from the top edge anti-clockwise to the right edge (270°), but the gradient is wrong. Instead of following the path so that the beginning (top edge, 0°) is opaque and the end (right edge, 270°) is transparent, the resulting image of the arc stroke is coloured from left to right in screen space.

How can I make the gradient follow my arc path?

3条回答
男人必须洒脱
2楼-- · 2019-01-07 19:42

This type of gradient is not easy to achieve in SVG, see SVG angular gradient.

Also, transparent is not a valid color in SVG. You should state stop-opacity as in this example: http://jsfiddle.net/WF2CS/

I'm afraid the easiest solution might be a series of small arc paths with varying opacity.

查看更多
孤傲高冷的网名
3楼-- · 2019-01-07 19:48

Another way is to make two half circles and apply the opposite linear gradient to each's stroke, and make sure they are both contained in a g element. (In my example the combined gradient isn't 270 degrees but 360. Two half-circles are stacked vertically. The first gradient (applied to the top semi-circle's stroke) would be 100-50% opacity, then the next would have 0% to 50%. Both gradients have the unit vector set to x1,y1,y2=0 and x2=1, making them run from left to right.) Then apply transform=rotate(deg,ctrX,ctrY) to the g.

查看更多
手持菜刀,她持情操
4楼-- · 2019-01-07 19:56

Mike Bostock figured out a way, though it's not easy: https://bl.ocks.org/mbostock/4163057

Basically, this technique uses getPointAtLength to slice the stroke into many short strokes, specify interpolated color stops for each, and then apply a gradient to each short stroke between those stops.

Good luck if you're up to the challenge ;)

查看更多
登录 后发表回答