Анимация загрузки круга


Я пытаюсь создать анимацию загрузки Apple OS X circle.

что я пробовал до сих пор:

.animation-wrapper {
  width: 200px;
  height: 200px;
  border: 1px solid black;
  border-radius: 50%;
  position: relative;
  overflow: hidden;
  filter: brightness(0.8);
  -webkit-filter: brightness(0.8);
}
.pie-piece1 {
  position: absolute;
  width: 50%;
  height: 50%;
  bottom: 0;
  left: 0;
  background: linear-gradient(to right, rgba(255, 0, 0, 1) 0%, rgba(255, 255, 0, 1) 100%);
}
.pie-piece2 {
  position: absolute;
  width: 50%;
  height: 50%;
  bottom: 0;
  right: 0;
  background: linear-gradient(to right, rgba(255, 255, 0, 1) 0%, rgba(0, 255, 0, 1) 100%);
}
.pie-piece3 {
  position: absolute;
  width: 50%;
  height: 50%;
  top: 0;
  left: 0;
  background: linear-gradient(to right, rgba(255, 0, 0, 1) 0%, rgba(255, 0, 255, 1) 100%);
}
.pie-piece4 {
  position: absolute;
  width: 50%;
  height: 50%;
  top: 0;
  right: 0;
  background: linear-gradient(to right, rgba(255, 0, 255, 1) 0%, rgba(0, 0, 255, 1) 100%);
}
.rotating-spinners {
  position: absolute;
}
.spike {
  fill: rgba(22, 22, 22, 0.5);
}
<figure class="animation-wrapper">
  <div class="pie-piece1"></div>
  <div class="pie-piece2"></div>
  <div class="pie-piece3"></div>
  <div class="pie-piece4"></div>
  <svg class="rotating-spinners" width="100%" height="100%" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <defs>
      <path id="spin-part" class="spike" d="M 65,-40 C 65,-40 80,20 50,50 60,40 50,-40 50,-40Z" />
    </defs>
    <use x="0" y="0" xlink:href="#spin-part" />
    <use x="0" y="0" xlink:href="#spin-part" transform="rotate(60, 50, 50)" />
    <use x="0" y="0" xlink:href="#spin-part" transform="rotate(120, 50, 50)" />
    <use x="0" y="0" xlink:href="#spin-part" transform="rotate(180, 50, 50)" />
    <use x="0" y="0" xlink:href="#spin-part" transform="rotate(240, 50, 50)" />
    <use x="0" y="0" xlink:href="#spin-part" transform="rotate(300, 50, 50)" />
  </svg>
</figure>

линейные градиенты, похоже, не выстраиваются правильно, так как я не мог найти способ заставить градиенты идти в двух направлениях.

есть ли способ создать это, используя только CSS или SVG, не смешивая их, как я сделал?

или есть другие решения, которые я могу использовать, как холст или какая-то магия изображений?

4 74

4 ответа:

вот мои усилия. Конический градиент-это встроенное растровое изображение, извлеченное путем вычисления максимального значения каждого пикселя в анимированном GIF, опубликованном OP. поверх этого накладывается полупрозрачный черный шаблон ветряной мельницы и анимируется, а фильтр размытия избавляется от артефактов JPEG.

