Vue.js SVG Loader

HTML

<script src="https://rawgit.com/vuejs/vue/dev/dist/vue.js"></script>
<script src="https://rawgit.com/vuejs/vue-router/dev/dist/vue-router.js"></script>
<script src="https://rawgit.com/vuejs/vue-resource/master/dist/vue-resource.js"></script>
<div id="app">
  <svg-loader></svg-loader>
</div>

<script type="text/template" id="svg-loader">
  <svg class="loader" viewBox="0 0 120 120" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <symbol id="s--circle">
      <circle r="10" cx="20" cy="20"></circle>
    </symbol>
    <g class="g-circles g-circles--v4">
      <g class="g--circle">
        <use xlink:href="#s--circle" class="u--circle" />
      </g>
      <g class="g--circle">
        <use xlink:href="#s--circle" class="u--circle" />
      </g>
      <g class="g--circle">
        <use xlink:href="#s--circle" class="u--circle" />
      </g>
      <g class="g--circle">
        <use xlink:href="#s--circle" class="u--circle" />
      </g>
      <g class="g--circle">
        <use xlink:href="#s--circle" class="u--circle" />
      </g>
      <g class="g--circle">
        <use xlink:href="#s--circle" class="u--circle" />
      </g>
      <g class="g--circle">
        <use xlink:href="#s--circle" class="u--circle" />
      </g>
      <g class="g--circle">
        <use xlink:href="#s--circle" class="u--circle" />
      </g>
      <g class="g--circle">
        <use xlink:href="#s--circle" class="u--circle" />
      </g>
      <g class="g--circle">
        <use xlink:href="#s--circle" class="u--circle" />
      </g>
      <g class="g--circle">
        <use xlink:href="#s--circle" class="u--circle" />
      </g>
      <g class="g--circle">
        <use xlink:href="#s--circle" class="u--circle" />
      </g>
    </g>
  </svg>
</script>

SCSS

$max: 12;
$angle: 360/$max;
$size: 120px;
$fill: dodgerblue;
.loader {
  height: $size;
  width: $size;
  overflow: visible;
  /* border: 1px solid red; */
}

@function transform($item: 1) {
  $base: rotate(#{-$angle*$item}deg) translate(5px, 5px);
  @return $base;
}

.g--circle {
  transform-origin: $size/2 $size/2;
  fill: $fill;
  animation: opacity 1.2s linear infinite;
  @for $item from 1 through $max {
    &:nth-child(#{$max}n + #{$item}) {
      animation-delay: -#{$item/10}s;
      transform: transform($item) scale(.9);
    }
  }
}

.g-circles--v1 .g--circle {
  fill-opacity: 0;
  animation-name: opacity;
}

.g-circles--v2 .g--circle {
  fill-opacity: 0;
  stroke-opacity: 0;
  stroke-width: 1;
  stroke: yellowgreen;
  animation-name: opacity-stroke, colors, colors-stroke;
  .u--circle {
    //transform: scale(.6) translate(10px,10px);
    //transform-origin: 10px 10px;
    animation: transform-2 1.2s linear infinite;
  }
}

.g-circles--v2 .g--circle {
  @for $item from 1 through $max {
    &:nth-child(#{$max}n + #{$item}) .u--circle {
      animation-delay: -#{$item/10}s;
    }
  }
}

.g-circles--v3 .g--circle {
  fill-opacity: 1;
  animation-name: opacity, colors;
}

.g-circles--v4 {
  .g--circle {
    fill-opacity: 1;
    fill: orange;
    animation-name: opacity, colors-3;
  }
  .u--circle {
    animation: transform 1.2s linear infinite;
  }
}

.g-circles--v4 .g--circle {
  @for $item from 1 through $max {
    &:nth-child(#{$max}n + #{$item}) .u--circle {
      animation-delay: -#{$item/10}s;
    }
  }
}

@keyframes opacity {
  3% {
    fill-opacity: 1;
  }
  75% {
    fill-opacity: 0;
  }
}

@keyframes opacity-stroke {
  10% {
    stroke-opacity: 1;
  }
  85% {
    stroke-opacity: 0;
  }
}

@keyframes colors {
  0% {
    fill: yellowgreen;
  }
  10% {
    fill: gold;
  }
  75% {
    fill: crimson;
  }
}

@keyframes colors-stroke {
  0% {
    stroke: yellowgreen;
  }
  10% {
    stroke: gold;
  }
  75% {
    stroke: crimson;
  }
}

@keyframes colors-2...

Babel + JSX

Vue.component('svg-loader', {
	template: '#svg-loader'
});

new Vue({
	el: '#app'
});