You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

鼠标悬停段落元素时字符随机消失问题求助

问题解决:鼠标悬停时字符随机消失的修复

问题分析

你遇到的字符随机消失问题,核心原因有两个:

  • 段落的mouseover事件会重复触发highlight函数,每次触发都会重新将文本拆分为字符并生成新的span替换原innerHTML,过程中索引处理错误导致字符丢失;
  • 单词处理逻辑中固定循环6次取字符,未考虑数组边界和实际文本结构,会导致越界取到undefined,最终显示为空。

解决方案

关键修改思路

  1. 提前构建带span的DOM结构:在fillParagraph生成文本时直接用span包裹字符和单词,避免后续重复修改innerHTML;
  2. 用CSS伪类实现高亮:替换JS绑定的mouseover/mouseout事件,用:hover伪类实现高亮,更稳定高效;
  3. 修复单词识别逻辑:正确识别连续的字母序列作为单词,而非固定截取6个字符。

修正后的核心代码

const garbage = ["`", "~", "!", "@", "#", "$", "%", "^", "&", "*", "-", "_", "=", "+"];
// 移除原单词里的前置空格,避免干扰识别
const wordBank = ["jujube", "muzzle", "puzzle", "whizzo", "jimply", "jinxed", "fezzes", "queazy"];
const numOfRows = 8;

const password = wordBank[randomNum(0, wordBank.length)];

function fillText() {
    fillParagraph("left-p");
    fillParagraph("right-p");
}

function fillParagraph(pId) {
    let spanElements = [];
    let wordPos = [];
    let counter = 0;

    // 生成3个不重叠的单词位置
    while (counter < 3) {
        let validPos = false;
        while (!validPos) {
            validPos = true;
            const randomNumber = randomNum(0, (12 * numOfRows) - 6);
            for (let pos of wordPos) {
                if (Math.abs(randomNumber - pos) <= 6) {
                    validPos = false;
                    break;
                }
            }
            if (validPos) {
                wordPos.push(randomNumber);
                counter++;
            }
        }
    }

    // 构建每个位置的元素:单词或符号
    for (let i = 0; i < numOfRows * 12; ) {
        // 每12个字符换行
        if (i !== 0 && i % 12 === 0) {
            spanElements.push(document.createElement('br'));
        }

        // 当前位置是单词起始点
        if (wordPos.includes(i)) {
            const word = wordBank.shift();
            const wordSpan = document.createElement('span');
            wordSpan.className = 'word';
            wordSpan.textContent = word;
            spanElements.push(wordSpan);
            // 跳过单词占用的位置
            i += word.length;
        } else {
            // 生成单个符号的span
            const charSpan = document.createElement('span');
            charSpan.className = 'char';
            charSpan.textContent = garbage[randomNum(0, garbage.length - 1)];
            spanElements.push(charSpan);
            i++;
        }
    }

    // 渲染到页面
    const paragraph = document.getElementById(pId);
    paragraph.innerHTML = '';
    spanElements.forEach(el => paragraph.appendChild(el));
}

function randomNum(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

对应的CSS样式:

/* 单个符号和单词的高亮效果 */
.char:hover, .word:hover {
    background-color: yellow;
}

/* 保持排版整齐 */
#left-p, #right-p {
    white-space: pre-line;
    font-family: monospace;
    line-height: 1.2;
}

修改说明

  1. DOM构建时机调整:在fillParagraph中直接创建span元素,一次性添加到段落,彻底避免重复修改innerHTML导致的字符丢失;
  2. 单词位置生成优化:改用while循环生成3个不重叠的单词位置,逻辑更清晰,避免原代码中循环次数冗余的问题;
  3. CSS高亮替代JS事件:用:hover伪类实现高亮,无需绑定大量事件,避免事件重复触发的冲突;
  4. 修复单词处理逻辑:直接使用单词本身的长度跳过位置,避免固定6次循环的越界问题,同时清理了原单词数组中的前置空格,保证文本结构正确。

内容的提问来源于stack exchange,提问作者someCoder21

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 08:01:23