I\'m trying to create Apple\'s OS X circle loading animation.

What I h
Canvas Approach
Since this is a loading animation where the dimensions are probably going to be fixed with almost nil user interactions, Canvas would also be a good option because it doesn't add any extra elements to the DOM. Canvas drawing commands are pretty similar to SVG and the browser support is also not worse.
One disadvantage would be that Canvas does not have its own blur filter (unlike SVG). But that can be overcome by either using CSS blur filter (has very low browser support) or the libraries mentioned in this Stack Overflow thread.
Background Gradient Wheel:
The background gradient wheel is created using an approach similar to the one detailed in my answer here. Basically we find multiple points in the circle and draw lines each of which have different colored stroke. By modifying the hue value for every line we can paint the gradient wheel.
In the below screenshot the first picture shows how the background would have looked if we had drawn just 24 lines (with a hue change of 15 between every line)and the second one is our actual gradient wheel which has 360 lines in total with the hue being incremented by 1 for each line.

Fan:
The fan is created using the same approach as used in your SVG snippet. Path commands are used to draw each spoke. While use tag is used in SVG to repeat a shape, loops can be used in Canvas.
The main difference here between SVG and Canvas is that Canvas cannot take in transform origin as a parameter for the rotate function and so context must be translated to the center point before applying rotations.
Finally the canvas must be clipped into a circle because the default shape is a square (as height and width are same). The below screenshot shows the unclipped and clipped versions of the fan.

This fan is then placed on top of the background gradient wheel.
3D effect:
The 3D effect on top is provided by adding a small arc with an higher amount of transparency over the background and the fan.
Below is the screenshot of the full picture without any animation.

Animation:
Animation is added by using the window.requestAnimationFrame method which calls the function passed as an argument at regular intervals. This method would generally call the function about 60 times per second (according to MDN). By incrementing the value of the counter variable during every iteration and adding it to the angle of the fan's spokes the animation effect can be achieved.
window.onload = function() {
var canvas = document.querySelector("#canvas"),
ctx = canvas.getContext("2d"),
counter = 360;
function fan() {
ctx.clearRect(0, 0, 100, 100);
for (var i = 0; i < 360; i++) {
ctx.strokeStyle = "hsl(" + (180 - i) + ", 60%, 50%)";
ctx.beginPath();
ctx.moveTo(50, 50);
x = 50 + 50 * Math.cos((i / 360) * Math.PI * 2);
y = 50 + 50 * Math.sin((i / 360) * Math.PI * 2)
ctx.lineTo(x, y);
ctx.lineWidth = 2;
ctx.stroke();
}
counter++;
for (var j = 0; j < 6; j++) {
ctx.save();
ctx.beginPath();
ctx.arc(50, 50, 50, 0, Math.PI * 2, true);
ctx.clip();
ctx.translate(50, 50);
ctx.rotate(((60 * j) + counter) * Math.PI / 180);
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.bezierCurveTo(0, 0, 30, 50, 100, 0);
x = 75 * Math.cos((-20 / 360) * Math.PI * 2);
y = 75 * Math.sin((-20 / 360) * Math.PI * 2)
ctx.lineTo(x, y);
ctx.bezierCurveTo(x, y, (x - 30), (y + 40), 0, 0);
ctx.closePath();
ctx.fillStyle = "rgba(0,0,0,0.5)";
ctx.fill();
ctx.restore();
}
ctx.save();
ctx.beginPath();
ctx.arc(50, 50, 50, 0, Math.PI, true);
ctx.arc(50, 55, 50, Math.PI, 0, false);
ctx.fillStyle = "rgba(0,0,0,0.15)";
ctx.closePath();
ctx.fill();
ctx.restore();
window.requestAnimationFrame(fan);
}
fan();
}
SVG Approach
The same approach as described above can be used with SVG also. The only downside would be the no. of extra elements that get added to the DOM both for the background and the fan.
window.onload = function() {
var colorWheel = document.querySelector("#color-wheel");
for (var i = 0; i < 360; i++) {
lineColor = "hsl(" + (180 - i) + ", 60%, 50%)";
x = 50 + 50 * Math.cos((i / 360) * Math.PI * 2);
y = 50 + 50 * Math.sin((i / 360) * Math.PI * 2);
line = document.createElementNS("http://www.w3.org/2000/svg", "line");
line.setAttribute('x1', 50);
line.setAttribute('y1', 50);
line.setAttribute('x2', x);
line.setAttribute('y2', y);
line.setAttribute('stroke', lineColor);
line.setAttribute('stroke-width', 2);
colorWheel.appendChild(line);
}
}
Mixed Approach
Or, if you have no problems with the extra elements for the fan but just want to avoid the 360 line elements that would get added, you could use a mixture of Canvas (for the background) and SVG for the fans like in the below snippet.
window.onload = function() {
var canvas = document.querySelector("#canvas");
var ctx = canvas.getContext("2d");
for (var i = 0; i < 360; i++) {
ctx.strokeStyle = "hsl(" + (180 - i) + ", 60%, 50%)";
ctx.beginPath();
ctx.moveTo(50, 50);
x = 50 + 50 * Math.cos((i / 360) * Math.PI * 2);
y = 50 + 50 * Math.sin((i / 360) * Math.PI * 2)
ctx.lineTo(x, y);
ctx.lineWidth = 2;
ctx.stroke();
}
ctx.save();
ctx.beginPath();
ctx.arc(50, 50, 50, 0, Math.PI, true);
ctx.arc(50, 55, 50, Math.PI, 0, false);
ctx.fillStyle = "rgba(0,0,0,0.15)";
ctx.closePath();
ctx.fill();
ctx.restore();
}
div {
position: relative;
height: 100px;
width: 100px;
}
canvas,
svg {
position: absolute;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
}