在现代网页设计中,为了提升用户体验,常常会添加一些富有创意和交互性的元素。其中,数字动态递增效果就是一种能够吸引用户注意力,增强页面生动性的设计技巧。
代码实现概述
我们先来看一段实现数字动态递增效果的 JavaScript 代码。这段代码主要完成了以下几个关键任务:
- 获取页面元素:通过
document.querySelector
和document.querySelectorAll
方法,分别获取到包含数字的父容器(list-container
类)以及所有需要动态递增的数字元素(num
类)。
const container = document.querySelector('.list-container');
const numElements = document.querySelectorAll('.num');
- 存储原始数据:遍历所有数字元素,提取每个数字的原始值(去除非数字字符)以及是否包含+号后缀,并将这些信息存储在元素的自定义属性中。
numElements.forEach(element => {
const originalText = element.textContent;
const originalValue = originalText.replace(/\D/g, '');
const hasPlus = originalText.includes('+');
element.dataset.original = originalValue;
element.dataset.plus = hasPlus? '+' : '';
});
- 使用IntersectionObserver:创建一个
IntersectionObserver
来观察父容器。当父容器有 50% 进入视口时,触发相应的回调函数。
const containerObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// 当容器进入视口时的操作
}
});
}, {
threshold: 0.5 });
containerObserver.observe(container);
- 数字动态递增动画:在父容器进入视口的回调函数中,为每个数字元素启动动态递增动画。通过定时器,逐步增加数字的值,直到达到原始值,并在需要时添加
+
号后缀。
numElements.forEach(element => {
const target = parseInt(element.dataset.original);
const hasPlus = element.dataset.plus === '+';
let current = 0;
if (element.intervalId) {
clearInterval(element.intervalId);
}
element.textContent = current;
const duration = 3000;
const steps = 30;
const increment = Math.ceil(target / steps);
const interval = duration / steps;
element.intervalId = setInterval(() => {
current = Math.min(current + increment, target);
element.textContent = current;
if (current >= target) {
element.textContent = target + (hasPlus? '+' : '');
clearInterval(element.intervalId);
}
}, interval);
});
详细解析
获取和处理元素
-
获取页面元素是实现任何交互效果的基础。document.querySelector方法用于获取页面中第一个匹配指定选择器的元素,而document.querySelectorAll方法则返回所有匹配选择器的元素列表。在我们的例子中,通过这两个方法分别获取到父容器和所有数字元素,为后续操作提供了目标对象。
-
提取数字的原始值和后缀是为了在动画过程中能够准确地恢复到原始状态。使用正则表达式/\D/g去除非数字字符,轻松提取出数字的实际值。同时,通过判断原始文本中是否包含+号,确定是否需要在最终显示时添加后缀。将这些信息存储在自定义属性dataset中,方便后续获取和使用。
IntersectionObserver 的作用
-
IntersectionObserver是 JavaScript 提供的一个非常强大的 API,它允许我们异步观察目标元素与祖先元素或视口的交集变化情况。在我们的代码中,使用IntersectionObserver来观察父容器与视口的交集。当父容器有 50% 进入视口(通过threshold设置为 0.5 来控制)时,触发回调函数。这样做的好处是,只有当用户有可能看到这些数字时,才会启动动画,避免了不必要的资源消耗,提升了页面性能。
-
数字动态递增动画的实现
在动画实现部分,首先确定每个数字元素的目标值(即原始值)以及是否有+号后缀。然后,通过设置定时器setInterval来逐步增加当前显示的数字值。这里通过计算总时长(duration)、步数(steps)和每次递增的幅度(increment)来控制动画的速度和效果。在每次定时器触发时,更新当前数字值,并判断是否达到目标值。如果达到目标值,则添加后缀并清除定时器,完成动画过程。同时,为了避免多次启动定时器导致动画混乱,在每次启动前先清除可能存在的旧定时器。
完整代码
<script>
document.addEventListener('DOMContentLoaded', function () {
// 获取父容器和所有数字元素
const container = document.querySelector('.list-container');
const numElements = document.querySelectorAll('.num');
// 存储每个数字的原始值和后缀(如+号)
numElements.forEach(element => {
const originalText = element.textContent;
// 提取数值部分(移除非数字字符)
const originalValue = originalText.replace(/\D/g, '');
// 检查原始文本是否包含+号
const hasPlus = originalText.includes('+');
// 将数据存储在元素属性中
element.dataset.original = originalValue;
element.dataset.plus = hasPlus ? '+' : '';
});
// 创建观察父容器的 IntersectionObserver
const containerObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// 当容器进入视口时,启动所有数字的动画
numElements.forEach(element => {
const target = parseInt(element.dataset.original);
const hasPlus = element.dataset.plus === '+';
let current = 0;
// 清除之前的定时器(如果存在)
if (element.intervalId) {
clearInterval(element.intervalId);
}
// 重置为初始状态
element.textContent = current;
// 动画参数
const duration = 3000; // 总时长3秒
const steps = 30;
const increment = Math.ceil(target / steps);
const interval = duration / steps;
// 启动新的定时器
element.intervalId = setInterval(() => {
current = Math.min(current + increment, target);
element.textContent = current;
// 当达到目标值时添加后缀并清除定时器
if (current >= target) {
element.textContent = target + (hasPlus ? '+' : '');
clearInterval(element.intervalId);
}
}, interval);
});
}
});
}, {
threshold: 0.5 }); // 当容器50%进入视口时触发
// 开始观察父容器
containerObserver.observe(container);
});
</script>
<div class="list-container">
<span class="num">2016</span>
<span class="num">400</div>
<span class="num">2000</div>
</div>
总结
通过以上步骤,我们成功地实现了网页中数字动态递增的效果。从获取元素、存储数据,到利用IntersectionObserver触发动画,再到具体的动画实现,每一步都紧密相连,共同构建了这个有趣的交互效果。这种数字动态递增效果不仅能够提升页面的视觉吸引力,还能在一定程度上引导用户关注重要的数据信息。