(Edit: добавлена отражающая подсветка, чтобы она выглядела немного более 3D)

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
  width="121" height="121" viewBox="0 0 121 121">
  <defs>
    <clipPath id="circ">
      <circle r="60" cx="60.5" cy="60.5"/>
    </clipPath>
    <linearGradient id="shine" x1="0%" y1="0%" x2="0%" y2="100%">
      <stop offset="0%" style="stop-color:#fff;stop-opacity:0.6" />
      <stop offset="10%" style="stop-color:#fff;stop-opacity:0.3" />
      <stop offset="20%" style="stop-color:#fff;stop-opacity:0.1" />
      <stop offset="40%" style="stop-color:#fff;stop-opacity:0" />
    </linearGradient>
    <filter id="blur">
      <feGaussianBlur in="SourceGraphic" stdDeviation="2"/>
    </filter>
  </defs>
  <image width="121" height="121" filter="url(#blur)" xlink:href="data:image/jpeg;base64,
  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
  hIYYg5SFtM/cMbbeoFFHwc04MnGHKcXl/9k=" clip-path="url(#circ)" />
  <g transform="translate(60.5,60.5)">
    <path d="M0 0A56 56 0 0 0 0 56 56 56 0 0 0 32.916 45.305 56 56 0 0 1 0 0 56
        56 0 0 0 53.259 17.305 56 56 0 0 0 53.259-17.305 56 56 0 0 1 0 0 56 56
        0 0 0 32.916-45.305 56 56 0 0 0 0-56 56 56 0 0 1 0 0 56 56 0 0 0
        -32.916-45.305 56 56 0 0 0-53.259-17.305 56 56 0 0 1 0 0 56 56 0 0 0
        -53.259 17.305 56 56 0 0 0-32.916 45.305 56 56 0 0 1 0 0Z"
        stroke="none" fill="#000" opacity="0.25" transform="rotate(0)">
      <animateTransform attributeName="transform" type="rotate" from="0"
          to="72" begin="0s" dur="0.6s" repeatCount="indefinite" />
    </path>
    <circle r="59" stroke="#000" stroke-width="2" fill="none" opacity="0.25" />
    <circle r="55" fill="url(#shine)" stroke="none" />
  </g>
</svg>

вот моя версия SVG-only. Цвет фона колеса не идеально, но я думаю, что я получил довольно близко.

<svg width="135" height="135" viewBox="0 0 200 200">
    <defs>
        <filter id="blur" color-interpolation-filters="linear">
            <feGaussianBlur in="SourceGraphic" stdDeviation="11"/>
        </filter>
        <mask id="mask">
            <circle cx="0" cy="0" r="90" fill="white"/>
        </mask>
        <linearGradient id="gloss" x2="0" y2="0.4">
            <stop offset="0" stop-color="white" stop-opacity="0.5"/>
            <stop offset="1" stop-color="white" stop-opacity="0"/>
        </linearGradient>
    </defs>

    <g transform="translate(100,100)" mask="url(#mask)">
        <g filter="url(#blur)">
            <polygon points="0,0, -100,-26.8, -100,26.8" fill="#c44"/>
            <polygon points="0,0, -100,-26.8, -100,26.8" fill="#c09" transform="rotate(30)"/>
            <polygon points="0,0, -100,-26.8, -100,26.8" fill="#c0c" transform="rotate(60)"/>
            <polygon points="0,0, -100,-26.8, -100,26.8" fill="#90c" transform="rotate(90)"/>
            <polygon points="0,0, -100,-26.8, -100,26.8" fill="#44c" transform="rotate(120)"/>
            <polygon points="0,0, -100,-26.8, -100,26.8" fill="#09c" transform="rotate(150)"/>
            <polygon points="0,0, -100,-26.8, -100,26.8" fill="#0cc" transform="rotate(180)"/>
            <polygon points="0,0, -100,-26.8, -100,26.8" fill="#0c9" transform="rotate(210)"/>
            <polygon points="0,0, -100,-26.8, -100,26.8" fill="#4c4" transform="rotate(240)"/>
            <polygon points="0,0, -100,-26.8, -100,26.8" fill="#9c0" transform="rotate(270)"/>
            <polygon points="0,0, -100,-26.8, -100,26.8" fill="#cc0" transform="rotate(300)"/>
            <polygon points="0,0, -100,-26.8, -100,26.8" fill="#c90" transform="rotate(330)"/>
        </g>
        <g transform="scale(0.9,0.9)">
            <path d="M0,0C5,-61,-32,-86,-95,-90L-100,-46C-65,-53,-24,-35,0,0Z" fill="black" fill-opacity="0.4"/>
            <path d="M0,0C5,-61,-32,-86,-95,-90L-100,-46C-65,-53,-24,-35,0,0Z" fill="black" fill-opacity="0.4" transform="rotate(60)"/>
            <path d="M0,0C5,-61,-32,-86,-95,-90L-100,-46C-65,-53,-24,-35,0,0Z" fill="black" fill-opacity="0.4" transform="rotate(120)"/>
            <path d="M0,0C5,-61,-32,-86,-95,-90L-100,-46C-65,-53,-24,-35,0,0Z" fill="black" fill-opacity="0.4" transform="rotate(180)"/>
            <path d="M0,0C5,-61,-32,-86,-95,-90L-100,-46C-65,-53,-24,-35,0,0Z" fill="black" fill-opacity="0.4" transform="rotate(240)"/>
            <path d="M0,0C5,-61,-32,-86,-95,-90L-100,-46C-65,-53,-24,-35,0,0Z" fill="black" fill-opacity="0.4" transform="rotate(300)"/>
            <animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0" to="360" dur="4s" repeatCount="indefinite"/>

        </g>
        <circle r="83" fill="url(#gloss)"/>
        <circle r="90" fill="none" stroke="black" stroke-width="2"/>
    </g>
</svg>

Подход Холст

поскольку это анимация загрузки, где размеры, вероятно, будут исправлены с почти нулевым взаимодействием с пользователем,холст также был бы хорошим вариантом потому что он не добавляет никаких дополнительных элементов в DOM. Команды рисования холста очень похожи на SVG и поддержка браузеров тоже не хуже.

одним из недостатков было бы то, что холст не имеет собственного фильтра размытия (в отличие от SVG). Но это можно преодолеть либо с помощью CSS blur filter (имеет очень низкую поддержку браузера), либо библиотек, упомянутых в этот поток переполнения стека.


Колесо Градиента Фона:

колесо градиента фона создается с использованием подхода, аналогичного описанному в мой ответ здесь. В основном мы находим несколько точек в круге и рисуем линии, каждая из которых имеет различный цвет ход. Путем изменения hue значение для каждой линии можно нарисовать градиент колеса.

на скриншоте ниже первое изображение показывает, как выглядел бы фон, если бы мы нарисовали только 24 линии (с hue изменение 15 между каждой линией), а второй-наше фактическое градиентное колесо, которое имеет 360 линий в общей сложности с hue увеличивается на 1 для каждой строки.

любитель:

в вентилятор создается с использованием того же подхода,что и в вашем фрагменте SVG. Команды пути используются для рисования каждой спицы. В то время как use тег используется в SVG для повторения формы, петли могут быть использованы в холсте.

основное различие здесь между SVG и Canvas заключается в том, что Canvas не может принимать начало преобразования в качестве параметра для rotate функция и поэтому контекст должны быть переведены в центральную точку перед применением поворотов.

наконец, холст должен быть обрезан в a круг, потому что форма по умолчанию-квадрат (так как высота и ширина одинаковы). На приведенном ниже скриншоте показаны незакрепленные и обрезанные версии вентилятора.

этот вентилятор после этого помещен поверх колеса градиента предпосылки.

3D эффект:

3D-эффект сверху обеспечивается добавлением небольшой дуги с большим количеством прозрачности по фону и вентилятору.

ниже скриншот полной картины без какой-либо анимации.

анимация:

анимация добавляется с помощью window.requestAnimationFrame метод, который вызывает функцию, передаваемую в качестве аргумента через регулярные промежутки времени. Этот метод обычно вызывает функцию около 60 раз в секунду (согласно MDN). Путем увеличения значения counter переменная во время каждой итерации и добавление ее к углу вентилятора спицы эффект анимации может быть достигнут.

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();
}
<canvas width='100px' height='100px' id='canvas'></canvas>

