需求分析
让数字动起来,需要一个开始数字,一个结束数字,一个动画时间。
根据动画时间,开始数字,结束数字,可以计算出每次的变动平均值。
利用浏览器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