近期做了个数据大屏的项目,项目中用到一些数字动画效果,本来想用一些第三方库来做,但是想想会增加项目体积,就没有用第三方库实现,后来就自己用自定义指令来实现数字动画效果,记录一下
(1)数字滚动效果
实现步骤:
一、将要滚动的数字进行拆分,拆分成一个一个数字,每个数字单独做滚动效果;
二、将每个数字的 DOM 元素内容换成 0123456789
, 利用 css 属性 writing-mode:vertical-rl
和 text-orientation:upright
将这一串数字变成竖向展示;
三、配合 transform
属性,对元素的 Y 轴进行偏移,加上 transition
来实现动画过渡效果;
const transform = {
mounted(el, binding) {
const { transform } = binding.value;
el.style.transform = `translate3d(-50%, -${(transform || 9) * 10}%, 0)`;
// 为了让 0 也有动画过渡效果
if (transform == 0) {
el.innerHTML = "1234567890";
}
},
updated(el, binding) {
const { transform } = binding.value;
// 还原一开始定义好 0123456789 的数字字符串,保证偏移的位置一致
el.innerHTML = "0123456789";
el.style.transform = `translate3d(-50%, -${(transform || 9) * 10}%, 0)`;
if (transform == 0) {
el.innerHTML = "1234567890";
}
},
};
(2)数字变化效果
数字变化效果的实现比较简单,大致步骤就是设置一个定时器,逐渐增加数值,直到大于等于目标值,停止定时器;
const animateDigit = {
updated(el, binding) {
let { innerHTML } = el;
const oldData = binding.oldValue && binding.oldValue.origin;
const originData = binding.value && binding.value.origin;
// 非数值、空值、前后值相同值时直接返回
if (!innerHTML || isNaN(innerHTML) || oldData == originData) {
return;
}
innerHTML = originData;
let timer = null;
let count = 0;
// 增长速率
let speed = +innerHTML / 50;
// 定时器
timer = setInterval(() => {
let number = Math.ceil(Math.random() * speed);
count += number;
if (+innerHTML <= count) {
count = innerHTML;
// 达到目标值,清除定时器
clearInterval(timer);
}
el.innerHTML = count;
}, 10);
},
};