Kacper Faligowski
Kacper Faligowski

Reputation: 369

A function that execute once when scrollY is higher than 100vh

I want call my function once when the statement if (scrollY > 100vh), but on every scroll when I get more than 100vh is calling func. I understand the reason why is that, but don't know how to fix that.

Perhaps it is simple but I can't do that.

I want a simple animation on scrolling.

code :

import anime from 'animejs';

var txt = document.querySelector('.textanimation');
txt.innerHTML = txt.textContent.replace(
     /\S/g,
     "<span class='letter'>$&</span>"
);

window.addEventListener('scroll', () => {
     const vh = window.innerHeight;
     const scrolled = window.scrollTop;
     if (scrolled > vh) {
          const scrollTextAnimation = anime.timeline();
          scrollTextAnimation
               .add({
                    targets: '.textanimation .letter',
                    translateY: [-100, 0],
                    easing: 'easeOutExpo',
                    duration: 1400,
                    delay: (el, i) => 30 * i
               })
               .add({
                    targets: '.textanimation',
                    duration: 1000,
                    easing: 'easeOutExpo',
                    delay: 1000
               });
     }
});

Upvotes: 0

Views: 655

Answers (3)

j3py
j3py

Reputation: 1257

You can remove the event listener after your logic executes in order to stop it from ever firing again. You can do this in two ways:

1) Use the once option as defined in the parameters for addEventListener here. This option automatically removes the event listener after the event happens once. The OP has already stated this isn't working for them (possibly because the scroll needs to reach a certain height before the logic works so it is being removed too early).

2) Call removeEventListener after the logic executes:

import anime from 'animejs';

var txt = document.querySelector('.textanimation');
txt.innerHTML = txt.textContent.replace(
     /\S/g,
     "<span class='letter'>$&</span>"
);

var animateOnce = function() {
    const vh = window.innerHeight;
     const scrolled = window.scrollTop;
     if (scrolled > vh) {
          const scrollTextAnimation = anime.timeline();
          scrollTextAnimation
               .add({
                    targets: '.textanimation .letter',
                    translateY: [-100, 0],
                    easing: 'easeOutExpo',
                    duration: 1400,
                    delay: (el, i) => 30 * i
               })
               .add({
                    targets: '.textanimation',
                    duration: 1000,
                    easing: 'easeOutExpo',
                    delay: 1000
               });
         // remove the event listener after the animation happens on the first time
         window.removeEventListener('scroll', animateOnce);
     }
}

window.addEventListener('scroll', animateOnce);

3) Here are a couple of other solutions in a post on sitepoint.

Upvotes: 0

Kacper Faligowski
Kacper Faligowski

Reputation: 369

I just added a bool that change the statement to false when I make a scrollY more than innerHeight/2. "Once" option in addEventListener was not working, don't know why. Is there a better solution how to fix that? The code below is working:

let myBool = true;
window.addEventListener('scroll', () => {
     if (window.scrollY > window.innerHeight / 2 && myBool) {
          anime.timeline()
               .add({
                    targets: '.textanimation .letter',
                    translateY: [-100, 0],
                    easing: 'easeOutExpo',
                    duration: 1400,
                    delay: (el, i) => 30 * i
               })
               .add({
                    targets: '.textanimation',
                    duration: 1000,
                    easing: 'easeOutExpo',
                    delay: 1000
               });

          myBool = false;
     }
});

Upvotes: 1

Abdelmonaem Shahat
Abdelmonaem Shahat

Reputation: 544

just add once option to the event listener to execute it one time.

window.addEventListener('scroll', () => {
     const vh = window.innerHeight;
     const scrolled = window.scrollTop;
     if (scrolled > vh) {
          const scrollTextAnimation = anime.timeline();
          scrollTextAnimation
               .add({
                    targets: '.textanimation .letter',
                    translateY: [-100, 0],
                    easing: 'easeOutExpo',
                    duration: 1400,
                    delay: (el, i) => 30 * i
               })
               .add({
                    targets: '.textanimation',
                    duration: 1000,
                    easing: 'easeOutExpo',
                    delay: 1000
               });
     }
}, {once: true});

Upvotes: 1

Related Questions