fix: Gitea Traefik routing and connection pool optimization
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
- Remove middleware reference from Gitea Traefik labels (caused routing issues) - Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s) - Add explicit service reference in Traefik labels - Fix intermittent 504 timeouts by improving PostgreSQL connection handling Fixes Gitea unreachability via git.michaelschiemer.de
This commit is contained in:
302
resources/js/modules/animation-system/AnimationSystem.js
Normal file
302
resources/js/modules/animation-system/AnimationSystem.js
Normal file
@@ -0,0 +1,302 @@
|
||||
/**
|
||||
* Unified Animation System
|
||||
*
|
||||
* Consolidates all scroll animation modules into a single, unified system.
|
||||
* Replaces: scrollfx, parallax, scroll-timeline, scroll-loop, scroll-dependent, sticky-fade, sticky-steps
|
||||
*/
|
||||
|
||||
import { Logger } from '../../core/logger.js';
|
||||
import { ScrollAnimation } from './ScrollAnimation.js';
|
||||
import { TimelineAnimation } from './TimelineAnimation.js';
|
||||
|
||||
/**
|
||||
* AnimationSystem - Unified animation system
|
||||
*/
|
||||
export class AnimationSystem {
|
||||
constructor(config = {}) {
|
||||
this.config = {
|
||||
enabled: config.enabled ?? true,
|
||||
useIntersectionObserver: config.useIntersectionObserver ?? true,
|
||||
throttleDelay: config.throttleDelay || 16, // ~60fps
|
||||
...config
|
||||
};
|
||||
|
||||
this.animations = new Map(); // Map<element, Animation>
|
||||
this.observers = new Map(); // Map<element, IntersectionObserver>
|
||||
this.scrollHandler = null;
|
||||
this.isScrolling = false;
|
||||
|
||||
// Initialize
|
||||
if (this.config.enabled) {
|
||||
this.init();
|
||||
}
|
||||
|
||||
Logger.info('[AnimationSystem] Initialized', {
|
||||
enabled: this.config.enabled,
|
||||
useIntersectionObserver: this.config.useIntersectionObserver
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new AnimationSystem instance
|
||||
*/
|
||||
static create(config = {}) {
|
||||
return new AnimationSystem(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize animation system
|
||||
*/
|
||||
init() {
|
||||
// Set up scroll handler
|
||||
if (!this.config.useIntersectionObserver) {
|
||||
this.setupScrollHandler();
|
||||
}
|
||||
|
||||
// Auto-initialize elements with data attributes
|
||||
this.autoInitialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up scroll handler
|
||||
*/
|
||||
setupScrollHandler() {
|
||||
let ticking = false;
|
||||
|
||||
this.scrollHandler = () => {
|
||||
if (!ticking) {
|
||||
window.requestAnimationFrame(() => {
|
||||
this.updateAnimations();
|
||||
ticking = false;
|
||||
});
|
||||
ticking = true;
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('scroll', this.scrollHandler, { passive: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto-initialize elements with data attributes
|
||||
*/
|
||||
autoInitialize() {
|
||||
// Fade in on scroll (scrollfx)
|
||||
this.initializeFadeIn();
|
||||
|
||||
// Parallax
|
||||
this.initializeParallax();
|
||||
|
||||
// Scroll timeline
|
||||
this.initializeTimeline();
|
||||
|
||||
// Sticky fade
|
||||
this.initializeStickyFade();
|
||||
|
||||
// Sticky steps
|
||||
this.initializeStickySteps();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize fade-in animations (scrollfx)
|
||||
*/
|
||||
initializeFadeIn() {
|
||||
const elements = document.querySelectorAll('.fade-in-on-scroll, .zoom-in, [data-animate="fade-in"]');
|
||||
elements.forEach(element => {
|
||||
this.registerAnimation(element, {
|
||||
type: 'fade-in',
|
||||
offset: parseFloat(element.dataset.offset) || 0.85,
|
||||
delay: parseFloat(element.dataset.delay) || 0,
|
||||
once: element.dataset.once !== 'false'
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize parallax animations
|
||||
*/
|
||||
initializeParallax() {
|
||||
const elements = document.querySelectorAll('[data-parallax], .parallax');
|
||||
elements.forEach(element => {
|
||||
const speed = parseFloat(element.dataset.parallax || element.dataset.speed) || 0.5;
|
||||
this.registerAnimation(element, {
|
||||
type: 'parallax',
|
||||
speed
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize timeline animations (scroll-timeline)
|
||||
*/
|
||||
initializeTimeline() {
|
||||
const elements = document.querySelectorAll('[data-scroll-timeline], [data-scroll-step]');
|
||||
elements.forEach(element => {
|
||||
this.registerAnimation(element, {
|
||||
type: 'timeline',
|
||||
steps: element.dataset.scrollSteps ? parseInt(element.dataset.scrollSteps) : null,
|
||||
triggerPoint: parseFloat(element.dataset.triggerPoint) || 0.4
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize sticky fade animations
|
||||
*/
|
||||
initializeStickyFade() {
|
||||
const elements = document.querySelectorAll('[data-sticky-fade], .sticky-fade');
|
||||
elements.forEach(element => {
|
||||
this.registerAnimation(element, {
|
||||
type: 'sticky-fade',
|
||||
fadeStart: parseFloat(element.dataset.fadeStart) || 0,
|
||||
fadeEnd: parseFloat(element.dataset.fadeEnd) || 1
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize sticky steps animations
|
||||
*/
|
||||
initializeStickySteps() {
|
||||
const elements = document.querySelectorAll('[data-sticky-steps], .sticky-steps');
|
||||
elements.forEach(element => {
|
||||
const steps = element.dataset.stickySteps ? parseInt(element.dataset.stickySteps) : 3;
|
||||
this.registerAnimation(element, {
|
||||
type: 'sticky-steps',
|
||||
steps
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an animation
|
||||
*/
|
||||
registerAnimation(element, config) {
|
||||
if (this.animations.has(element)) {
|
||||
Logger.warn('[AnimationSystem] Animation already registered for element', element);
|
||||
return;
|
||||
}
|
||||
|
||||
let animation;
|
||||
|
||||
switch (config.type) {
|
||||
case 'fade-in':
|
||||
case 'zoom-in':
|
||||
animation = new ScrollAnimation(element, {
|
||||
type: config.type,
|
||||
offset: config.offset || 0.85,
|
||||
delay: config.delay || 0,
|
||||
once: config.once !== false
|
||||
});
|
||||
break;
|
||||
|
||||
case 'parallax':
|
||||
animation = new ScrollAnimation(element, {
|
||||
type: 'parallax',
|
||||
speed: config.speed || 0.5
|
||||
});
|
||||
break;
|
||||
|
||||
case 'timeline':
|
||||
animation = new TimelineAnimation(element, {
|
||||
steps: config.steps,
|
||||
triggerPoint: config.triggerPoint || 0.4
|
||||
});
|
||||
break;
|
||||
|
||||
case 'sticky-fade':
|
||||
animation = new ScrollAnimation(element, {
|
||||
type: 'sticky-fade',
|
||||
fadeStart: config.fadeStart || 0,
|
||||
fadeEnd: config.fadeEnd || 1
|
||||
});
|
||||
break;
|
||||
|
||||
case 'sticky-steps':
|
||||
animation = new ScrollAnimation(element, {
|
||||
type: 'sticky-steps',
|
||||
steps: config.steps || 3
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
Logger.warn('[AnimationSystem] Unknown animation type', config.type);
|
||||
return;
|
||||
}
|
||||
|
||||
this.animations.set(element, animation);
|
||||
|
||||
// Set up observer if using IntersectionObserver
|
||||
if (this.config.useIntersectionObserver) {
|
||||
this.setupObserver(element, animation);
|
||||
}
|
||||
|
||||
Logger.debug('[AnimationSystem] Animation registered', { element, type: config.type });
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up IntersectionObserver for element
|
||||
*/
|
||||
setupObserver(element, animation) {
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
animation.enter();
|
||||
} else if (!animation.config.once) {
|
||||
animation.exit();
|
||||
}
|
||||
});
|
||||
}, {
|
||||
threshold: animation.config.offset || 0.85,
|
||||
rootMargin: '0px'
|
||||
});
|
||||
|
||||
observer.observe(element);
|
||||
this.observers.set(element, observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update all animations (for scroll-based updates)
|
||||
*/
|
||||
updateAnimations() {
|
||||
this.animations.forEach((animation, element) => {
|
||||
if (animation.needsUpdate) {
|
||||
animation.update();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove animation
|
||||
*/
|
||||
removeAnimation(element) {
|
||||
const animation = this.animations.get(element);
|
||||
if (animation) {
|
||||
animation.destroy();
|
||||
this.animations.delete(element);
|
||||
}
|
||||
|
||||
const observer = this.observers.get(element);
|
||||
if (observer) {
|
||||
observer.disconnect();
|
||||
this.observers.delete(element);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy animation system
|
||||
*/
|
||||
destroy() {
|
||||
// Remove all animations
|
||||
this.animations.forEach((animation, element) => {
|
||||
this.removeAnimation(element);
|
||||
});
|
||||
|
||||
// Remove scroll handler
|
||||
if (this.scrollHandler) {
|
||||
window.removeEventListener('scroll', this.scrollHandler);
|
||||
}
|
||||
|
||||
Logger.info('[AnimationSystem] Destroyed');
|
||||
}
|
||||
}
|
||||
|
||||
211
resources/js/modules/animation-system/ScrollAnimation.js
Normal file
211
resources/js/modules/animation-system/ScrollAnimation.js
Normal file
@@ -0,0 +1,211 @@
|
||||
/**
|
||||
* Scroll Animation
|
||||
*
|
||||
* Handles various scroll-based animations: fade-in, zoom-in, parallax, sticky-fade, sticky-steps
|
||||
*/
|
||||
|
||||
import { Logger } from '../../core/logger.js';
|
||||
|
||||
/**
|
||||
* ScrollAnimation - Individual scroll animation
|
||||
*/
|
||||
export class ScrollAnimation {
|
||||
constructor(element, config = {}) {
|
||||
this.element = element;
|
||||
this.config = {
|
||||
type: config.type || 'fade-in',
|
||||
offset: config.offset || 0.85,
|
||||
delay: config.delay || 0,
|
||||
once: config.once !== false,
|
||||
speed: config.speed || 0.5,
|
||||
fadeStart: config.fadeStart || 0,
|
||||
fadeEnd: config.fadeEnd || 1,
|
||||
steps: config.steps || 3,
|
||||
...config
|
||||
};
|
||||
|
||||
this.triggered = false;
|
||||
this.needsUpdate = true;
|
||||
|
||||
// Initialize based on type
|
||||
this.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize animation
|
||||
*/
|
||||
init() {
|
||||
switch (this.config.type) {
|
||||
case 'fade-in':
|
||||
case 'zoom-in':
|
||||
this.initFadeIn();
|
||||
break;
|
||||
case 'parallax':
|
||||
this.initParallax();
|
||||
break;
|
||||
case 'sticky-fade':
|
||||
this.initStickyFade();
|
||||
break;
|
||||
case 'sticky-steps':
|
||||
this.initStickySteps();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize fade-in animation
|
||||
*/
|
||||
initFadeIn() {
|
||||
this.element.style.opacity = '0';
|
||||
this.element.style.transition = `opacity 0.6s ease, transform 0.6s ease`;
|
||||
this.element.style.transitionDelay = `${this.config.delay}s`;
|
||||
|
||||
if (this.config.type === 'zoom-in') {
|
||||
this.element.style.transform = 'scale(0.9)';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize parallax animation
|
||||
*/
|
||||
initParallax() {
|
||||
// Parallax doesn't need initial setup
|
||||
this.needsUpdate = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize sticky fade animation
|
||||
*/
|
||||
initStickyFade() {
|
||||
this.element.style.position = 'sticky';
|
||||
this.element.style.top = '0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize sticky steps animation
|
||||
*/
|
||||
initStickySteps() {
|
||||
this.element.style.position = 'sticky';
|
||||
this.element.style.top = '0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter animation (element enters viewport)
|
||||
*/
|
||||
enter() {
|
||||
if (this.triggered && this.config.once) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.triggered = true;
|
||||
|
||||
switch (this.config.type) {
|
||||
case 'fade-in':
|
||||
this.element.style.opacity = '1';
|
||||
this.element.classList.add('visible', 'entered');
|
||||
break;
|
||||
case 'zoom-in':
|
||||
this.element.style.opacity = '1';
|
||||
this.element.style.transform = 'scale(1)';
|
||||
this.element.classList.add('visible', 'entered');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit animation (element exits viewport)
|
||||
*/
|
||||
exit() {
|
||||
if (this.config.once) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.triggered = false;
|
||||
|
||||
switch (this.config.type) {
|
||||
case 'fade-in':
|
||||
this.element.style.opacity = '0';
|
||||
this.element.classList.remove('visible', 'entered');
|
||||
break;
|
||||
case 'zoom-in':
|
||||
this.element.style.opacity = '0';
|
||||
this.element.style.transform = 'scale(0.9)';
|
||||
this.element.classList.remove('visible', 'entered');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update animation (for scroll-based animations)
|
||||
*/
|
||||
update() {
|
||||
const rect = this.element.getBoundingClientRect();
|
||||
const viewportHeight = window.innerHeight;
|
||||
const scrollY = window.scrollY;
|
||||
|
||||
switch (this.config.type) {
|
||||
case 'parallax':
|
||||
this.updateParallax(rect, scrollY);
|
||||
break;
|
||||
case 'sticky-fade':
|
||||
this.updateStickyFade(rect, viewportHeight);
|
||||
break;
|
||||
case 'sticky-steps':
|
||||
this.updateStickySteps(rect, viewportHeight, scrollY);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update parallax animation
|
||||
*/
|
||||
updateParallax(rect, scrollY) {
|
||||
const elementTop = rect.top + scrollY;
|
||||
const scrolled = scrollY - elementTop;
|
||||
const translateY = scrolled * this.config.speed;
|
||||
|
||||
this.element.style.transform = `translateY(${translateY}px)`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update sticky fade animation
|
||||
*/
|
||||
updateStickyFade(rect, viewportHeight) {
|
||||
const progress = Math.max(0, Math.min(1, (viewportHeight - rect.top) / viewportHeight));
|
||||
const opacity = this.config.fadeStart + (this.config.fadeEnd - this.config.fadeStart) * progress;
|
||||
|
||||
this.element.style.opacity = opacity.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update sticky steps animation
|
||||
*/
|
||||
updateStickySteps(rect, viewportHeight, scrollY) {
|
||||
const elementTop = rect.top + scrollY - viewportHeight;
|
||||
const scrollProgress = Math.max(0, Math.min(1, scrollY / (rect.height + viewportHeight)));
|
||||
const step = Math.floor(scrollProgress * this.config.steps);
|
||||
|
||||
this.element.setAttribute('data-step', step.toString());
|
||||
this.element.classList.remove('step-0', 'step-1', 'step-2', 'step-3', 'step-4', 'step-5');
|
||||
this.element.classList.add(`step-${step}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy animation
|
||||
*/
|
||||
destroy() {
|
||||
// Reset styles
|
||||
this.element.style.opacity = '';
|
||||
this.element.style.transform = '';
|
||||
this.element.style.transition = '';
|
||||
this.element.style.transitionDelay = '';
|
||||
this.element.style.position = '';
|
||||
this.element.style.top = '';
|
||||
|
||||
// Remove classes
|
||||
this.element.classList.remove('visible', 'entered');
|
||||
|
||||
this.triggered = false;
|
||||
}
|
||||
}
|
||||
|
||||
157
resources/js/modules/animation-system/TimelineAnimation.js
Normal file
157
resources/js/modules/animation-system/TimelineAnimation.js
Normal file
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
* Timeline Animation
|
||||
*
|
||||
* Handles scroll timeline animations (scroll-timeline, scroll-loop)
|
||||
*/
|
||||
|
||||
import { Logger } from '../../core/logger.js';
|
||||
|
||||
/**
|
||||
* TimelineAnimation - Scroll timeline animation
|
||||
*/
|
||||
export class TimelineAnimation {
|
||||
constructor(element, config = {}) {
|
||||
this.element = element;
|
||||
this.config = {
|
||||
steps: config.steps || null,
|
||||
triggerPoint: config.triggerPoint || 0.4,
|
||||
loop: config.loop ?? false,
|
||||
...config
|
||||
};
|
||||
|
||||
this.currentStep = 0;
|
||||
this.triggered = false;
|
||||
|
||||
// Initialize
|
||||
this.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize timeline animation
|
||||
*/
|
||||
init() {
|
||||
// Set initial step
|
||||
this.element.setAttribute('data-scroll-step', '0');
|
||||
this.element.classList.add('scroll-timeline');
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter animation
|
||||
*/
|
||||
enter() {
|
||||
if (this.triggered && !this.config.loop) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.triggered = true;
|
||||
this.update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit animation
|
||||
*/
|
||||
exit() {
|
||||
if (this.config.loop) {
|
||||
this.currentStep = 0;
|
||||
this.update();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update animation based on scroll position
|
||||
*/
|
||||
update() {
|
||||
const rect = this.element.getBoundingClientRect();
|
||||
const viewportHeight = window.innerHeight;
|
||||
const triggerY = viewportHeight * this.config.triggerPoint;
|
||||
|
||||
if (rect.top < triggerY && rect.bottom > 0) {
|
||||
// Calculate progress
|
||||
const progress = Math.max(0, Math.min(1, (triggerY - rect.top) / (rect.height + viewportHeight)));
|
||||
|
||||
if (this.config.steps) {
|
||||
// Step-based animation
|
||||
const step = Math.floor(progress * this.config.steps);
|
||||
this.setStep(step);
|
||||
} else {
|
||||
// Continuous animation
|
||||
this.setProgress(progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set step
|
||||
*/
|
||||
setStep(step) {
|
||||
if (step === this.currentStep) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentStep = step;
|
||||
this.element.setAttribute('data-scroll-step', step.toString());
|
||||
|
||||
// Remove old step classes
|
||||
for (let i = 0; i <= this.config.steps; i++) {
|
||||
this.element.classList.remove(`step-${i}`);
|
||||
}
|
||||
|
||||
// Add new step class
|
||||
this.element.classList.add(`step-${step}`);
|
||||
|
||||
// Trigger event
|
||||
this.triggerStepEvent(step);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set progress (continuous)
|
||||
*/
|
||||
setProgress(progress) {
|
||||
this.element.setAttribute('data-scroll-progress', progress.toString());
|
||||
this.element.style.setProperty('--scroll-progress', progress.toString());
|
||||
|
||||
// Trigger event
|
||||
this.triggerProgressEvent(progress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger step event
|
||||
*/
|
||||
triggerStepEvent(step) {
|
||||
const event = new CustomEvent('scroll-timeline:step', {
|
||||
detail: { step, element: this.element },
|
||||
bubbles: true
|
||||
});
|
||||
this.element.dispatchEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger progress event
|
||||
*/
|
||||
triggerProgressEvent(progress) {
|
||||
const event = new CustomEvent('scroll-timeline:progress', {
|
||||
detail: { progress, element: this.element },
|
||||
bubbles: true
|
||||
});
|
||||
this.element.dispatchEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy animation
|
||||
*/
|
||||
destroy() {
|
||||
this.element.removeAttribute('data-scroll-step');
|
||||
this.element.removeAttribute('data-scroll-progress');
|
||||
this.element.style.removeProperty('--scroll-progress');
|
||||
this.element.classList.remove('scroll-timeline');
|
||||
|
||||
// Remove step classes
|
||||
for (let i = 0; i <= 10; i++) {
|
||||
this.element.classList.remove(`step-${i}`);
|
||||
}
|
||||
|
||||
this.currentStep = 0;
|
||||
this.triggered = false;
|
||||
}
|
||||
}
|
||||
|
||||
92
resources/js/modules/animation-system/index.js
Normal file
92
resources/js/modules/animation-system/index.js
Normal file
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* Animation System Module
|
||||
*
|
||||
* Unified animation system consolidating all scroll animation modules.
|
||||
*
|
||||
* Replaces:
|
||||
* - scrollfx
|
||||
* - parallax
|
||||
* - scroll-timeline
|
||||
* - scroll-loop
|
||||
* - scroll-dependent
|
||||
* - sticky-fade
|
||||
* - sticky-steps
|
||||
*
|
||||
* Usage:
|
||||
* - Add data-module="animation-system" to enable animations
|
||||
* - Or import and use directly: import { AnimationSystem } from './modules/animation-system/index.js'
|
||||
*
|
||||
* Features:
|
||||
* - Fade-in animations
|
||||
* - Parallax effects
|
||||
* - Scroll timeline animations
|
||||
* - Sticky fade animations
|
||||
* - Sticky steps animations
|
||||
* - IntersectionObserver support
|
||||
* - Backward compatibility with old modules
|
||||
*/
|
||||
|
||||
import { Logger } from '../../core/logger.js';
|
||||
import { AnimationSystem } from './AnimationSystem.js';
|
||||
import { ScrollAnimation } from './ScrollAnimation.js';
|
||||
import { TimelineAnimation } from './TimelineAnimation.js';
|
||||
|
||||
const AnimationSystemModule = {
|
||||
name: 'animation-system',
|
||||
animationSystem: null,
|
||||
|
||||
init(config = {}, state = null) {
|
||||
Logger.info('[AnimationSystemModule] Module initialized');
|
||||
|
||||
// Create animation system
|
||||
this.animationSystem = AnimationSystem.create(config);
|
||||
|
||||
// Expose globally for easy access
|
||||
if (typeof window !== 'undefined') {
|
||||
window.AnimationSystem = this.animationSystem;
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get animation system instance
|
||||
*/
|
||||
getAnimationSystem() {
|
||||
return this.animationSystem || AnimationSystem.create();
|
||||
},
|
||||
|
||||
/**
|
||||
* Register animation
|
||||
*/
|
||||
registerAnimation(element, config) {
|
||||
const system = this.getAnimationSystem();
|
||||
system.registerAnimation(element, config);
|
||||
},
|
||||
|
||||
destroy() {
|
||||
if (this.animationSystem) {
|
||||
this.animationSystem.destroy();
|
||||
this.animationSystem = null;
|
||||
}
|
||||
|
||||
if (typeof window !== 'undefined' && window.AnimationSystem) {
|
||||
delete window.AnimationSystem;
|
||||
}
|
||||
|
||||
Logger.info('[AnimationSystemModule] Module destroyed');
|
||||
}
|
||||
};
|
||||
|
||||
// Export for direct usage
|
||||
export { AnimationSystem, ScrollAnimation, TimelineAnimation };
|
||||
|
||||
// Export as default for module system
|
||||
export default AnimationSystemModule;
|
||||
|
||||
// Export init function for module system
|
||||
export const init = AnimationSystemModule.init.bind(AnimationSystemModule);
|
||||
|
||||
// Backward compatibility exports
|
||||
export { createTrigger } from '../scrollfx/index.js';
|
||||
|
||||
Reference in New Issue
Block a user