js封装动画函数

52 阅读2分钟

一、在本项目中封装 JS 动画函数

1. 动画函数封装思路

web-admin/src/utils/web-company/src/utils/ 下新建 animate.ts,封装一个通用的动画函数(如缓动动画、属性过渡等),便于在各页面/组件中复用。

2. 示例:封装 requestAnimationFrame 动画函数

文件:web-admin/src/utils/animate.ts

// 支持属性过渡的通用动画函数
export function animate(
  from: number,
  to: number,
  duration: number,
  onUpdate: (value: number) => void,
  onComplete?: () => void
) {
  const start = performance.now();
  function frame(now: number) {
    const elapsed = now - start;
    const progress = Math.min(elapsed / duration, 1);
    const value = from + (to - from) * easeInOutQuad(progress);
    onUpdate(value);
    if (progress < 1) {
      requestAnimationFrame(frame);
    } else {
      onUpdate(to);
      onComplete?.();
    }
  }
  requestAnimationFrame(frame);
}

// 缓动函数
function easeInOutQuad(t: number) {
  return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
}

3. 使用示例(如页面滚动、数字增长动画)

import { animate } from '@/utils/animate';

// 让页面平滑滚动到顶部
function scrollToTop() {
  const from = window.scrollY;
  animate(from, 0, 500, value => window.scrollTo(0, value));
}

// 数字增长动画
function animateNumber(from: number, to: number, el: HTMLElement) {
  animate(from, to, 1000, value => {
    el.innerText = Math.round(value).toString();
  });
}

二、问题

1. 问:你在项目中是如何封装动画函数的?为什么要这样做?

答:
在本项目(如 web-admin),我在 src/utils/animate.ts 封装了一个基于 requestAnimationFrame 的通用动画函数。这样可以在不同页面(如首页统计数字增长、平滑滚动等)复用,避免重复造轮子,也方便后续维护和扩展。


2. 问:你封装的动画函数支持哪些功能?项目中有哪些实际应用?

答:
我封装的动画函数支持属性过渡、缓动曲线、动画完成回调等功能。项目中用它实现了首页统计数字的平滑增长动画、页面平滑滚动到顶部、弹窗渐显等效果,提升了用户体验和页面的动感。


3. 问:为什么选择 requestAnimationFrame 实现动画?和 setTimeout 有什么区别?

答:
requestAnimationFrame 能让动画与浏览器刷新同步,保证动画流畅且节能,避免掉帧和卡顿。setTimeout/setInterval 可能导致动画不连贯,且在页面切换标签时仍然执行,浪费资源。项目中所有动画都用 requestAnimationFrame 实现,保证了性能和体验。


4. 问:动画函数如何支持不同的缓动效果?项目中有用到吗?

答:
动画函数通过传入不同的缓动函数(如 easeInOutQuad、linear、easeOutCubic 等)实现不同的动画节奏。项目中首页数字增长动画用的是 easeInOutQuad,让数字变化更自然,用户感知更好。


5. 问:你如何保证动画函数的可维护性和可扩展性?项目中有哪些实践?

答:
我将动画函数单独封装在 utils 目录,参数设计灵活,支持回调和自定义缓动函数。这样后续如果要扩展更多动画类型或支持并行动画,只需在 utils 里维护即可,项目中所有用到动画的地方都能统一调用,极大提升了代码的可维护性和复用性。