多行文本打字光标效果实现:解决光标消失与末尾字符未变白问题
多行文本打字光标效果实现:解决光标消失与末尾字符未变白问题
嘿,我看了你遇到的两个问题——光标消失和每行最后一个字符一直黑,咱们一步步来解决它们:
问题根源分析
- 光标消失:你每次处理完一行就移除了光标,最后添加的光标定位计算有偏差;而且初始HTML里的行元素自带文本,你创建span后直接移除第一个子节点,导致DOM节点索引混乱,影响光标位置和显示。
- 最后字符变黑:
childNodes的索引逻辑出错,当currentChar走到文本长度时,你试图修改currentChar-1的字符颜色,但因为节点索引混乱,这个操作没作用到正确的字符上。
修复后的完整代码
HTML
<div class="top-container"> <h1> <span class="text" id="line1"></span><br> <span class="text" id="line2"></span><br> <span class="text" id="line3"></span> </h1> </div>
CSS
.top-container h1 { font-size: 5rem; font-weight: 950; line-height: 1.2; white-space: nowrap; background-color: black; position: relative; } .top-container h1 .text { display: inline-block; position: relative; } .cursor { display: inline-block; width: 0.15em; height: 1em; background-color: white; animation: blink-caret 0.75s step-end infinite; vertical-align: bottom; } @keyframes blink-caret { 50% { background-color: transparent; } } .button-container { display: flex; justify-content: space-evenly; align-items: center; width: 100%; margin-top: 200px; }
JavaScript
document.addEventListener("DOMContentLoaded", function() { const lines = [ { element: document.getElementById("line1"), text: "Lorem ipsum dolor" }, { element: document.getElementById("line2"), text: "sit" }, { element: document.getElementById("line3"), text: "amet, consectetur adipiscing elit." } ]; let currentLine = 0; let currentChar = 0; let currentCursor = null; function createCursor() { const cursor = document.createElement("span"); cursor.className = "cursor"; return cursor; } function type() { if (currentLine < lines.length) { const line = lines[currentLine]; const text = line.text; // 先清空行元素,避免原有文本干扰 line.element.innerHTML = ""; // 预先创建所有黑色字符span for (let i = 0; i < text.length; i++) { const span = document.createElement("span"); span.textContent = text[i]; span.style.color = "black"; line.element.appendChild(span); } // 创建光标并添加到当前行 currentCursor = createCursor(); line.element.appendChild(currentCursor); function typeChar() { if (currentChar < text.length) { // 直接通过children获取span,避免childNodes包含文本节点的问题 line.element.children[currentChar].style.color = "white"; currentChar++; setTimeout(typeChar, 40); } else { // 确保最后一个字符变白 line.element.children[currentChar - 1].style.color = "white"; // 移除当前行的光标 if (currentCursor) { currentCursor.remove(); currentCursor = null; } currentLine++; currentChar = 0; setTimeout(type, 200); // 增加换行延迟,体验更自然 } } typeChar(); } else { // 在最后一行添加闪烁光标 const lastLine = lines[lines.length - 1].element; currentCursor = createCursor(); lastLine.appendChild(currentCursor); } } type(); });
关键修改点
- HTML优化:清空了行元素的初始文本,避免后续DOM操作混乱。
- 光标逻辑调整:
- 单独封装光标创建函数,统一管理光标实例
- 去掉了容易出错的绝对定位,改用inline-block+垂直对齐,确保光标始终显示在正确位置
- 字符颜色修复:使用
children而非childNodes获取字符span,因为children只返回元素节点,不会包含文本节点,索引更准确 - DOM清理:每行开始前先清空元素内容,避免旧节点干扰
这样修改后,光标会正常闪烁,每行的所有字符都会正确变白,完全解决你遇到的两个问题~
备注:内容来源于stack exchange,提问作者Andy G
相关产品推荐
相关产品推荐