SVG подход

такой же подход, как описано выше, может быть использован и с SVG. Единственным недостатком было бы нет. из дополнительных элементов, которые добавляются в DOM как для фона, так и для вентилятора.

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);
  }
}
<svg class="rotating-spinners" width="100px" height="100px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <path id="spin-part" class="spike" d="M 50,50 c0,0 30,50 100,0 l-5,-35 c0,0 -30,50 -95,35Z" />
    <clipPath id="shape">
      <circle r="50" cx="50" cy="50" />
    </clipPath>
    <clipPath id="shade">
      <path d='M-5,55 a55,55 1 0,1 110,0 h-5 a50,50 1 0,0 -100,0' />
    </clipPath>
  </defs>
  <g id='color-wheel' clip-path='url(#shape)'>
  </g>
  <g id='fan' fill-opacity="0.5" clip-path='url(#shape)'>
    <use x="0" y="0" xlink:href="#spin-part" />
    <use x="0" y="0" xlink:href="#spin-part" transform="rotate(60, 50, 50)" />
    <use x="0" y="0" xlink:href="#spin-part" transform="rotate(120, 50, 50)" />
    <use x="0" y="0" xlink:href="#spin-part" transform="rotate(180, 50, 50)" />
    <use x="0" y="0" xlink:href="#spin-part" transform="rotate(240, 50, 50)" />
    <use x="0" y="0" xlink:href="#spin-part" transform="rotate(300, 50, 50)" />
    <animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0,50,50" to="360,50,50" dur="6s" repeatCount="indefinite" />
  </g>
  <circle r='50' cx='50' cy='50' fill-opacity='0.15' clip-path='url(#shade)' />
