前端数字动效

55 阅读2分钟

需求分析

让数字动起来,需要一个开始数字,一个结束数字,一个动画时间。
根据动画时间,开始数字,结束数字,可以计算出每次的变动平均值。
利用浏览器window.requestAnimationFrame方法,一直变动数字,直到数字与结束数字相等。

代码(仅提供思路,具体使用请结合实际情况进行效果测试)

vue版本

/** 
    @params num {Ref<number>} 需要变动的变量
    @params from {unknown} 变动前的数值
    @params to {unknown} 变动后的数值
    @params time {number} 动画次数
*/
const handleSetCount = (num, from, to, count) => {
  let start = Number(from) || 0; // 变动前的数据
  const end = Number(to); // 变动后数据
  if(isNaN(end)) return num.value = to; // 变动后数据如果不是数字则直接变动
  const speed = (end - start) / count; // 计算出变动的间隔 如从1变到100,动画次数99次,则speed = 1
  const checkFn = end < start? Math.max: Math.min; // 用于检测变动的数值是否已经满足条件
  const tick = () => window.requestAnimationFrame(() => {
    start += speed; //
    const next_val = checkFn(start | 0, end); // 美观处理,不显示小数 -> 如显示的数据存在小数 checkFn(start, end);
    num.value = next_val; // 赋值,界面数字发生变化,产生动画效果
    if(next_val !== end) { // 当变动值不等于end时,持续动画,直到与end相等
      tick();
    }
  });
  tick();
}

// 测试用例 vue 版本
 const msg = ref<number>(10);
 handleSetCount(msg, msg.value, 1000, 100) // 希望msg的数值在100次动画内,从原先值变化到1000

react版本

/** 
    @params num {Ref<number>} 需要变动的变量
    @params from {unknown} 变动前的数值
    @params to {unknown} 变动后的数值
    @params time {number} 动画次数
*/
const handleSetCount = (setNum, from, to, count) => {
  let start = Number(from) || 0; // 变动前的数据
  const end = Number(to); // 变动后数据
  if(isNaN(end)) return num.value = to; // 变动后数据如果不是数字则直接变动
  const speed = (end - start) / count; // 计算出变动的间隔 如从1变到100,动画次数99次,则speed = 1
  const checkFn = end < start? Math.max: Math.min; // 用于检测变动的数值是否已经满足条件
  const tick = () => window.requestAnimationFrame(() => {
    start += speed; //
    const next_val = checkFn(start | 0, end); // 美观处理,不显示小数 -> 如显示的数据存在小数 checkFn(start, end);
    setNum(next_val); // 赋值,界面数字发生变化,产生动画效果
    if(next_val !== end) { // 当变动值不等于end时,持续动画,直到与end相等
      tick();
    }
  });
  tick();
}

// 测试用例 vue 版本
 const [msg, setMsg] = useState(10);
 handleSetCount(setMsg, msg, 1000, 100) // 希望msg的数值在100次动画内,从原先值变化到1000

注意点

数字在17位开始 使用 Number 方法 会出现精度丢失的情况

Number(112121212121211212) // 112121212121211220