Control Lottie via Javascript?

Is it possible to control the play / pause / stop of a Lottie animation via Javascript calls? I understand that I can use IX2, but there are a few instances where I want an animation to be able to loop until a stop command has been issued, or where I want to trigger the start of a Lottie animation when my modal visibility changes, which is triggered through a javascript call.

I can’t use the IX2 for “scroll into view” because my modals are always in view, though hidden, since I’m using absolute positioning. In some instances I use IX2 triggers, but only when I don’t need the animations to loop indefinitely until the modal is closed.

I have other instances where I am controlling html5 video content

Hey Jon! Welcome!

Can you explain what you want to achieve in detail?
There are lots of posts here with discussions on how to hook into the animation engine, if I understand your use-case we might find a starting point…

can you provide a preview link also?

Kind regards

Here’s a read-only link to the project: (Ignore the home page, the Agency-Evolved page is the work in question)

https://preview.webflow.com/preview/totemdesign?utm_medium=preview_link&utm_source=designer&utm_content=totemdesign&preview=2cd9e9c3c837ebe9d16df3f9f1e94cea&pageId=6125315f4ca0d8a22eeea335&workflow=preview

Note: Since the cards/modals are controlled via javascript it will only work on the published site which you can see here: https://totemdesign.webflow.io/agency-evolved

The floating cards each open a modal panel when clicked. There are a dozen cards/modals so I am using a javascript function to show/hide the visibility of the target modal when a card is clicked. Some of the modals display a video that is paused until the modal is opened, and then pauses again when closed so that it isn’t using too many CPU resources (e.g. Three Year Anniversary card). As you can see we have a lot of video and lottie animations on the page, so I’m trying to do my best to conserve the CPU.

The lottie animations on the cards don’t play until they are scrolled into view, which is great. I am also using IX2 to start playback on the Lottie animations on the modals when they are opened (e.g. Process Approach card), but that only works if I want to the animation to play once (since the lottie playback is triggered by clicking the card).

In many cases I want the lottie to loop until the card is closed, and then it should stop or pause playback (e.g. Our Story So Far card). The issue is that I am using Javascript to close the modal via the close button, clicking off the modal, or hitting escape. So I can’t find a great way to use IX2 to stop the lottie playback if I have it looping.

I hope that helps explain the situation. I am thinking perhaps I can create a global modal class for lotties that are used on the modals, and then apply an IX2 click interaction to the close button and lightbox dimmer classes that acts on all lotties with that class, and set the lottie to 0%. I’m just not sure how to also trap the Esc button to stop the animations as well.

Thanks in advance for taking a look at this. I searched the forums for lottie controls but only came across the aspectratio fix.

Okay Jon!
I think I found a way to do what you want to achieve.

Here’s how to programmatically pause and play your lotties ON the cards depending if they are visible or not.


Just FYI:

First you need a way to access the lottie library since it’s bundled inside the WF internals.

This code will reinitialize the lottie library to a globally scoped variable, which you can directly access:

const lottie = Webflow.require('lottie').lottie;

Now you can get all previously registered animations with this line

const animations = lottie.getRegisteredAnimations();

I found this snippet from @Jarek, which waits for the .jsons files to be loaded and parsed. I have modified it to work with your use-case.
Place this code possibly where you have your other jquery code (at the end of the body):

<script>
	var lottie, animations
  
	// Return a promise that resolves to true once animation is loaded
	async function animationLoaded(animation) {
		if(animation.isLoaded) {
			return true
		}

		return new Promise((resolve, reject) => {
			animation.addEventListener('DOMLoaded', () => {
				resolve(true)
			})
		})
	}

	// Return a promise that resolves to true once all animations are loaded
	async function waitForAnimationsLoaded(animations) {
		await Promise.all(animations.map(animationLoaded))
	}

	async function initAnimations() {
		lottie = Webflow.require('lottie').lottie
		animations = lottie.getRegisteredAnimations()
		await waitForAnimationsLoaded(animations)
	}

	var Webflow = Webflow || []

	Webflow.push(() => {
		initAnimations()
			.then(() => {
				console.log('Initialized animations')
				// hide splash screen
			})
			.catch((error) => {
				console.error(error)
			})
	})
</script>

You can now use lotties global methods like lottie.freeze() on the global scope!

If you take a look at the contents of animations you will see an array of all animations lottie found on your site:

You can target specific animations via animations[X].isPaused = true to pause them or unpause them with false.

If you hardcode the indexes of the animationItems and later on insert a new lottie somewhere, be aware, this WILL mess with the targeting.

Usually one could directly target each animation controls by setting the custom attribute data-name on the lottie element in the WF designer, however - this doesn’t work for me.

You can give individual animations a name, still:

animations[X].name = 'NAME'
// and then
lottie.stop('NAME')
// OR
lottie.play('NAME')

Have a look at the properties and methods of either the lottie object (e.g. addressing all animations) or the individual animation object. They have different intents and purposes!

BUTT, HERE’S THE CATCH

All these things ONLY work on lottie elements that DO NOT have additional interactions set, like scroll into view etc…

As soon as you add your own interactions on the lottie element in the designer, this will not work anymore. The interactions simply override the reinitiated behaviour we have set here. I didn’t look into the internals too much, so I’m not sure.

If you need functionality like scroll into view, etc. you could however resort back to implementing your own intersectionObserver via the browsers API.

I hope this helps you a bit, feel free to ask if you get stuck!

11 Likes

@RDaneelOliwav

Using your code, I was able to give the moment when the lottie animation would stop, via data attribute named data-lottie-percent:

https://lottie-animation-example-2cd7a9.webflow.io/

Thank you very much.