</svg>

Смешанный Подход

или, если у вас есть никаких проблем с дополнительными элементами для вентилятора, но просто хочу избежать 360 line элементы, которые будут добавлены, вы можете использовать смесь Canvas (для фона) и SVG для поклонников, как в приведенном ниже фрагменте.

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%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='container'>
  <canvas width='100px' height='100px' id='canvas'></canvas>
  <svg class="rotating-spinners" width="100%" height="100%" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <defs>
      <path id="spin-part" class="spike" d="M 50,50 c0,0 30,50 100,0 l-5,-35 c0,0 -30,50 -95,35Z" />
      <clipPath id="shape">
        <circle r="50" cx="50" cy="50" />
      </clipPath>
    </defs>
    <g id='fan' fill-opacity="0.5" clip-path="url(#shape)">
      <use x="0" y="0" xlink:href="#spin-part" />
      <use x="0" y="0" xlink:href="#spin-part" transform="rotate(60, 50, 50)" />
      <use x="0" y="0" xlink:href="#spin-part" transform="rotate(120, 50, 50)" />
      <use x="0" y="0" xlink:href="#spin-part" transform="rotate(180, 50, 50)" />
      <use x="0" y="0" xlink:href="#spin-part" transform="rotate(240, 50, 50)" />
      <use x="0" y="0" xlink:href="#spin-part" transform="rotate(300, 50, 50)" />
      <animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0,50,50" to="360,50,50" dur="6s" repeatCount="indefinite" />
    </g>
  </svg>
</div>

Я должен был сделать это со смесью градиентов SVG и CSS, которые, как я знаю, против запроса, но это то, что я знаю. Я использовал некоторые из ваших оригинальных кодов, в основном части SVG для форм пропеллера.

радиальный градиент выполнен с использованием 12 li элементы.

.wheel,
.umbrella,
.color {
  content: "";
  position: absolute;
  border-radius: 50%;
  width: 15em;
  height: 15em;
  margin: 0;
  padding: 0;
}
.wheel {
  overflow: hidden;
  width: 15em;
  height: 15em;
  position: relative;
}
.umbrella {
  position: relative;
  -webkit-transform: scale(1.35);
}
.color,
.color:nth-child(n+7):after {
  clip: rect(0, 15em, 15em, 7.5em);
}
.color:after,
.color:nth-child(n+7) {
  content: "";
  position: absolute;
  border-radius: 50%;
  left: calc(50% - 7.5em);
  top: calc(50% - 7.5em);
  width: 15em;
  height: 15em;
  clip: rect(0, 7.5em, 15em, 0);
}
.color:nth-child(1):after {
  background-color: #9ED110;
  transform: rotate(30deg);
  z-index: 12;
}
.color:nth-child(2):after {
  background-color: #50B517;
  transform: rotate(60deg);
  z-index: 11;
}
.color:nth-child(3):after {
  background-color: #179067;
  transform: rotate(90deg);
  z-index: 10;
}
.color:nth-child(4):after {
  background-color: #476EAF;
  transform: rotate(120deg);
  z-index: 9;
}
.color:nth-child(5):after {
  background-color: #9f49ac;
  transform: rotate(150deg);
  z-index: 8;
}
.color:nth-child(6):after {
  background-color: #CC42A2;
  transform: rotate(180deg);
  z-index: 7;
}
.color:nth-child(7):after {
  background-color: #FF3BA7;
  transform: rotate(180deg);
}
.color:nth-child(8):after {
  background-color: #FF5800;
  transform: rotate(210deg);
}
.color:nth-child(9):after {
  background-color: #FF8100;
  transform: rotate(240deg);
}
.color:nth-child(10):after {
  background-color: #FEAC00;
  transform: rotate(270deg);
}
.color:nth-child(11):after {
  background-color: #FFCC00;
  transform: rotate(300deg);
}
.color:nth-child(12):after {
  background-color: #EDE604;
  transform: rotate(330deg);
}
<div class="wheel">
  <ul class="umbrella">
    <li class="color"></li>
    <li class="color"></li>
    <li class="color"></li>
    <li class="color"></li>
    <li class="color"></li>
    <li class="color"></li>
    <li class="color"></li>
    <li class="color"></li>
    <li class="color"></li>
    <li class="color"></li>
    <li class="color"></li>
    <li class="color"></li>
  </ul>
