Анимированное рисование светящихся линий SVG не работает в браузерах

Я пытаюсь создать анимацию, использующую фильтры SVG и stroke-dasharray. подход к созданию эффекта постепенно нарисованной «светящейся» линии. После недолгих исследований я смог собрать что-то вроде работы:

JSFiddle (пути SVG делают это слишком большим для фрагмента SO)

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

Проблема в том, что анимация явно ресурсоемкая и очень неуклюжая в FireFox и Safari. Как я могу добиться того же анимированного эффекта «светящейся линии», чтобы он работал без сбоев в этих браузерах? Есть ли способ обойти падение производительности с таким большим набором координат или есть лучший способ добиться эффекта свечения без использования двух наборов путей?

Кроме того, для чего это стоит ... Я не использую изображение R2-D2, но фактический рисунок линии состоит из такого же большого набора координат, так что это делает пример репрезентативным.

Я новичок в работе с анимированными SVG, и я понимаю, что мой подход здесь может быть немного тупым. Любая помощь очень ценится.


person Rich    schedule 13.05.2017    source источник


Ответы (2)


Есть довольно много оптимизаций, которые вы можете сделать, чтобы настроить производительность. Базовый шаблон, который вы должны использовать, выглядит следующим образом:

<svg xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
  <g id="lines">
    <!--one set of paths, no classes, no attributes besides d-->
    <path d="..." />
  </g>
  <filter id="glow">
    <feGaussianBlur stdDeviation="4 4" result="glow"/>
    <feComponentTransfer>
      <feFuncA type="linear" slope="8"/>
    </feComponentTransfer>
  </filter>
</defs>
  <use xlink:href="#lines" class="line" />
  <use xlink:href="#lines" class="glow" filter="url(#glow)" />
</svg>

CSS:

body {
  background: black;
}

#lines {
  stroke-dasharray: 3400;
  stroke-dashoffset: 3400;
  animation: draw 16s forwards ease;
}

.line {
  stroke: white;
  stroke-width: 1;
}

.glow {
  stroke: lime;
  stroke-width: .7;
  fill: none;
  opacity: .5;
}

@keyframes draw {
  to {
    stroke-dashoffset: 0;
  }
}

Ключевые моменты, на которые следует обратить внимание

  • только один набор путей
  • только одна анимация, примененная к <g> вокруг путей
  • стили и фильтр применены к <use>
  • более простой фильтр всего с 2 шагами вычисления вместо 9
person ccprog    schedule 14.05.2017

Что ж, вы пытаетесь избежать всех этих пересчитываемых фильтров. Итак, что вы можете сделать, так это сначала нарисовать светящийся рисунок, затем нарисовать 4-пиксельную черную обведенную копию его верхней части, а затем анимировать перерисовку в обратном порядке, тем самым открывая оригинал.

person Michael Mullany    schedule 13.05.2017
comment
Уверены ли вы? По моему опыту, изменение элемента, который графически расположен поверх других элементов, вызывает перерисовку всех элементов, ограничивающая рамка которых перекрывается, даже если они сами не меняются. Это приведет к пересчету фильтров. - person ccprog; 13.05.2017
comment
Перерисовка стала лучше, но если она вызывает перерисовку, вы можете поместить подложку в отдельный SVG и вытащить ее через тег изображения. - person Michael Mullany; 14.05.2017