实现含HTML标签的JS实时打字动画,解决标签字符闪烁问题
问题解析与解决方案
你遇到的<字符闪烁问题,核心原因是当前代码在逐个输出转义后的HTML实体(比如<br>会被拆成&、l、t、;等字符),直到整个实体序列输出完毕,innerHTML才会把它解析成真正的<br>标签,这中间的字符片段就会造成闪烁。不需要提前执行解码函数,而是要调整动画逻辑,避免输出标签的字符片段。
解决思路
把API返回的原始HTML字符串,拆分为纯文本片段和完整HTML标签的组合:
- 纯文本片段:保持逐个字符输出,保留打字动画效果
- HTML标签:完整插入DOM,不拆分字符输出,彻底避免显示标签代码
修改后的完整代码
JavaScript
// API返回的原始HTML文本(无需转义,直接用接口返回的text值) let rawHtml = "<b>Here is some example text</b> followed by line breaks<br><br><br><br><br>and another line break<br><br><b>as well as some bold text.</b>"; // 把HTML拆分为「标签」和「纯文本」的片段数组 function splitHtmlIntoFragments(html) { const fragments = []; // 正则匹配:要么是完整的HTML标签,要么是标签外的纯文本 const regex = /(<[^>]+>|[^<]+)/g; let match; while ((match = regex.exec(html)) !== null) { fragments.push(match[0]); } return fragments; } const htmlFragments = splitHtmlIntoFragments(rawHtml); let fragmentIndex = 0; // 当前处理的片段索引 let charIndex = 0; // 当前文本片段的字符索引 let currentContent = ""; // 已经输出的内容 function typingAnimation(targetId) { const targetEl = document.getElementById(targetId); if (!targetEl) return; setTimeout(() => { const currentFragment = htmlFragments[fragmentIndex]; if (!currentFragment) return; if (currentFragment.startsWith("<")) { // 当前片段是HTML标签,直接完整添加 currentContent += currentFragment; fragmentIndex++; } else { // 当前片段是纯文本,逐个字符输出 if (charIndex < currentFragment.length) { currentContent += currentFragment[charIndex]; charIndex++; } else { // 文本片段输出完,切换到下一个片段 fragmentIndex++; charIndex = 0; } } // 更新DOM内容 targetEl.innerHTML = currentContent; // 继续动画直到所有片段处理完成 if (fragmentIndex < htmlFragments.length || charIndex < currentFragment.length) { typingAnimation(targetId); } }, 50); } // 跳过动画按钮逻辑 $("#skipAnimationBtn").on("click", () => { const targetEl = document.getElementById("typing-animation"); targetEl.innerHTML = rawHtml; fragmentIndex = htmlFragments.length; // 终止动画循环 }); // 启动打字动画 typingAnimation("typing-animation");
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <div id="parent"> <button id="skipAnimationBtn">点击跳过动画</button> <div id="typing-animation"></div> </div>
CSS
#parent { display: block; }
关键细节说明
- HTML片段拆分:用正则
/(<[^>]+>|[^<]+)/g精准识别完整的HTML标签和纯文本,确保标签不会被拆分成单个字符输出。 - 动画逻辑优化:标签直接完整插入DOM,只有纯文本部分做逐字输出,彻底解决标签字符闪烁的问题。
- 跳过动画优化:点击按钮后直接渲染完整的HTML内容,同时终止动画循环,避免后续无效执行。
内容的提问来源于stack exchange,提问作者Mickey Vershbow
相关产品推荐
相关产品推荐

