+201223538180

Web site Developer I Advertising and marketing I Social Media Advertising and marketing I Content material Creators I Branding Creators I Administration I System SolutionFire SVG animations (SMIL) when the SVG is seen—zachleat.com

Web site Developer I Advertising and marketing I Social Media Advertising and marketing I Content material Creators I Branding Creators I Administration I System SolutionFire SVG animations (SMIL) when the SVG is seen—zachleat.com

Web site Developer I Advertising and marketing I Social Media Advertising and marketing I Content material Creators I Branding Creators I Administration I System Answer

Had a use case are available in the place the design had an SVG animation that ran one interation and just one. It appeared like this (some content material has been eliminated):

In the event you’re on a tool with a small vertical viewport dimension, you could not have seen the above animation. Sadly the animations begin (and full!) whether or not or not the SVG is seen!

I needed to wire the animations as much as IntersectionObserver to verify they solely began animating when seen. Right here’s how I did it:

Modify the SVG

I discovered all the situations of <animate> or <animateTransform> and wired up the start attributes to correctly cascade the order of the animation internally. I need all of them to begin when my bezier curve begins animating, so I added an id to that animation (there was a difficulty with dashes in that id, so beware utilizing dashes):

<animate
id="mysvgline"
attributeType="xml"
attributeName="stroke-dashoffset"
from="500"
to="0"
dur=".8s"
start="0s"
/>

Discover ways to animate a line/curve: css’s AvatarCSS Tips: How SVG Line Animation Works

Pay attention to the start attribute above, that will likely be necessary later.

Now I need to discover the opposite animations in my SVG that I need to begin on the similar time and alter their start attribute to make use of the id from above with a .start suffix. This begins this animation when the referenced animation begins. It seems like this:

<animateMotion
start="mysvgline.start"
dur=".8s"
repeatCount="1"
fill="freeze"
path="M35.5 20C216.281 20 352.411 182 512.5 182"
/>

Alternatively, you should use .finish to begin this animation when the referenced animation ends.

(Facet be aware: repeatCount="1" and fill="freeze" are finest buddies. fill="freeze" signifies that your animation gained’t rewind to the primary body on the finish)

Subsequent return to the unique animation and alter the start attribute to indefinite (Learn extra at MDN: start – SVG). This tells the SVG to not begin it till I take advantage of JavaScript to set off it utilizing .beginElement().

<animate
id="mysvgline"
attributeType="xml"
attributeName="stroke-dashoffset"
from="500"
to="0"
dur=".8s"
start="indefinite"
/>

(One other facet be aware: simply pondering aloud right here as I write this—I’m wondering if I can use <noscript> within SVG as a no-JS fallback)

Add the IntersectionObserver

It would seem like this:

if ('IntersectionObserver' in window)  {
let parts = doc.querySelectorAll("svg");

let observer = new IntersectionObserver(entries => {
let mediaQuery = window.matchMedia('(prefers-reduced-motion: no-preference)');
if(!mediaQuery.matches) {
return;
}

for(let entry of entries) {
if(!entry.isIntersecting) {
proceed;
}


let beginElements = entry.goal.querySelectorAll(`:scope [begin="indefinite"]`);
for(let beginEl of beginElements) {
beginEl.beginElement();


observer.unobserve(entry.goal);
}
}
},
{
threshold: .5
});

for(let elem of parts) {
observer.observe(elem);
}
}

Attempt it your self

Supply hyperlink

Leave a Reply