GSAP 性能优化

GSAP 性能优化技巧,确保动画流畅运行在 60fps。


📚 性能优化原则

60fps 目标

  • 帧率:60fps = 每帧 16.67ms
  • 目标:保持动画流畅,避免卡顿
  • 监控:使用浏览器 DevTools 监控性能

性能影响因素

  1. 属性选择:transform 和 opacity 性能最好
  2. 动画数量:同时运行的动画数量
  3. 元素数量:动画元素的数量
  4. 重排重绘:避免触发布局和绘制

🎯 属性优化

GPU 加速属性

推荐使用:这些属性由 GPU 处理,性能最佳

// Transform 属性
gsap.to(".box", {
  x: 100,           // translateX
  y: 50,            // translateY
  z: 0,             // translateZ
  rotation: 360,    // rotateZ
  rotationX: 180,   // rotateX
  rotationY: 90,    // rotateY
  scale: 1.5,       // scale
  scaleX: 2,        // scaleX
  scaleY: 0.5,      // scaleY
  skewX: 45,        // skewX
  skewY: 30,        // skewY
  opacity: 0.5      // opacity
});

触发重排的属性

避免使用:这些属性会触发重排,性能较差

// ❌ 不推荐
gsap.to(".box", {
  left: "100px",      // 触发重排
  top: "50px",        // 触发重排
  width: "200px",     // 触发重排
  height: "100px",    // 触发重排
  margin: "20px",     // 触发重排
  padding: "10px"     // 触发重排
});
 
// ✅ 推荐:使用 transform
gsap.to(".box", {
  x: 100,    // translateX
  y: 50      // translateY
});

颜色和滤镜

⚠️ 谨慎使用:这些属性可能触发重绘

// 颜色动画(需要 ColorPropsPlugin)
gsap.to(".box", {
  backgroundColor: "#ff0000",
  color: "#ffffff"
});
 
// 滤镜动画(性能较差)
gsap.to(".box", {
  filter: "blur(10px)",
  backdropFilter: "blur(10px)"
});

🎨 will-change 优化

使用 will-change

.animated-element {
  will-change: transform, opacity;
}

动态设置 will-change

// 动画开始前
gsap.set(".box", { willChange: "transform" });
 
// 动画完成后移除
gsap.to(".box", {
  x: 100,
  duration: 1,
  onComplete: function() {
    gsap.set(".box", { willChange: "auto" });
  }
});

🚀 批量操作优化

使用 Timeline 而不是多个独立动画

// ❌ 不推荐:多个独立动画
gsap.to(".box1", { x: 100, duration: 1 });
gsap.to(".box2", { y: 100, duration: 1 });
gsap.to(".box3", { rotation: 360, duration: 1 });
 
// ✅ 推荐:使用 Timeline
const tl = gsap.timeline();
tl.to(".box1", { x: 100, duration: 1 })
  .to(".box2", { y: 100, duration: 1 })
  .to(".box3", { rotation: 360, duration: 1 });

使用 stagger 批量动画

// ✅ 推荐:使用 stagger
gsap.to(".item", {
  x: 100,
  duration: 1,
  stagger: 0.1
});
 
// ❌ 不推荐:循环创建多个动画
document.querySelectorAll(".item").forEach((item, i) => {
  gsap.to(item, {
    x: 100,
    duration: 1,
    delay: i * 0.1
  });
});

📊 性能监控

使用 DevTools 监控

  1. Performance 面板:录制动画性能
  2. Rendering 面板:显示重排重绘
  3. FPS 计数器:监控帧率

代码性能监控

// 监控动画性能
const startTime = performance.now();
 
gsap.to(".box", {
  x: 100,
  duration: 1,
  onComplete: function() {
    const endTime = performance.now();
    console.log(`动画耗时: ${endTime - startTime}ms`);
  }
});

使用 requestAnimationFrame

let frameCount = 0;
let lastTime = performance.now();
 
function measureFPS() {
  frameCount++;
  const currentTime = performance.now();
  
  if (currentTime >= lastTime + 1000) {
    console.log(`FPS: ${frameCount}`);
    frameCount = 0;
    lastTime = currentTime;
  }
  
  requestAnimationFrame(measureFPS);
}
 
