SVG Animation Three Ways: SMIL Scrolling Gradient
Part 2: SMIL Scrolling Gradient
Despite the lean toward deprecation, there are still many SVG animation techniques that can only be accomplished using SMIL (Synchronized Multimedia Integration Language). According to MDN:
Although Chrome 45 deprecated SMIL in favor of CSS animations and Web animations, the Chrome developers have since suspended that deprecation.
SMIL lets you animate graphics by adding animation elements to your SVG code. Sara Soueidan gives a great explanation of these elements in her extensive guide to using SMIL from 2014:
<animate>which allows you to animate scalar attributes and properties over a period of time.
<set>- which is a convenient shorthand for animate, which is useful for assigning animation values to non-numeric attributes and properties, such as the visibility property.
<animateMotion>- which moves an element along a motion path.
<animateColor>- which modifies the color value of particular attributes or properties over time. Note that the
<animateColor>element has been deprecated in favor of simply using the animate element to target properties that can take color values. Even though it’s still present in the SVG 1.1 specification, it is clearly noted that it has been deprecated; and it has been completely removed from the SVG 2 specification.
For this second installment, continually inspired by the party parrot and the super hot trendiness of gradients right now, I wanted to create a scrolling gradient-fill affect for my leaf.
Step 1: Get that SVG Logo
Again, I started with the basic logo SVG code:
<svg width="100px" height="auto" viewBox="0 0 53 87" version="1.1"> <defs> <polygon id="path-1" points="52.67871 0.617407954 0 0.617407954 0 86.5269756 52.67871 86.5269756"></polygon> </defs> <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g id="junglebug"> <g id="Fill-1-Clipped"> <mask id="mask-2" fill="white"> <use xlink:href="#path-1"></use> </mask> <g id="path-1"></g> <path d="M47.76201,37.2875648 L28.79811,46.8794704 L28.79811,28.2616913 L47.82321,18.6869108 C47.84481,18.8698798 47.76201,19.0555529 47.76201,19.2430286 L47.76201,37.2875648 Z M26.22231,24.0984688 L7.62291,14.7850728 L26.13591,5.48068984 L44.80461,14.7931847 L26.22231,24.0984688 Z M23.88141,46.8794704 L4.56561,37.2875647 L4.56561,19.227706 C4.56561,19.044737 4.65831,18.8644719 4.67811,18.6860094 L23.88141,28.2616913 L23.88141,46.8794704 Z M23.88141,70.860136 L7.29261,62.5931788 C5.66001,61.7756767 4.56561,60.1316588 4.56561,58.3037707 L4.56561,42.6495499 L23.88141,52.2414556 L23.88141,70.860136 Z M47.31201,10.5578563 L47.28321,10.5578563 L28.16361,1.07681355 C26.89821,0.444984388 25.38171,0.47292548 24.11811,1.10745862 L5.22621,10.6425809 C1.96911,12.2802892 -9e-05,15.5773379 -9e-05,19.227706 L-9e-05,58.3037707 C-9e-05,61.9604482 1.99701,65.2475824 5.26221,66.8825867 L23.88141,76.2221214 L23.88141,86.5269756 L28.79811,86.5269756 L28.79811,76.2221214 L28.79811,70.860136 L28.79811,52.2468637 L28.79811,52.2414556 L47.76201,42.6495499 L47.76201,58.3037707 C47.76201,60.1316588 46.73151,61.7756767 45.09891,62.5931788 L33.36291,68.461709 L33.36291,73.8236943 L47.30391,66.8825867 C50.57001,65.2475824 52.67871,61.9604482 52.67871,58.3037707 L52.67871,19.2430286 C52.67871,15.5800418 50.58621,12.3163423 47.31201,10.5578563 Z" id="Fill-1" fill="#58BA57" fill-rule="nonzero"></path> </g> </g> </g> </svg>
This time I didn’t need to create any additional shapes in Sketch, however I did need to add some additional SVG elements to achieve my animated gradient fill.
Step 2: Create a gradient
To create a gradient in SVG, you use a
<radialGradient> element. These elements are then referenced by
id to use as either a fill or a stroke. I created a gradient that began and ended with the same color, so I could arrange elements of this gradient side by side without a visual seam.
<defs> <linearGradient id="gradient" x1="100%" y1="0%" x2="0%" y2="0%"> <stop offset="6.25%" style="stop-color:#87FFFE;"/> <stop offset="18.75%" style="stop-color:#88FF89;"/> <stop offset="31.25%" style="stop-color:#F8F58A;"/> <stop offset="43.75%" style="stop-color:#EF696A;"/> <stop offset="56.25%" style="stop-color:#F36ABA;"/> <stop offset="68.75%" style="stop-color:#EF696A;"/> <stop offset="81.25%" style="stop-color:#F8F58A;"/> <stop offset="93.75%" style="stop-color:#88FF89;"/> <stop offset="100%" style="stop-color:#87FFFE;"/> </linearGradient> </defs>
Step 3: Create a Pattern
In order to achieve my scrolling affect, I needed to use my old-school video game knowledge. Like the classic sidescrolling games, an infinite background affect can be created by arranging two identical rectangles horizontally and moving them each 100% across, looping so that the first appears to be the seamless next frame when it starts over.
To re-use my gradient on multiple shapes, I used a
<pattern> element and created two
<rect> elements. However, what I really wanted was a gradient at an angle to match the lines of the leaf. So, I had to tweak the classic sidescroll using
transform: rotate(-65) on my rectangles. Finally, I added my
<animate> element to the rectangles to change their
x value over the course of my chosen speed.
<pattern id="pattern" x="0" y="0" width="100%" height="100%"> <rect x="-150%" y="0" width="200%" height="100%" fill="url(#gradient)" transform="rotate(-65)"> <animate attributeType="XML" attributeName="x" from="-150%" to="50%" dur="6s" repeatCount="indefinite"/> </rect> <rect x="-350%" y="0" width="200%" height="100%" fill="url(#gradient)" transform="rotate(-65)"> <animate attributeType="XML" attributeName="x" from="-350%" to="-150%" dur="6s" repeatCount="indefinite"/> </rect> </pattern>
Because my rectangles are rotated, I had to play with the widths and x values to get them to fully cover the full diagonal distance. I’ll admit, this took quite a bit of trial and error. Learning!
Step 4: Fill the Leaf!
To use this new animating scrolling gradient pattern, I need to assign it as the
fill property on my logo path. Using the
id that I set on the
<pattern>, I can simply target it like a url (shortened for space):
Chrome has openly stated that their intention is to deprecate SMIL, although they are maintaining support in the mean time for those features that CSS animations do not yet provide.
We firmly believe that SMIL is not in the best long-term interests of the open web platform for several reasons: There is no clear path towards broad cross-browser support, The vendors which support SMIL have implementations that continue to vary widely, even after more than a decade of support, There are high-quality cross-platform replacement features on the horizon.
Despite those plans, currently SMIL is available in all modern browsers except Edge and Opera Mini. It’s up to you to decide whether the effect you’re going for is worth writing code that may be deprecated in the future. For a guide on alternative methods for SMIL features, check out this article from Sara Drasner on CSS Tricks.