106 lines
4.0 KiB
JavaScript
106 lines
4.0 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.$value.animateOnLoad ? this.enter() : (this.$el.style.opacity = '');
|
|
}
|
|
|
|
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;
|