0

I'm trying to create an animation that uses SVG filters and the stroke-dasharray approach to create a progressively drawn "glowing" line effect. After quite a bit of research I was able to put together something that sort of works:

JSFiddle (the SVG paths make this too big for an SO snippet)

My attempted solution uses two sets of coordinates, the first being the lines themselves, followed by the same paths with the SVG glow filter applied. For the most part, the animation looks ok and close to what I'd like as far as the appearance.

The problem is that the animation is obviously resource intensive and is super clunky in FireFox and Safari. How can I achieve this same animated "glowing line" effect while getting it to run smoothly in those browsers? Is there a way around the performance hit with such a large set of coordinates, or is there a better way to achieve the glow effect without using two sets of paths?

Also for what it's worth...I'm not using an image of R2-D2, but the actual line drawing is comprised of a similarly large set of coords, so this makes for a representative example.

I'm new to working with animated SVGs, and I realize my approach here may be a bit obtuse. Any help is very much appreciated.

Rich
  • 3,156
  • 3
  • 19
  • 29

2 Answers2

1

Well, what you're trying to do is avoid all those recalculated filters. So what you can do is to draw the glowing drawing first, then draw a 4pxish black stroked copy of top of it, and then reverse-animate the over-drawing - thereby revealing the original.

Michael Mullany
  • 30,283
  • 6
  • 81
  • 105
  • Are you sure? In my experience, changing an element that grafically sits on top of other elements triggers all elements whose bounding box overlap to redraw - even if they do not change themself. That would result in a recalculation of the filters. – ccprog May 13 '17 at 19:12
  • Redraws have been getting better - but if does trigger a redraw then you can put the underlay into a separate SVG and pull it in via an image tag. – Michael Mullany May 14 '17 at 01:50
1

There are quite a few optimisations you can do to tweak performance. The base pattern you should use looks like this:

<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;
  }
}

Key points to note

  • only one set of paths
  • only one animation, applied to the <g> arround the paths
  • styles and filter applied to <use>
  • simpler filter with only 2 computation steps instead of 9
ccprog
  • 20,308
  • 4
  • 27
  • 44