If a case came up where the model had an SVG animation that performed one interaction and only one. It looked like this (some content has been removed):

If you are using a device with a small vertical view size, you may not have noticed the animation above. Unfortunately, the animations begin (and end!) Whether or not SVG is visible!

I wanted to combine the animations with the IntersectionObserver to make sure they just started animating. Here’s how I did it:

Edit SVG

I found all the cases <animate> or <animateTransform> and wired begin attributes so that the order of the animation can be arranged correctly internally. I want them all to start when my Bezier curve starts animating, so I added id animation (it had a problem with dashed lines id, so watch out for dashes):

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

Learn line / curve animation: CSS Tricks: How the SVG Line Animation Works

Take note begin the above feature, it will be relevant later.

Now I want to find other animations in my SVG that I want to start at the same time and change their animations begin attribute to use id from above a .begin terminal This starts this animation when the referenced animation starts. It looks like this:

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

Alternatively, you can use .end start this animation when the referenced animation ends.

(Side note: repeatCount="1" and fill="freeze" are best friends. fill="freeze" means that your animation does not rewind to the first box at the end)

Next, return to the original animation and more begin attribute indefinite (Read more at MDN: begin – SVG). This tells SVG not to start it until I use JavaScript to start it .beginElement().

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

(Second side note: I’m just thinking out loud as I write here – I’m wondering if I can use <noscript> Within SVG as a non-JS backup)

Add IntersectionObserver

It may look like this:

if ('IntersectionObserver' in window)  {
let elements = document.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) {
continue;
}


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


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

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

Try it for yourself

LEAVE A REPLY

Please enter your comment!
Please enter your name here