6

The updated anime.js documentation (Controls->Seek) says that you can control the animation while scrolling, but there is no example.

Could anyone give an example of how to set up animation.seek?

https://animejs.com/documentation/#seekAnim

var animation = anime({
  targets: '.seek-anim-demo .el',
  translateX: 270,
  delay: function(el, i) { return i * 100; },
  elasticity: 200,
  easing: 'easeInOutSine',
  autoplay: false
});

var seekProgressEl = document.querySelector('.seek-anim-demo .progress');
seekProgressEl.oninput = function() {
  animation.seek(animation.duration * (seekProgressEl.value / 100));
};
Alex Chebotarsky
  • 481
  • 5
  • 19
Alessio Paoletti
  • 91
  • 1
  • 1
  • 8

4 Answers4

7

This is what you're looking for.

JavaScript:

function getScrollPercent() {
   var h = document.documentElement,
   b = document.body,
   st = 'scrollTop',
   sh = 'scrollHeight';
   return (h[st] || b[st]) / ((h[sh] || b[sh]) - h.clientHeight) * 100;
 }
 const
 // parent = document.querySelector('.outerHeight'),
 els = document.querySelectorAll('.el'),
 tl = anime.timeline({ autoplay: false });
    
 _.map(els, el => {
   anime.set(el, {
     top: anime.random(0, 150) + 'vh',
     left: anime.random(0, 100) + 'vw' });
    
   tl.add({
     targets: el,
     translateX: anime.random(-500, 500) + '%',
     translateY: anime.random(-500, 500) + '%',
     scale: anime.random(0.3, 1.7),
     rotate: anime.random(-365, 365) + 'deg',
     duration: anime.random(500, 5000), easing: 'easeInOutCirc' },
   0);
 });
    
 // new AnimePlayer({ add: tl })
    
 window.addEventListener('scroll', () => {
   const persentage = getScrollPercent();
   tl.seek(tl.duration * (persentage * 0.01));
});

Source: Codepen (https://codepen.io/gaougalos/pen/bJXYZa)

Community
  • 1
  • 1
Adil Aijaz
  • 71
  • 1
  • 3
  • Thank you very much for your example. Do you know if there is any way to add a damping/smoothing effect? For example, that way the animation does not stop abruptly when the scrolling stops: https://university.webflow.com/article/interpolation-easing-smoothing – mr1031011 Jul 08 '20 at 05:27
  • @mr1031011 No, I don't know, and I think it can't be done without huge tweaking because you want to add easing to scrolling whereas AnimeJS offers easing to targets (timeline animation). – Adil Aijaz Jul 12 '20 at 13:08
  • I kind of made it work, for anyone that is interested, you can check more here: https://github.com/juliangarnier/anime/issues/703 – mr1031011 Jul 13 '20 at 01:35
  • I just want to say thank you, for mentioning that it is "easing to the scrolling". You are absolutely right, the easing must be applied to the trigger of the seek function instead of the seek itself. That was an aha moment when I read your comment. – mr1031011 Jul 15 '20 at 12:28
3

Finally I have found a solution with seek and using intersection observer to trigger and control animations.

but the only problem it's that entry.boundingClientRect don't track all progress but only entry or leave of trigger:

    let observer_imgs_parallax;
    let Element_imgs_parallax;

    let prevRatio = 0.0;
    let options_parallax = {
        root: null,
        rootMargin: '0px',
        threshold: buildThresholdList() //se parallax
    };

    // Set things up
        Element_imgs_parallax = document.querySelector('.trigger-parallax-fake');
        initObserver_parallax();

    //////////////////////////////////////////////////////////////////////////////

    function initObserver_parallax() {
        observer_imgs_parallax = new IntersectionObserver(callback_imgs_parallax, options_parallax);
        observer_imgs_parallax.observe(Element_imgs_parallax);
    }

    /////////////////////////////////////////////////////////////////////////////

    function buildThresholdList() {
    let thresholds = [];
    let numSteps = 200;
    for (let i=1.0; i<=numSteps; i++) {
        let ratio = i/numSteps;
        thresholds.push(ratio);
    }
    thresholds.push(0);
    return thresholds;
    }

    /////////////////////////////////////////////////////////////////////////////


    var animazione_parallax = anime ({
        targets: '.immagini-parallax img',
        translateY: ['15%','-15%'],
        easing: 'easeInOutSine',
        duration: 1000,
        autoplay: false
    });


    ////////////////////////////////////////////////////////////////////////////


    //animazione parallax
    function callback_imgs_parallax (entries, observer_imgs_parallax) {
    entries.forEach((entry) => {
    if(entry.boundingClientRect.top < 0){ //osservazione elemento da top

        animazione_parallax.seek(animazione_parallax.duration * (entry.intersectionRatio)); //parallax

    }else{ animazione_parallax.seek(1000);} //posizione dopo il passaggio
    prevRatio = entry.intersectionRatio; //rimuove se non parallax
    });
    }

Every animation in my site now are triggered or controlled with intersection observer and made with anime.js

link: https://alessiopaolettidesign.it

Kalitsune
  • 75
  • 1
  • 6
Alessio Paoletti
  • 91
  • 1
  • 1
  • 8
0

For this animation control no need scroll bar, no need any page offset. Animation control depending on its progress in both directions

    let a;
let tl = anime({
 targets: '.element',
 translateX: 250,
 duration: 3000,
 easing: 'linear',
 delay: 500,
 autoplay: false,
 update: function (anim) {
      a = tl.progress;
      console.log(a);
 }
});
   let PathProgress = 0;
   let change = true;
   window.addEventListener('wheel', () => {
 if (change) {
      PathProgress += 2;
      console.log(PathProgress);
      tl.seek(tl.duration * (PathProgress / 100));
      if (PathProgress === 100) {
           change = false;
      }
 } else {
      PathProgress -= 2;
      console.log(PathProgress);
      tl.seek(tl.duration * (PathProgress / 100));
      if (PathProgress === 0) {
           change = true;
      }
 }
 })
Lighty
  • 11
  • 1
-1

Here is how you can control an animation when an element you choose shows up. https://codepen.io/straktormedia/pen/wvyRErr

// Animation
const animation = anime({
  targets: ".text-animate",
  translateX: 800,
  duration: 4000,
  autoplay: false,
});

const section2 = document.querySelector(".section-2");

// Animate on scroll
const animateOnScroll = function (div, speed = 100, offset = 0) {
  const scrollPercent = window.pageYOffset - div.offsetTop;
  return (scrollPercent + offset) / speed;
};

// Scroll listener
window.onscroll = function () {
  animation.seek(animateOnScroll(section2, 1000, 200) * animation.duration);
};

I made a YouTube video for it in case it gets confusing: https://www.youtube.com/watch?v=f_gozrMnD7I

Straktor
  • 9
  • 2