动态效果

使用JavaScript创建流畅的动画和交互体验

核心概念

CSS动画

使用CSS transition和animation属性创建流畅的视觉效果。

/* CSS过渡 */ .animated-element { transition: all 0.3s ease; } .animated-element:hover { transform: scale(1.1); background-color: #0EA5E9; } /* CSS关键帧动画 */ @keyframes slideIn { from { transform: translateX(-100%); } to { transform: translateX(0); } }

JavaScript动画

使用requestAnimationFrame和定时器创建复杂的动画效果。

// 使用requestAnimationFrame function animate(element, targetX, duration) { const startX = parseInt(element.style.left) || 0; const startTime = performance.now(); function step(currentTime) { const elapsed = currentTime - startTime; const progress = Math.min(elapsed / duration, 1); const currentX = startX + (targetX - startX) * progress; element.style.left = currentX + 'px'; if (progress < 1) { requestAnimationFrame(step); } } requestAnimationFrame(step); }

Web Animations API

现代浏览器提供的强大动画API。

// 使用Web Animations API element.animate([ { transform: 'rotate(0deg)' }, { transform: 'rotate(360deg)' } ], { duration: 1000, iterations: Infinity, direction: 'alternate' });

动画效果演示

淡入淡出效果

这是一个淡入淡出的元素

滑动效果

这是一个滑动显示的元素

进度条动画

进度: 0%

加载动画

内容加载完成

交互式动画

悬停效果

悬停我

旋转

移动

点击动画

拖拽动画

拖我

滚动动画

内容1
内容2
内容3

高级动画技巧

性能优化

// 使用transform和opacity优化性能 const element = document.getElementById('animated'); // 避免触发布局重排 element.style.transform = 'translateX(100px)'; element.style.opacity = '0.5'; // 使用will-change提示浏览器 element.style.willChange = 'transform, opacity'; // 动画结束后清理 setTimeout(() => { element.style.willChange = 'auto'; }, 1000); // 批量DOM操作 const fragment = document.createDocumentFragment(); for (let i = 0; i < 100; i++) { const div = document.createElement('div'); div.className = 'animated-item'; fragment.appendChild(div); } document.body.appendChild(fragment);

动画库集成

// 使用GSAP动画库 // gsap.to('.box', { duration: 1, x: 100, rotation: 360 }); // 使用Anime.js // anime({ // targets: '.box', // translateX: 250, // rotate: '1turn', // duration: 800 // }); // 自定义动画引擎 class AnimationEngine { constructor() { this.animations = new Set(); } add(animation) { this.animations.add(animation); } update() { const now = performance.now(); this.animations.forEach(anim => { if (anim.update(now)) { this.animations.delete(anim); } }); } }

案例:小华的在线商城

商城动画需求

  • • 商品卡片悬停效果
  • • 购物车添加动画
  • • 页面切换过渡
  • • 加载状态动画
  • • 搜索建议下拉
  • • 图片轮播效果

实现架构

class AnimationManager { constructor() { this.animations = { hover: new HoverAnimation(), cart: new CartAnimation(), transition: new TransitionAnimation(), loading: new LoadingAnimation() }; } init() { // 初始化所有动画 Object.values(this.animations).forEach(animation => { animation.init(); }); } } class CartAnimation { constructor() { this.cartIcon = document.querySelector('.cart-icon'); this.cartCount = document.querySelector('.cart-count'); } addToCart(product) { // 创建飞入动画 const clone = product.cloneNode(true); clone.classList.add('flying-item'); const start = product.getBoundingClientRect(); const end = this.cartIcon.getBoundingClientRect(); clone.style.position = 'fixed'; clone.style.left = start.left + 'px'; clone.style.top = start.top + 'px'; clone.style.zIndex = '1000'; document.body.appendChild(clone); // 执行飞行动画 clone.animate([ { transform: 'scale(1)' }, { transform: 'scale(0.5)', offset: 0.7 }, { transform: 'scale(0)', left: end.left + 'px', top: end.top + 'px' } ], { duration: 600, easing: 'ease-out' }).onfinish = () => { clone.remove(); this.updateCartCount(); }; } updateCartCount() { const count = parseInt(this.cartCount.textContent); this.cartCount.textContent = count + 1; // 添加计数动画 this.cartCount.classList.add('bounce'); setTimeout(() => { this.cartCount.classList.remove('bounce'); }, 600); } }

实际演示:商城动画系统

商品1

¥99

商品2

¥199

商品3

¥299

购物车 0
🛒

练习题(8个实战练习)

练习1:打字机效果

实现一个打字机效果,文字逐个显示。

class Typewriter { constructor(element, text, speed = 100) { this.element = element; this.text = text; this.speed = speed; this.index = 0; } type() { if (this.index < this.text.length) { this.element.textContent += this.text.charAt(this.index); this.index++; setTimeout(() => this.type(), this.speed); } } erase() { if (this.index > 0) { this.element.textContent = this.text.substring(0, this.index - 1); this.index--; setTimeout(() => this.erase(), this.speed / 2); } } typeAndErase() { this.type(); setTimeout(() => { this.erase(); setTimeout(() => this.typeAndErase(), 1000); }, this.text.length * this.speed + 1000); } } // 使用示例 const typewriter = new Typewriter( document.getElementById('typewriter'), '欢迎来到JavaScript动画世界!', 150 ); typewriter.type();

练习2:粒子效果

创建鼠标跟随的粒子动画效果。

class ParticleSystem { constructor(canvas) { this.canvas = canvas; this.ctx = canvas.getContext('2d'); this.particles = []; this.mouse = { x: 0, y: 0 }; this.setupCanvas(); this.bindEvents(); this.animate(); } setupCanvas() { this.canvas.width = window.innerWidth; this.canvas.height = window.innerHeight; } bindEvents() { this.canvas.addEventListener('mousemove', (e) => { this.mouse.x = e.clientX; this.mouse.y = e.clientY; this.createParticle(); }); } createParticle() { const particle = { x: this.mouse.x, y: this.mouse.y, vx: (Math.random() - 0.5) * 2, vy: (Math.random() - 0.5) * 2, size: Math.random() * 3 + 1, color: `hsl(${Math.random() * 360}, 70%, 50%)`, life: 1 }; this.particles.push(particle); } updateParticles() { this.particles = this.particles.filter(particle => { particle.x += particle.vx; particle.y += particle.vy; particle.life -= 0.01; return particle.life > 0; }); } drawParticles() { this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); this.particles.forEach(particle => { this.ctx.globalAlpha = particle.life; this.ctx.fillStyle = particle.color; this.ctx.beginPath(); this.ctx.arc(particle.x, particle.y, particle.size, 0, Math.PI * 2); this.ctx.fill(); }); } animate() { this.updateParticles(); this.drawParticles(); requestAnimationFrame(() => this.animate()); } }

练习3-5:基础动画

  • • 图片轮播器
  • • 滚动视差效果
  • • 数字计数器

练习6-8:高级动画

  • • 3D翻转卡片
  • • 路径动画
  • • 交互式图表