primevue-mirror/components/lib/animateonscroll/AnimateOnScroll.js

106 lines
3.9 KiB
JavaScript

import { DomHandler } from 'primevue/utils';
import BaseAnimateOnScroll from './BaseAnimateOnScroll';
const AnimateOnScroll = BaseAnimateOnScroll.extend('animateonscroll', {
created() {
this.$value = this.$value || {};
this.$el.style.opacity = this.$value.enterClass ? '0' : '';
},
mounted() {
this.$el.setAttribute('data-pd-animateonscroll', true);
this.bindIntersectionObserver();
},
unmounted() {
this.unbindAnimationEvents();
this.unbindIntersectionObserver();
},
observer: undefined,
resetObserver: undefined,
isObserverActive: false,
animationState: undefined,
animationEndListener: undefined,
methods: {
bindAnimationEvents() {
if (!this.animationEndListener) {
this.animationEndListener = () => {
DomHandler.removeMultipleClasses(this.$el, [this.$value.enterClass, this.$value.leaveClass]);
!this.$modifiers.once && this.resetObserver.observe(this.$el);
this.unbindAnimationEvents();
};
this.$el.addEventListener('animationend', this.animationEndListener);
}
},
bindIntersectionObserver() {
const { root, rootMargin, threshold = 0.5 } = this.$value;
const options = { root, rootMargin, threshold };
// States
this.observer = new IntersectionObserver(([entry]) => {
if (this.isObserverActive) {
if (entry.boundingClientRect.top > 0) {
entry.isIntersecting ? this.enter() : this.leave();
}
} else if (entry.isIntersecting) {
this.enter();
}
this.isObserverActive = true;
}, options);
setTimeout(() => this.observer.observe(this.$el), 0);
// Reset
this.resetObserver = new IntersectionObserver(
([entry]) => {
if (entry.boundingClientRect.top > 0 && !entry.isIntersecting) {
this.$el.style.opacity = this.$value.enterClass ? '0' : '';
DomHandler.removeMultipleClasses(this.$el, [this.$value.enterClass, this.$value.leaveClass]);
this.resetObserver.unobserve(this.$el);
}
this.animationState = undefined;
},
{ ...options, threshold: 0 }
);
},
enter() {
if (this.animationState !== 'enter' && this.$value.enterClass) {
this.$el.style.opacity = '';
DomHandler.removeMultipleClasses(this.$el, this.$value.leaveClass);
DomHandler.addMultipleClasses(this.$el, this.$value.enterClass);
this.$modifiers.once && this.unbindIntersectionObserver(this.$el);
this.bindAnimationEvents();
this.animationState = 'enter';
}
},
leave() {
if (this.animationState !== 'leave' && this.$value.leaveClass) {
this.$el.style.opacity = this.$value.enterClass ? '0' : '';
DomHandler.removeMultipleClasses(this.$el, this.$value.enterClass);
DomHandler.addMultipleClasses(this.$el, this.$value.leaveClass);
this.bindAnimationEvents();
this.animationState = 'leave';
}
},
unbindAnimationEvents() {
if (this.animationEndListener) {
this.$el.removeEventListener('animationend', this.animationEndListener);
this.animationEndListener = undefined;
}
},
unbindIntersectionObserver() {
this.observer?.unobserve(this.$el);
this.resetObserver?.unobserve(this.$el);
this.isObserverActive = false;
}
}
});
export default AnimateOnScroll;