UNPKG

my-animation-lib

Version:

A powerful animation library combining Three.js, GSAP, custom scroll triggers, and advanced effects with MathUtils integration

203 lines (172 loc) 5.36 kB
import { gsap } from 'gsap'; export class HiTechScroller { constructor(container, options = {}) { this.container = container; this.options = { speed: options.speed || 1, smoothness: options.smoothness || 0.1, showProgress: options.showProgress || true, showIndicator: options.showIndicator || true, ...options }; this.currentScroll = 0; this.targetScroll = 0; this.isScrolling = false; this.progressBar = null; this.scrollIndicator = null; this.sections = []; this.init(); } init() { this.setupContainer(); this.createProgressBar(); this.createScrollIndicator(); this.setupEventListeners(); this.animate(); } setupContainer() { this.container.style.position = 'relative'; this.container.style.overflow = 'hidden'; this.container.style.height = '100vh'; } createProgressBar() { if (!this.options.showProgress) return; this.progressBar = document.createElement('div'); this.progressBar.style.cssText = ` position: fixed; top: 0; left: 0; width: 0%; height: 3px; background: linear-gradient(90deg, #00ff88, #00ccff, #ff0088); z-index: 1000; transition: width 0.1s ease; `; document.body.appendChild(this.progressBar); } createScrollIndicator() { if (!this.options.showIndicator) return; this.scrollIndicator = document.createElement('div'); this.scrollIndicator.style.cssText = ` position: fixed; right: 20px; top: 50%; transform: translateY(-50%); width: 4px; height: 100px; background: rgba(255, 255, 255, 0.2); border-radius: 2px; z-index: 1000; `; const indicatorDot = document.createElement('div'); indicatorDot.style.cssText = ` position: absolute; top: 0; left: 0; width: 100%; height: 20px; background: linear-gradient(180deg, #00ff88, #00ccff); border-radius: 2px; transition: top 0.1s ease; `; this.scrollIndicator.appendChild(indicatorDot); this.indicatorDot = indicatorDot; document.body.appendChild(this.scrollIndicator); } setupEventListeners() { window.addEventListener('wheel', this.handleWheel.bind(this)); window.addEventListener('keydown', this.handleKeydown.bind(this)); window.addEventListener('resize', this.handleResize.bind(this)); } handleWheel(event) { event.preventDefault(); const delta = event.deltaY * this.options.speed; this.targetScroll += delta; this.targetScroll = Math.max(0, this.targetScroll); this.targetScroll = Math.min(this.getMaxScroll(), this.targetScroll); this.isScrolling = true; setTimeout(() => { this.isScrolling = false; }, 150); } handleKeydown(event) { switch (event.key) { case 'ArrowDown': case 'PageDown': event.preventDefault(); this.scrollTo(this.targetScroll + window.innerHeight); break; case 'ArrowUp': case 'PageUp': event.preventDefault(); this.scrollTo(this.targetScroll - window.innerHeight); break; case 'Home': event.preventDefault(); this.scrollTo(0); break; case 'End': event.preventDefault(); this.scrollTo(this.getMaxScroll()); break; } } handleResize() { this.updateProgressBar(); this.updateScrollIndicator(); } animate() { if (Math.abs(this.currentScroll - this.targetScroll) > 0.1) { this.currentScroll += (this.targetScroll - this.currentScroll) * this.options.smoothness; this.updateScroll(); } requestAnimationFrame(this.animate.bind(this)); } updateScroll() { this.container.style.transform = `translateY(-${this.currentScroll}px)`; this.updateProgressBar(); this.updateScrollIndicator(); } updateProgressBar() { if (this.progressBar) { const progress = (this.currentScroll / this.getMaxScroll()) * 100; this.progressBar.style.width = `${progress}%`; } } updateScrollIndicator() { if (this.indicatorDot) { const progress = (this.currentScroll / this.getMaxScroll()) * 80; this.indicatorDot.style.top = `${progress}%`; } } getMaxScroll() { return Math.max(0, this.container.scrollHeight - window.innerHeight); } scrollTo(position, duration = 1) { gsap.to(this, { targetScroll: position, duration: duration, ease: "power2.out" }); } scrollToSection(index, duration = 1) { if (this.sections[index]) { const position = this.sections[index].offsetTop; this.scrollTo(position, duration); } } addSection(section) { this.sections.push(section); } destroy() { window.removeEventListener('wheel', this.handleWheel); window.removeEventListener('keydown', this.handleKeydown); window.removeEventListener('resize', this.handleResize); if (this.progressBar) { document.body.removeChild(this.progressBar); } if (this.scrollIndicator) { document.body.removeChild(this.scrollIndicator); } } }