my-animation-lib
Version:
A powerful animation library combining Three.js, GSAP, custom scroll triggers, and advanced effects with MathUtils integration
665 lines (571 loc) • 24.3 kB
HTML
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Advanced Effects Demo - My Animation Library</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Arial', sans-serif;
line-height: 1.6;
color: #333;
background: #f0f0f0;
}
.header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
text-align: center;
padding: 3rem 2rem;
position: relative;
overflow: hidden;
}
.header h1 {
font-size: 3rem;
margin-bottom: 1rem;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
}
.header p {
font-size: 1.2rem;
opacity: 0.9;
}
.floating-elements {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
}
.floating-element {
position: absolute;
width: 50px;
height: 50px;
background: rgba(255, 255, 255, 0.1);
border-radius: 50%;
animation: float 6s ease-in-out infinite;
}
.floating-element:nth-child(1) { top: 20%; left: 10%; animation-delay: 0s; }
.floating-element:nth-child(2) { top: 60%; right: 15%; animation-delay: 2s; }
.floating-element:nth-child(3) { top: 40%; left: 80%; animation-delay: 4s; }
@keyframes float {
0%, 100% { transform: translateY(0px) rotate(0deg); }
50% { transform: translateY(-20px) rotate(180deg); }
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
}
.section {
margin-bottom: 4rem;
padding: 2rem;
background: white;
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
}
.section h2 {
font-size: 2.5rem;
margin-bottom: 1.5rem;
color: #333;
text-align: center;
}
.effects-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
margin-top: 2rem;
}
.effect-card {
background: #f8f9fa;
padding: 1.5rem;
border-radius: 10px;
border: 2px solid transparent;
transition: all 0.3s ease;
cursor: pointer;
}
.effect-card:hover {
border-color: #667eea;
transform: translateY(-5px);
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1);
}
.effect-card h3 {
color: #667eea;
margin-bottom: 1rem;
font-size: 1.3rem;
}
.effect-card p {
color: #666;
margin-bottom: 1rem;
}
.effect-demo {
min-height: 100px;
display: flex;
align-items: center;
justify-content: center;
background: white;
border-radius: 8px;
margin-bottom: 1rem;
border: 1px solid #ddd;
}
.text-effect-demo {
font-size: 1.5rem;
font-weight: bold;
color: #333;
}
.image-effect-demo {
width: 100px;
height: 100px;
background: linear-gradient(45deg, #667eea, #764ba2);
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
}
.controls {
background: #333;
color: white;
padding: 2rem;
border-radius: 15px;
margin-bottom: 2rem;
}
.controls h3 {
color: #00ff88;
margin-bottom: 1rem;
}
.control-group {
margin-bottom: 1rem;
}
.control-group label {
display: block;
margin-bottom: 0.5rem;
font-size: 0.9rem;
}
.control-group input,
.control-group select,
.control-group button {
width: 100%;
padding: 0.5rem;
margin-bottom: 0.5rem;
border: none;
border-radius: 5px;
background: #555;
color: white;
}
.control-group button {
background: #007bff;
cursor: pointer;
transition: background 0.3s;
}
.control-group button:hover {
background: #0056b3;
}
.control-group button.active {
background: #28a745;
}
.button-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 1rem;
}
.performance {
background: #f8f9fa;
padding: 1rem;
border-radius: 10px;
margin-top: 1rem;
font-family: monospace;
font-size: 0.9rem;
}
.performance div {
margin-bottom: 0.5rem;
}
.footer {
background: #333;
color: white;
text-align: center;
padding: 2rem;
margin-top: 4rem;
}
@media (max-width: 768px) {
.header h1 {
font-size: 2rem;
}
.effects-grid {
grid-template-columns: 1fr;
}
.button-grid {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="header">
<div class="floating-elements">
<div class="floating-element"></div>
<div class="floating-element"></div>
<div class="floating-element"></div>
</div>
<h1>Advanced Effects Demo</h1>
<p>Experience the full power of our animation library</p>
</div>
<div class="container">
<div class="controls">
<h3>Global Controls</h3>
<div class="control-group">
<label>Animation Speed:</label>
<input type="range" id="globalSpeed" min="0.1" max="3" value="1" step="0.1">
<span id="speedValue">1x</span>
</div>
<div class="control-group">
<button id="pauseAll">Pause All</button>
<button id="resumeAll">Resume All</button>
<button id="resetAll">Reset All</button>
</div>
</div>
<div class="section">
<h2>Text Effects</h2>
<div class="effects-grid">
<div class="effect-card" data-effect="typewriter">
<h3>Typewriter</h3>
<p>Text appears character by character</p>
<div class="effect-demo">
<div class="text-effect-demo" id="typewriter-demo">Hello World!</div>
</div>
<button class="play-effect">Play Effect</button>
</div>
<div class="effect-card" data-effect="scramble">
<h3>Scramble</h3>
<p>Text scrambles and reveals</p>
<div class="effect-demo">
<div class="text-effect-demo" id="scramble-demo">Scramble Text</div>
</div>
<button class="play-effect">Play Effect</button>
</div>
<div class="effect-card" data-effect="wave">
<h3>Wave</h3>
<p>Text waves like water</p>
<div class="effect-demo">
<div class="text-effect-demo" id="wave-demo">Wave Effect</div>
</div>
<button class="play-effect">Play Effect</button>
</div>
<div class="effect-card" data-effect="bounce">
<h3>Bounce</h3>
<p>Text bounces with energy</p>
<div class="effect-demo">
<div class="text-effect-demo" id="bounce-demo">Bounce!</div>
</div>
<button class="play-effect">Play Effect</button>
</div>
<div class="effect-card" data-effect="glitch">
<h3>Glitch</h3>
<p>Digital glitch effect</p>
<div class="effect-demo">
<div class="text-effect-demo" id="glitch-demo">Glitch</div>
</div>
<button class="play-effect">Play Effect</button>
</div>
<div class="effect-card" data-effect="slideIn">
<h3>Slide In</h3>
<p>Text slides in from sides</p>
<div class="effect-demo">
<div class="text-effect-demo" id="slideIn-demo">Slide In</div>
</div>
<button class="play-effect">Play Effect</button>
</div>
</div>
</div>
<div class="section">
<h2>Image Effects</h2>
<div class="effects-grid">
<div class="effect-card" data-effect="morph">
<h3>Morph</h3>
<p>Shape-shifting transformation</p>
<div class="effect-demo">
<div class="image-effect-demo" id="morph-demo">Morph</div>
</div>
<button class="play-effect">Play Effect</button>
</div>
<div class="effect-card" data-effect="distortion">
<h3>Distortion</h3>
<p>Wave-like distortion</p>
<div class="effect-demo">
<div class="image-effect-demo" id="distortion-demo">Distort</div>
</div>
<button class="play-effect">Play Effect</button>
</div>
<div class="effect-card" data-effect="glitch">
<h3>Glitch</h3>
<p>Digital corruption effect</p>
<div class="effect-demo">
<div class="image-effect-demo" id="glitch-img-demo">Glitch</div>
</div>
<button class="play-effect">Play Effect</button>
</div>
<div class="effect-card" data-effect="wave">
<h3>Wave</h3>
<p>Ocean wave movement</p>
<div class="effect-demo">
<div class="image-effect-demo" id="wave-img-demo">Wave</div>
</div>
<button class="play-effect">Play Effect</button>
</div>
<div class="effect-card" data-effect="pulse">
<h3>Pulse</h3>
<p>Heartbeat rhythm</p>
<div class="effect-demo">
<div class="image-effect-demo" id="pulse-demo">Pulse</div>
</div>
<button class="play-effect">Play Effect</button>
</div>
<div class="effect-card" data-effect="shake">
<h3>Shake</h3>
<p>Earthquake effect</p>
<div class="effect-demo">
<div class="image-effect-demo" id="shake-demo">Shake</div>
</div>
<button class="play-effect">Play Effect</button>
</div>
</div>
</div>
<div class="section">
<h2>Combined Effects</h2>
<div class="effects-grid">
<div class="effect-card">
<h3>Text + Image Combo</h3>
<p>Multiple effects simultaneously</p>
<div class="effect-demo">
<div class="text-effect-demo" id="combo-text">Combo</div>
<div class="image-effect-demo" id="combo-img" style="margin-left: 1rem;">FX</div>
</div>
<button id="playCombo">Play Combo</button>
</div>
<div class="effect-card">
<h3>Sequence Chain</h3>
<p>Effects play in sequence</p>
<div class="effect-demo">
<div class="text-effect-demo" id="sequence-demo">Sequence</div>
</div>
<button id="playSequence">Play Sequence</button>
</div>
<div class="effect-card">
<h3>Random Effects</h3>
<p>Random effect selection</p>
<div class="effect-demo">
<div class="text-effect-demo" id="random-demo">Random</div>
</div>
<button id="playRandom">Play Random</button>
</div>
</div>
</div>
<div class="performance">
<h4>Performance Monitor</h4>
<div>Active Effects: <span id="activeEffects">0</span></div>
<div>FPS: <span id="fps">0</span></div>
<div>Memory: <span id="memory">0</span> MB</div>
</div>
</div>
<div class="footer">
<p>© 2024 My Animation Library. All rights reserved.</p>
</div>
<script type="module">
import { AnimationEngine, TextEffects, ImageEffects } from '../src/index.js';
// Initialize the animation engine
const engine = new AnimationEngine();
await engine.init();
// Initialize effects classes
const textEffects = new TextEffects();
const imageEffects = new ImageEffects();
// Global state
let globalSpeed = 1;
let isPaused = false;
let activeEffects = 0;
let currentAnimations = new Map();
// Performance monitoring
let frameCount = 0;
let lastTime = performance.now();
let fps = 0;
function updatePerformance() {
frameCount++;
const currentTime = performance.now();
if (currentTime - lastTime >= 1000) {
fps = Math.round((frameCount * 1000) / (currentTime - lastTime));
document.getElementById('fps').textContent = fps;
// Memory usage (approximate)
if (performance.memory) {
const memoryMB = Math.round(performance.memory.usedJSHeapSize / 1024 / 1024);
document.getElementById('memory').textContent = memoryMB;
}
frameCount = 0;
lastTime = currentTime;
}
}
// Global controls
document.getElementById('globalSpeed').addEventListener('input', (e) => {
globalSpeed = parseFloat(e.target.value);
document.getElementById('speedValue').textContent = globalSpeed + 'x';
// Update all active animations
currentAnimations.forEach(animation => {
if (animation.timeline) {
animation.timeline.timeScale(globalSpeed);
}
});
});
document.getElementById('pauseAll').addEventListener('click', function() {
isPaused = true;
currentAnimations.forEach(animation => {
if (animation.timeline) {
animation.timeline.pause();
}
});
this.classList.add('active');
document.getElementById('resumeAll').classList.remove('active');
});
document.getElementById('resumeAll').addEventListener('click', function() {
isPaused = false;
currentAnimations.forEach(animation => {
if (animation.timeline) {
animation.timeline.resume();
}
});
this.classList.add('active');
document.getElementById('pauseAll').classList.remove('active');
});
document.getElementById('resetAll').addEventListener('click', function() {
// Reset all effects
currentAnimations.forEach(animation => {
if (animation.timeline) {
animation.timeline.restart();
animation.timeline.pause();
}
});
// Reset elements to original state
document.querySelectorAll('.text-effect-demo, .image-effect-demo').forEach(element => {
element.style.transform = '';
element.style.filter = '';
element.style.animation = '';
});
activeEffects = 0;
document.getElementById('activeEffects').textContent = activeEffects;
});
// Text effects
document.querySelectorAll('[data-effect]').forEach(card => {
const effectType = card.dataset.effect;
const demoElement = card.querySelector('.text-effect-demo, .image-effect-demo');
const playButton = card.querySelector('.play-effect');
playButton.addEventListener('click', () => {
if (isPaused) return;
const animationId = `${effectType}-${Date.now()}`;
if (demoElement.classList.contains('text-effect-demo')) {
// Text effect
const animation = textEffects[effectType](demoElement, {
duration: 2 / globalSpeed,
ease: 'power2.out'
});
if (animation && animation.timeline) {
currentAnimations.set(animationId, animation);
activeEffects++;
document.getElementById('activeEffects').textContent = activeEffects;
animation.timeline.eventCallback('onComplete', () => {
currentAnimations.delete(animationId);
activeEffects--;
document.getElementById('activeEffects').textContent = activeEffects;
});
}
} else {
// Image effect
const animation = imageEffects[effectType](demoElement, {
duration: 2 / globalSpeed,
ease: 'power2.out'
});
if (animation && animation.timeline) {
currentAnimations.set(animationId, animation);
activeEffects++;
document.getElementById('activeEffects').textContent = activeEffects;
animation.timeline.eventCallback('onComplete', () => {
currentAnimations.delete(animationId);
activeEffects--;
document.getElementById('activeEffects').textContent = activeEffects;
});
}
}
});
});
// Combined effects
document.getElementById('playCombo').addEventListener('click', () => {
if (isPaused) return;
const textElement = document.getElementById('combo-text');
const imgElement = document.getElementById('combo-img');
const textAnim = textEffects.typewriter(textElement, { duration: 1.5 / globalSpeed });
const imgAnim = imageEffects.pulse(imgElement, { duration: 2 / globalSpeed });
if (textAnim && imgAnim) {
activeEffects += 2;
document.getElementById('activeEffects').textContent = activeEffects;
textAnim.timeline.eventCallback('onComplete', () => activeEffects--);
imgAnim.timeline.eventCallback('onComplete', () => activeEffects--);
}
});
document.getElementById('playSequence').addEventListener('click', () => {
if (isPaused) return;
const element = document.getElementById('sequence-demo');
const sequence = [
() => textEffects.fadeIn(element, { duration: 0.5 / globalSpeed }),
() => textEffects.bounce(element, { duration: 1 / globalSpeed }),
() => textEffects.wave(element, { duration: 1.5 / globalSpeed }),
() => textEffects.fadeOut(element, { duration: 0.5 / globalSpeed })
];
let currentIndex = 0;
function playNext() {
if (currentIndex < sequence.length) {
const animation = sequence[currentIndex]();
if (animation && animation.timeline) {
activeEffects++;
document.getElementById('activeEffects').textContent = activeEffects;
animation.timeline.eventCallback('onComplete', () => {
activeEffects--;
document.getElementById('activeEffects').textContent = activeEffects;
currentIndex++;
playNext();
});
}
}
}
playNext();
});
document.getElementById('playRandom').addEventListener('click', () => {
if (isPaused) return;
const element = document.getElementById('random-demo');
const effects = ['fadeIn', 'slideIn', 'bounce', 'wave', 'glitch'];
const randomEffect = effects[Math.floor(Math.random() * effects.length)];
const animation = textEffects[randomEffect](element, {
duration: 1.5 / globalSpeed,
ease: 'power2.out'
});
if (animation && animation.timeline) {
activeEffects++;
document.getElementById('activeEffects').textContent = activeEffects;
animation.timeline.eventCallback('onComplete', () => {
activeEffects--;
document.getElementById('activeEffects').textContent = activeEffects;
});
}
});
// Performance loop
function animate() {
requestAnimationFrame(animate);
updatePerformance();
}
animate();
console.log('Advanced effects demo loaded successfully!');
console.log('Available text effects:', Object.getOwnPropertyNames(TextEffects.prototype));
console.log('Available image effects:', Object.getOwnPropertyNames(ImageEffects.prototype));
</script>
</body>
</html>