原文链接:Animating Number Counters | CSS-Tricks (挑有用的部分翻译)
作者 Carter Li 翻译 Sirice
注:本文中使用的 code-pen jsrun 等嵌入式代码运行组件受浏览器版本的直接限制,Chrome 78 及以下版本无法正确运行,请更新您的浏览器版本。
数字跳动动画,指的是从 1 跳到 2,2 跳到 3,3 跳到 4……的页面效果,广泛用于 dashboard,可以对数字增加观感上的活力。以前的方法普遍是用 JS 更改 DOM 数字,现在提出一种新方法去用纯 CSS实现。
JavaScript 实现方案
我们可以用纯逻辑的思路,用 JS 的setInterval()
方法改变数字。但还有一个更奇特 (fancier) 的方法来实现:
<div id="value">100</div>
/**
* timeStamp 事件属性可返回一个时间戳。指示发生事件的日期和时间
* (timestamp - startTimestamp) / duration
* 这句 timestamp 会持续变,减去初始时间戳除以持续时间即可代替setInterval()
*/
function animateValue(obj, start, end, duration) {
let startTimestamp = null;
const step = (timestamp) => {
// console.log("timestamp",timestamp)
if (!startTimestamp) startTimestamp = timestamp;
const progress = Math.min((timestamp - startTimestamp) / duration, 1);
// console.log("progress",progress)
obj.innerHTML = Math.floor(progress * (end - start) + start);
if (progress < 1) {
window.requestAnimationFrame(step);
}
};
window.requestAnimationFrame(step);
}
const obj = document.getElementById("value");
animateValue(obj, 100, 0, 5000);
注:这里有 2 个知识点:
window.requestAnimationFrame(callback)
timeStamp
对象
Pure CSS 实现
跟进最新的浏览器对 CSS 的特性支持:CSS.registerProperty
和 @property
,我们可以使用 CSS 动画变量。
这个技巧是声明一个整数类型的自定义属性,这样的话可以作为一个任意整数差值进动画中。
代码示例:
@property --num {
syntax: "<integer>";
initial-value: 0;
inherits: false;
}
div {
transition: --num 1s;
counter-reset: num var(--num);
}
div:hover {
--num: 10000;
}
div::after {
content: counter(num);
}
注:这个特性是 Chrome >78 以上新支持的,因此这个方法对于旧版本浏览器并不友好。
CSS content
属性能用于显示中心的数字,但还需要 counter
将数字转换成字符因为 content
只接受输出为 <string>
的值。
类型化的 CSS 变量也可以用在 @keyframes
中。
这个方法的缺点是,counters 只支持整数,意味着小数是不行的,所以我们要想办法把整数和小数部分分开显示。
怎么对小数做这个效果?
我们可以将小数转换为整数,只要按以下步骤进行:
- 声明一个整数类型的 CSS 变量 (
<integer>
CSS variable),用initial-value
赋值。 - 然后用
calc()
对这个值取整:--integer: calc(var(--number))
@property --integer {
syntax: "<integer>";
initial-value: 0;
inherits: false;
}
--number: 1234.5678;
--integer: calc(var(--number)); /* 1235 */
有时我们仅需要整数部分,这里有个技巧:--integer: max(var(--number) - 0.5, 0)
。这个技巧仅对正数有效,这种情况甚至连calc()
都不需要。
/* @property --integer */
--number: 1234.5678;
--integer: max(var(--number) - 0.5, 0); /* 1234 */
同理,我们可以抽出小数部分。然后将其用 counter
转换为字符串。
content: "string1" var(--string2) counter(--integer)...;
以下为一个完整示例
其他示例
这是一个将字符应用同样效果的示例,将“CSS”变为“YES”
另一个 tip:
我们可以使用 JavaScript 调试捕获自定义属性的计算值的值
getComputedStyle(element).getPropertyValue('--variable')
其他实现方式参考
- 非常好用的 vue 数字滚动插件 vue-countTo
github live demo: vue-count-to