measureFPS();

🎯 ScrollTrigger 性能优化

减少 ScrollTrigger 数量

// ❌ 不推荐:为每个元素创建 ScrollTrigger
elements.forEach(element => {
  gsap.from(element, {
    scrollTrigger: {
      trigger: element,
      start: "top 80%"
    }
  });
});
 
// ✅ 推荐:批量处理
gsap.utils.toArray(".item").forEach((item, i) => {
  gsap.from(item, {
    y: 50,
    opacity: 0,
    duration: 0.5,
    scrollTrigger: {
      trigger: item,
      start: "top 80%",
      toggleActions: "play none none reverse"
    },
    delay: i * 0.1
  });
});

使用 markers 调试后移除

// 开发时使用
scrollTrigger: {
  trigger: ".box",
  start: "top center",
  markers: true  // 调试时使用
}
 
// 生产环境移除
scrollTrigger: {
  trigger: ".box",
  start: "top center",
  markers: false  // 生产环境关闭
}

及时刷新和清理

// 窗口大小改变时刷新
window.addEventListener("resize", () => {
  ScrollTrigger.refresh();
});
 
// 组件卸载时清理
function cleanup() {
  ScrollTrigger.getAll().forEach(st => st.kill());
}

💡 优化技巧

1. 减少同时运行的动画

// ✅ 推荐:使用 Timeline 控制动画数量
const tl = gsap.timeline();
tl.to(".box1", { x: 100 })
  .to(".box2", { y: 100 })
  .to(".box3", { rotation: 360 });
 
// ❌ 不推荐:同时运行太多动画
for (let i = 0; i < 100; i++) {
  gsap.to(`.box${i}`, { x: 100 });
}

2. 使用对象引用而不是选择器

// ✅ 推荐:性能更好
const box = document.querySelector(".box");
gsap.to(box, { x: 100 });
 
// ❌ 不推荐:每次都要查询 DOM
gsap.to(".box", { x: 100 });

3. 合理使用 ease

// ✅ 推荐:简单的缓动函数
gsap.to(".box", {
  x: 100,
  ease: "power2.out"  // 性能好
});
 
// ⚠️ 谨慎使用:复杂的自定义缓动
gsap.to(".box", {
  x: 100,
  ease: function(t) {
    // 复杂的计算可能影响性能
    return Math.sin(t * Math.PI);
  }
});

4. 避免频繁更新

// ❌ 不推荐:频繁更新
gsap.to(".box", {
  x: 100,
  onUpdate: function() {
    // 频繁执行可能影响性能
    console.log(this.progress());
  }
});
 
// ✅ 推荐:节流更新
let lastUpdate = 0;
gsap.to(".box", {
  x: 100,
  onUpdate: function() {
    const now = performance.now();
    if (now - lastUpdate > 100) {  // 每 100ms 更新一次
      console.log(this.progress());
      lastUpdate = now;
    }
  }
});

🔧 性能测试

性能基准测试

function performanceTest(iterations = 100) {
  const startTime = performance.now();
  
  for (let i = 0; i < iterations; i++) {
    gsap.to(".test-box", {
      x: Math.random() * 100,
      duration: 0.1
    });
  }
  
  const endTime = performance.now();
  const duration = endTime - startTime;
  const avgTime = duration / iterations;
  
  console.log(`总耗时: ${duration}ms`);
  console.log(`平均耗时: ${avgTime}ms`);
  console.log(`理论 FPS: ${1000 / avgTime}`);
}

📝 性能检查清单

开发时检查

  • 使用 transform 和 opacity
  • 避免动画 width、height、left、top
  • 使用 Timeline 管理多个动画
  • 使用 stagger 批量动画
  • 合理使用 will-change
  • 及时清理 ScrollTrigger
  • 窗口大小改变时刷新 ScrollTrigger

生产环境检查

  • 移除 markers
  • 移除 console.log
  • 优化动画数量
  • 测试不同设备性能
  • 监控实际 FPS

🔗 相关资源


GSAP 性能优化 60fps 动画性能