# ===== CodeLab: js-animation ===== # 以下代码片段按文章出现顺序拼接, 共 7 段 # ----- 片段 1 (text) ----- .box { width: 80px; height: 80px; background: #4f7cff; border-radius: 8px; transition: transform 0.4s ease, background 0.4s ease; } .box:hover { transform: scale(1.2); background: #ff6b6b; } # ----- 片段 2 (javascript) ----- const box = document.getElementById('box'); let start = null; function move(timestamp) { if (start === null) { start = timestamp; } const elapsed = timestamp - start; const progress = Math.min(elapsed / 2000, 1); box.style.transform = 'translateX(' + progress * 300 + 'px)'; if (progress < 1) { requestAnimationFrame(move); } } requestAnimationFrame(move); # ----- 片段 3 (javascript) ----- function easeOutCubic(t) { return 1 - Math.pow(1 - t, 3); } function easeInOutQuad(t) { return t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2; } function animate(duration, easing, onUpdate) { return new Promise(function (resolve) { const start = performance.now(); function frame(now) { const t = Math.min((now - start) / duration, 1); onUpdate(easing(t)); if (t < 1) { requestAnimationFrame(frame); } else { resolve(); } } requestAnimationFrame(frame); }); } const box = document.getElementById('box'); animate(1200, easeOutCubic, function (p) { box.style.opacity = p; box.style.transform = 'scale(' + (0.5 + p * 0.5) + ')'; }).then(function () { console.log('动画完成'); }); # ----- 片段 4 (javascript) ----- const observer = new IntersectionObserver(function (entries) { for (const entry of entries) { if (entry.isIntersecting) { entry.target.classList.add('visible'); observer.unobserve(entry.target); } } }, { threshold: 0.2 }); document.querySelectorAll('.reveal').forEach(function (el) { observer.observe(el); }); # ----- 片段 5 (text) ----- .reveal { opacity: 0; transform: translateY(24px); transition: opacity 0.6s ease, transform 0.6s ease; } .reveal.visible { opacity: 1; transform: none; } # ----- 片段 6 (javascript) ----- const draggable = document.getElementById('draggable'); draggable.addEventListener('pointerdown', function (event) { const startX = event.clientX; const startY = event.clientY; const rect = draggable.getBoundingClientRect(); function onMove(e) { draggable.style.left = rect.left + (e.clientX - startX) + 'px'; draggable.style.top = rect.top + (e.clientY - startY) + 'px'; } function onUp() { window.removeEventListener('pointermove', onMove); window.removeEventListener('pointerup', onUp); } window.addEventListener('pointermove', onMove); window.addEventListener('pointerup', onUp); }); # ----- 片段 7 (javascript) ----- const box = document.getElementById('box'); const animation = box.animate( [ { transform: 'translateX(0)' }, { transform: 'translateX(200px)' } ], { duration: 800, easing: 'ease-in-out', iterations: Infinity, direction: 'alternate' } ); animation.pause(); setTimeout(function () { animation.play(); }, 1000);