Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SVG polar gradients

I'm a beginner at SVG, but I'd like to learn some techniques.

To be short, is there a simple way to create something like this?

A common spinner

I was thinking about creating a polar gradient and then clipping it:

Polar gradient

But how do I generate a polar gradient?

Even if there's no native method, maybe it could be made with a simple linear gradient and then using some rectangular-polar coordinate transformation. Is there a way to do so?

like image 856
MaxArt Avatar asked Jun 17 '13 13:06

MaxArt


1 Answers

So this is the solution I developed:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> 
<svg viewBox="0 0 100 100" version="1.1" onload="makeGradient();">
    <script>
        function makeGradient() {
            var root = document.rootElement, i = 256, cir, a;
            for (; i--;) {
                a = i*Math.PI/128;
                cir = document.createElementNS("http://www.w3.org/2000/svg", "circle");
                cir.setAttribute("cx", 50 - Math.sin(a)*45);
                cir.setAttribute("cy", 50 - Math.cos(a)*45);
                cir.setAttribute("r", "5");
                cir.setAttribute("fill", "rgb(" + i + ", " + i + ", " + i + ")");
                root.appendChild(cir);
            }
        }
    </script>
</svg>

Minified version (395 bytes):

<?xml version="1.0" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" version="1.1" onload="g(this.namespaceURI,document,Math)"><script>function g(n,d,m,i,c,a,p,z){for(i=256;i--;){a=i*m.PI/128;c=d.createElementNS(n,"circle");for(p in z={cx:10-m.sin(a)*9,cy:10-m.cos(a)*9,r:1,fill:"rgb("+[i,i,i]+")"})c.setAttribute(p,z[p]);d.rootElement.appendChild(c)}}</script></svg>

This was made creating circles filled with 256 shades of gray (it sounds like porn literature for coders!) and conveniently placed.

The radii can be adjusted: I've chosen 45 for the whole spinner and 5 for the single circles. Moreover, the detail can be adjusted too if 256 are too many:

for (; i -= 2;) { ...

Use powers of 2 for optimal results. Or just define the number of steps:

var steps = 100, i = steps;
for (; i--;) {
    a = i*2*Math.PI/steps;
    ...
    cir.setAttribute("fill", "rgb(" + i*255/steps + ", " + ...);
}

A big "thank you" to Erik Dahlström for the hint, and thank you Michael Mullany for the attempt :)

Edit: Here's a fiddle to demonstrate the code.

Edit 2: Here's another fiddle using curved segments to create the spinner. You can adjust the number of segments and the size, and even see it spinning. I don't know why when the size is auto, there's a bottom margin of 5 pixels on the SVG, this making the spinning slightly off-centered...

like image 115
MaxArt Avatar answered Sep 23 '22 20:09

MaxArt