如何实现文字淡入淡出的正确循环动画?
文字淡入淡出动画修复方案
问题根源
- 定时器堆积:每次调用
homeCaptions()都会重新遍历所有.js-caption并生成新的setTimeout,多次循环后多个定时器同时触发,导致动画顺序混乱、卡顿。 - 无过渡切换:清空容器时直接调用
empty(),没有淡出过渡,且文字是一次性全部添加,未实现逐个淡入的效果。
修改方案
- 采用递归遍历的方式,完成当前caption的动画后再处理下一个,避免定时器堆积。
- 给容器清空添加淡出动画,切换时更自然。
- 实现文字逐个淡入的效果,而非一次性显示。
- 用变量保存当前定时器,防止重复触发。
完整代码
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="js-caption">test the first sentence</div> <div class="js-caption">test the second sentence</div> <div class="caption-loaded"></div>
CSS
.js-caption{ display:none; } .caption-item { opacity: 0; transition: opacity 0.5s ease; } .caption-loaded { min-height: 1.5em; /* 避免容器高度跳动 */ }
JavaScript
$(function(){ let currentTimer = null; let captions = $('.js-caption'); let currentIndex = 0; function homeCaptions(){ // 清理之前的定时器,避免堆积 if(currentTimer) clearTimeout(currentTimer); let currentCaption = captions.eq(currentIndex); let text = currentCaption.text(); animateText(text, function(){ // 切换到下一个caption,循环回到开头 currentIndex = (currentIndex + 1) % captions.length; // 延迟后启动下一轮动画 currentTimer = setTimeout(homeCaptions, 2000); // 停留时间可调整 }); } function animateText(text, callback){ let $container = $('.caption-loaded'); // 先淡出当前内容 $container.fadeOut(300, function(){ $container.empty(); let words = text.split(" ").map(word => word + " "); function addWord(index){ if(index >= words.length){ // 所有文字添加完成后淡入容器 $container.fadeIn(300); callback(); return; } let $span = $('<span class="caption-item">' + words[index] + '</span>'); $container.append($span); // 延迟显示当前文字 setTimeout(() => { $span.css('opacity', 1); addWord(index + 1); }, 300); // 文字间隔时间可调整 } addWord(0); }); }; // 启动动画 homeCaptions(); });
代码说明
- 递归遍历:通过
currentIndex跟踪当前处理的caption,完成一个后切换到下一个,循环往复。 - 过渡效果:容器清空时先淡出,文字逐个设置
opacity实现淡入,切换更流畅。 - 定时器管理:用
currentTimer保存当前定时器,每次启动前清理,避免堆积导致的冲突。
内容的提问来源于stack exchange,提问作者DigitalDesigner
相关产品推荐
相关产品推荐