</div>

эти 12 элементов затем могут быть размыты вместе, чтобы сформировать плавный градиент.

затем я анимировал части спина, чтобы сделать эффект вы требовать.

var rotation = 0;

$(document).ready(function() {
  setInterval(function() {
    rotation += 1;
    $('.wheel svg').css({
      'transform': 'rotate(' + rotation + 'deg)'
    });;
  }, 10);
});
.wheel,
.umbrella,
.color {
  content: "";
  position: absolute;
  border-radius: 50%;
  width: 15em;
  height: 15em;
  margin: 0;
  padding: 0;
}
.wheel {
  overflow: hidden;
  width: 15em;
  height: 15em;
  position: relative;
}
.umbrella {
  position: relative;
  filter: blur(.75em);
  -webkit-filter: blur(.75em);
  -moz-filter: blur(.75em);
  -o-filter: blur(.75em);
  -ms-filter: blur(.75em);
  filter: url(#blur);
  filter: progid: DXImageTransform.Microsoft.Blur(PixelRadius='.75');
  -webkit-transform: scale(1.35);
}
.color,
.color:nth-child(n+7):after {
  clip: rect(0, 15em, 15em, 7.5em);
}
.color:after,
.color:nth-child(n+7) {
  content: "";
  position: absolute;
  border-radius: 50%;
  left: calc(50% - 7.5em);
  top: calc(50% - 7.5em);
  width: 15em;
  height: 15em;
  clip: rect(0, 7.5em, 15em, 0);
}
.color:nth-child(1):after {
  background-color: #9ED110;
  transform: rotate(30deg);
  z-index: 12;
}
.color:nth-child(2):after {
  background-color: #50B517;
  transform: rotate(60deg);
  z-index: 11;
}
.color:nth-child(3):after {
  background-color: #179067;
  transform: rotate(90deg);
  z-index: 10;
}
.color:nth-child(4):after {
  background-color: #476EAF;
  transform: rotate(120deg);
  z-index: 9;
}
.color:nth-child(5):after {
  background-color: #9f49ac;
  transform: rotate(150deg);
  z-index: 8;
}
.color:nth-child(6):after {
  background-color: #CC42A2;
  transform: rotate(180deg);
  z-index: 7;
}
.color:nth-child(7):after {
  background-color: #FF3BA7;
  transform: rotate(180deg);
}
.color:nth-child(8):after {
  background-color: #FF5800;
  transform: rotate(210deg);
}
.color:nth-child(9):after {
  background-color: #FF8100;
  transform: rotate(240deg);
}
.color:nth-child(10):after {
  background-color: #FEAC00;
  transform: rotate(270deg);
}
.color:nth-child(11):after {
  background-color: #FFCC00;
  transform: rotate(300deg);
}
.color:nth-child(12):after {
  background-color: #EDE604;
  transform: rotate(330deg);
}
body {
  padding: 5px;
}
.wheel svg {
  position: absolute;
  top: 0;
  opacity: .5;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<figure class="animation-wrapper wheel">
  <ul class="umbrella">
    <li class="color"></li>
    <li class="color"></li>
    <li class="color"></li>
    <li class="color"></li>
    <li class="color"></li>
    <li class="color"></li>
    <li class="color"></li>
    <li class="color"></li>
    <li class="color"></li>
    <li class="color"></li>
    <li class="color"></li>
    <li class="color"></li>
  </ul>
  <svg class="rotating-spinners" width="100%" height="100%" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <defs>
      <path id="spin-part" class="spike" d="M 65,-40 C 65,-40 80,20 50,50 60,40 50,-40 50,-40Z" />
    </defs>
    <use x="0" y="0" xlink:href="#spin-part" />
    <use x="0" y="0" xlink:href="#spin-part" transform="rotate(60, 50, 50)" />
    <use x="0" y="0" xlink:href="#spin-part" transform="rotate(120, 50, 50)" />
    <use x="0" y="0" xlink:href="#spin-part" transform="rotate(180, 50, 50)" />
    <use x="0" y="0" xlink:href="#spin-part" transform="rotate(240, 50, 50)" />
    <use x="0" y="0" xlink:href="#spin-part" transform="rotate(300, 50, 50)" />
  </svg>
</figure>