Jump to content
Search Community

Triggering lottie animation on scroll

JPM82 test
Moderator Tag

Go to solution Solved by Cassie,

Recommended Posts

I'm trying to trigger some lottie animations using scroll trigger.  What I was hoping for is that the animations would trigger when coming into view, but when I look in the inspector it seems they are running constantly. 

The animations that are 'playOnce" I want to trigger when scrolled into view, but only once.  What am I missing in here?

//Regsiter Scroll Trigger

const animation = document.getElementsByClassName("animation");

Array.prototype.forEach.call(animation, icon => {
    let anim = bodymovin.loadAnimation({
        container: icon,
        path: icon.dataset.json,
        renderer: "svg",
        loop: true,
        class: "svg",
        autoplay: false

        trigger: animation,
        onEnter: anim.play(),
        onEnterBack: anim.play()

const playOnce = document.getElementsByClassName("animation--once");

Array.prototype.forEach.call(playOnce, once => {
    let onceAnim = bodymovin.loadAnimation({
        container: once,
        path: once.dataset.json,
        renderer: "svg",
        loop: false,
        class: "svg",
        autoplay: false

        trigger: playOnce,
        onEnter: onceAnim.play()


See the Pen MWBzvrm by jpaul1982 (@jpaul1982) on CodePen

Link to comment
Share on other sites

It looks like the animation is tied to the scroll position in this example.  I just want the animation to trigger when the scroll hits a certain point,  similar to the way it would in basic scroll trigger example. 

Link to comment
Share on other sites

Thank you, yes that helps.  However I'm thinking this may be a bit much for what I'm looking for.   I've added a basic reconstruction (albeit silly) of what I'm trying to achieve as a codepen.  

There are two different kinds of animations here: one that plays when the user scrolls in and out of the view port, and the other that play only once when coming into the viewport.  As it is right now, the playOnce animations to only play once, but they play as soon as the page loads, not onEnter.  The other animations are just playing all the time, not onEnter or onEnterBack.  

Does this help demonstrate what I'm going for?  

Link to comment
Share on other sites

Hey Cassie - yes that helps a ton!  I am having a little trouble understanding all of what's going on here (mostly in the LottieScrollTrigger function), but I think I can work with it.  Are there docs that explain it, or this a custom function?

Mainly, I would like my ".animation" lotties to loop while in the viewport.  I tried adding some parameters (loop: true/false) to the scrolltrigger like you did with the duration, but that didn't work.  I've updated my Codepen so you can see what I was trying to do there.   Is there a way to do that as well?

Either way this was extremely helpful.  Thank you so much!!

  • Like 1
Link to comment
Share on other sites

  • Solution

This is just a little helper function I'm afraid, no docs. I've added in an option to loop for you.

It'll be repeat though, not loop, because we're in scrollTrigger land, not Lottie land.

See the Pen LYBXejB by GreenSock (@GreenSock) on CodePen

Here's some notes

function LottieScrollTrigger(vars) {
  // this is grabbing all the stuff you pass through
  let playhead = { frame: 0 },
    target = gsap.utils.toArray(vars.target)[0],
    speeds = { slow: "+=2000", medium: "+=1000", fast: "+=500" },
    duration = vars.duration || 0.5, // I've added these for you
    repeat = vars.repeat || false, // I've added these for you
    // this is the scrollTrigger vars object
    st = {
      trigger: target,
      pin: true,
      start: "top top",
      end: speeds[vars.speed] || "+=1000",
      scrub: 1
    ctx = gsap.context && gsap.context(),
    // this is Lottie doing it's thing
    animation = lottie.loadAnimation({
      container: target,
      renderer: vars.renderer || "svg",
      loop: false,
      autoplay: false,
      path: vars.path,
      rendererSettings: vars.rendererSettings || {
        preserveAspectRatio: "xMidYMid slice"
  for (let p in vars) {
    // let users override the ScrollTrigger defaults
    st[p] = vars[p];
  // wait until the DOM is loaded
  animation.addEventListener("DOMLoaded", function () {
    // and make a tween to play the lottie animation using everything we passed through
    let createTween = function () {
      animation.frameTween = gsap.to(playhead, {
        frame: animation.totalFrames - 1,
        ease: "none",
        duration: duration, // they get used here
        repeat: repeat, // here you go!
        onUpdate: () => animation.goToAndStop(playhead.frame, true),
        scrollTrigger: st // this is the scrollTrigger stuff
      return () => animation.destroy && animation.destroy();
    // don't worry about this
    ctx && ctx.add ? ctx.add(createTween) : createTween();
    // in case there are any other ScrollTriggers on the page and the loading of this Lottie asset caused layout changes
  return animation;


  • Like 3
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...