my-animation-lib
Version:
A powerful animation library combining Three.js, GSAP, custom scroll triggers, and advanced effects with MathUtils integration
465 lines (390 loc) • 15.8 kB
HTML
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three.js Demo - My Animation Library</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Arial', sans-serif;
background: #000;
color: white;
overflow: hidden;
}
#threejs-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
.ui-overlay {
position: fixed;
top: 20px;
left: 20px;
z-index: 1000;
background: rgba(0, 0, 0, 0.8);
padding: 1rem;
border-radius: 10px;
max-width: 300px;
}
.ui-overlay h3 {
margin-bottom: 1rem;
color: #00ff88;
}
.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: #333;
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;
}
.stats {
position: fixed;
top: 20px;
right: 20px;
z-index: 1000;
background: rgba(0, 0, 0, 0.8);
padding: 1rem;
border-radius: 10px;
font-family: monospace;
font-size: 0.8rem;
}
.info-panel {
position: fixed;
bottom: 20px;
left: 20px;
z-index: 1000;
background: rgba(0, 0, 0, 0.8);
padding: 1rem;
border-radius: 10px;
max-width: 400px;
}
.info-panel h4 {
color: #00ff88;
margin-bottom: 0.5rem;
}
.info-panel p {
font-size: 0.9rem;
margin-bottom: 0.5rem;
}
.loading {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 2000;
background: rgba(0, 0, 0, 0.9);
padding: 2rem;
border-radius: 10px;
text-align: center;
}
.spinner {
border: 4px solid #333;
border-top: 4px solid #00ff88;
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
margin: 0 auto 1rem;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
</head>
<body>
<div id="threejs-container"></div>
<div class="ui-overlay">
<h3>3D Controls</h3>
<div class="control-group">
<label>Camera Position:</label>
<input type="range" id="cameraX" min="-50" max="50" value="0" step="1">
<input type="range" id="cameraY" min="-50" max="50" value="0" step="1">
<input type="range" id="cameraZ" min="10" max="100" value="30" step="1">
</div>
<div class="control-group">
<label>Rotation Speed:</label>
<input type="range" id="rotationSpeed" min="0" max="0.1" value="0.01" step="0.001">
</div>
<div class="control-group">
<label>Particle Count:</label>
<input type="range" id="particleCount" min="100" max="5000" value="1000" step="100">
</div>
<div class="control-group">
<button id="toggleRotation">Pause Rotation</button>
<button id="toggleParticles">Toggle Particles</button>
<button id="changeColor">Change Color</button>
<button id="resetScene">Reset Scene</button>
</div>
<div class="control-group">
<label>Effect Type:</label>
<select id="effectType">
<option value="basic">Basic Particles</option>
<option value="fire">Fire Effect</option>
<option value="smoke">Smoke Effect</option>
<option value="sparkle">Sparkle Effect</option>
<option value="rain">Rain Effect</option>
<option value="snow">Snow Effect</option>
</select>
<button id="createEffect">Create Effect</button>
</div>
</div>
<div class="stats">
<div>FPS: <span id="fps">0</span></div>
<div>Objects: <span id="objectCount">0</span></div>
<div>Particles: <span id="particleCount">0</span></div>
<div>Memory: <span id="memory">0</span> MB</div>
</div>
<div class="info-panel">
<h4>Three.js Demo</h4>
<p>Use the controls to manipulate the 3D scene:</p>
<p>• Adjust camera position with sliders</p>
<p>• Control rotation speed</p>
<p>• Toggle particle systems</p>
<p>• Create different particle effects</p>
<p>• Use mouse to rotate camera view</p>
</div>
<div class="loading" id="loading">
<div class="spinner"></div>
<p>Loading 3D Scene...</p>
</div>
<script type="module">
import { AnimationEngine, ThreeJSManager, ParticleEffects } from '../src/index.js';
// Initialize the animation engine
const engine = new AnimationEngine();
await engine.init();
// Get Three.js manager
const threeJSManager = engine.getThreeJSManager();
const container = document.getElementById('threejs-container');
// Initialize Three.js scene
await threeJSManager.init();
container.appendChild(threeJSManager.renderer.domElement);
// Initialize particle effects
const particleEffects = new ParticleEffects(threeJSManager);
// Create some basic 3D objects
const cube = threeJSManager.createCube({
size: 5,
color: 0x00ff88,
position: { x: -10, y: 0, z: 0 }
});
const sphere = threeJSManager.createSphere({
radius: 3,
color: 0xff0088,
position: { x: 10, y: 0, z: 0 }
});
// Create initial particle system
let currentParticleSystem = particleEffects.createParticleSystem({
count: 1000,
size: 0.1,
color: 0x00ffff,
speed: 0.01,
spread: 50
});
// Animation state
let rotationEnabled = true;
let particlesEnabled = true;
let currentEffect = 'basic';
// Control event listeners
document.getElementById('cameraX').addEventListener('input', (e) => {
threeJSManager.camera.position.x = parseFloat(e.target.value);
});
document.getElementById('cameraY').addEventListener('input', (e) => {
threeJSManager.camera.position.y = parseFloat(e.target.value);
});
document.getElementById('cameraZ').addEventListener('input', (e) => {
threeJSManager.camera.position.z = parseFloat(e.target.value);
});
document.getElementById('rotationSpeed').addEventListener('input', (e) => {
threeJSManager.rotationSpeed = parseFloat(e.target.value);
});
document.getElementById('particleCount').addEventListener('input', (e) => {
const count = parseInt(e.target.value);
document.getElementById('particleCount').textContent = count;
});
document.getElementById('toggleRotation').addEventListener('click', function() {
rotationEnabled = !rotationEnabled;
this.textContent = rotationEnabled ? 'Pause Rotation' : 'Resume Rotation';
this.classList.toggle('active');
});
document.getElementById('toggleParticles').addEventListener('click', function() {
particlesEnabled = !particlesEnabled;
this.textContent = particlesEnabled ? 'Hide Particles' : 'Show Particles';
this.classList.toggle('active');
const system = particleEffects.getParticleSystem(currentParticleSystem);
if (system) {
system.particles.visible = particlesEnabled;
}
});
document.getElementById('changeColor').addEventListener('click', function() {
const colors = [0x00ff88, 0xff0088, 0x0088ff, 0xffff00, 0xff8800, 0x8800ff];
const randomColor = colors[Math.floor(Math.random() * colors.length)];
// Change cube color
if (cube && cube.material) {
cube.material.color.setHex(randomColor);
}
// Change sphere color
if (sphere && sphere.material) {
sphere.material.color.setHex(colors[(colors.indexOf(randomColor) + 1) % colors.length]);
}
});
document.getElementById('resetScene').addEventListener('click', function() {
// Reset camera position
threeJSManager.camera.position.set(0, 0, 30);
threeJSManager.camera.lookAt(0, 0, 0);
// Reset sliders
document.getElementById('cameraX').value = 0;
document.getElementById('cameraY').value = 0;
document.getElementById('cameraZ').value = 30;
// Reset rotation speed
threeJSManager.rotationSpeed = 0.01;
document.getElementById('rotationSpeed').value = 0.01;
// Reset objects
if (cube) cube.rotation.set(0, 0, 0);
if (sphere) sphere.rotation.set(0, 0, 0);
});
document.getElementById('createEffect').addEventListener('click', function() {
const effectType = document.getElementById('effectType').value;
// Remove current particle system
if (currentParticleSystem) {
particleEffects.removeParticleSystem(currentParticleSystem);
}
// Create new effect based on selection
switch (effectType) {
case 'fire':
currentParticleSystem = particleEffects.createFireEffect({
position: { x: 0, y: -10, z: 0 },
intensity: 1.5
});
break;
case 'smoke':
currentParticleSystem = particleEffects.createSmokeEffect({
position: { x: 0, y: -10, z: 0 },
intensity: 1
});
break;
case 'sparkle':
currentParticleSystem = particleEffects.createSparkleEffect({
position: { x: 0, y: 0, z: 0 },
count: 300
});
break;
case 'rain':
currentParticleSystem = particleEffects.createRainEffect({
intensity: 1.5
});
break;
case 'snow':
currentParticleSystem = particleEffects.createSnowEffect({
intensity: 1
});
break;
default:
currentParticleSystem = particleEffects.createParticleSystem({
count: parseInt(document.getElementById('particleCount').value),
size: 0.1,
color: 0x00ffff,
speed: 0.01,
spread: 50
});
}
currentEffect = effectType;
});
// Mouse controls for camera rotation
let mouseDown = false;
let mouseX = 0;
let mouseY = 0;
container.addEventListener('mousedown', (e) => {
mouseDown = true;
mouseX = e.clientX;
mouseY = e.clientY;
});
container.addEventListener('mouseup', () => {
mouseDown = false;
});
container.addEventListener('mousemove', (e) => {
if (mouseDown) {
const deltaX = e.clientX - mouseX;
const deltaY = e.clientY - mouseY;
threeJSManager.camera.position.x += deltaX * 0.01;
threeJSManager.camera.position.y -= deltaY * 0.01;
mouseX = e.clientX;
mouseY = e.clientY;
}
});
// Performance monitoring
let frameCount = 0;
let lastTime = performance.now();
let fps = 0;
function updateStats() {
frameCount++;
const currentTime = performance.now();
if (currentTime - lastTime >= 1000) {
fps = Math.round((frameCount * 1000) / (currentTime - lastTime));
document.getElementById('fps').textContent = fps;
const objectCount = threeJSManager.scene.children.length;
document.getElementById('objectCount').textContent = objectCount;
const particleCount = particleEffects.getParticleSystemCount();
document.getElementById('particleCount').textContent = particleCount;
// Memory usage (approximate)
if (performance.memory) {
const memoryMB = Math.round(performance.memory.usedJSHeapSize / 1024 / 1024);
document.getElementById('memory').textContent = memoryMB;
}
frameCount = 0;
lastTime = currentTime;
}
}
// Custom animation loop
function animate() {
requestAnimationFrame(animate);
const deltaTime = 0.016; // Approximate 60fps
// Update particle effects
if (particlesEnabled) {
particleEffects.update(deltaTime);
}
// Update Three.js manager
threeJSManager.animate();
// Update stats
updateStats();
}
// Start animation
animate();
// Hide loading screen
document.getElementById('loading').style.display = 'none';
console.log('Three.js demo loaded successfully!');
console.log('Created scene with', threeJSManager.scene.children.length, 'objects');
console.log('Particle system ID:', currentParticleSystem);
</script>
</body>
</html>