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

如何在React JS网站实现点击播放按钮朗读内容并高亮功能?

功能可行性与实现方案

完全可以实现,核心依赖Web Speech API完成文本朗读,结合DOM操作实现同步高亮。下面是具体的实现步骤和代码示例:

一、基础准备:标记可朗读元素

给所有需要朗读的内容元素添加统一类名(比如read-target),方便后续批量获取:

  • 段落:<p className="read-target">...</p>
  • 列表项:<li className="read-target">...</li>
  • 图片:给图片标签加类,后续读取alt属性:<img className="read-target" alt="这是一张风景图" src="..." />

二、核心实现逻辑

1. 状态管理(React组件内)

在组件中定义必要状态,控制朗读流程:

import { useState, useEffect, useRef } from 'react';

function App() {
  const [isReading, setIsReading] = useState(false);
  const [currentIndex, setCurrentIndex] = useState(-1);
  const targetElementsRef = useRef([]);
  const synthRef = useRef(window.speechSynthesis);
  const utteranceRef = useRef(null);

2. 初始化可朗读元素列表

在useEffect中获取所有标记的元素,整理出朗读文本和DOM引用:

useEffect(() => {
  const elements = Array.from(document.querySelectorAll('.read-target'));
  const targetList = elements.map(el => {
    let text = el.textContent.trim();
    // 处理图片的alt文本
    if (el.tagName === 'IMG') {
      text = el.alt || '无描述的图片';
    }
    return { text, element: el };
  });
  targetElementsRef.current = targetList;
}, []);

3. 朗读与高亮同步函数

实现朗读控制逻辑,包括开始、暂停、切换高亮:

const startReading = () => {
  if (isReading) {
    // 暂停/继续逻辑
    if (synthRef.current.speaking) {
      synthRef.current.pause();
      setIsReading(false);
    } else if (synthRef.current.paused) {
      synthRef.current.resume();
      setIsReading(true);
    }
    return;
  }

  setIsReading(true);
  let index = currentIndex === -1 ? 0 : currentIndex;

  const readNext = () => {
    if (index >= targetElementsRef.current.length) {
      // 朗读结束,重置状态
      setIsReading(false);
      setCurrentIndex(-1);
      targetElementsRef.current.forEach(item => item.element.classList.remove('highlighted'));
      return;
    }

    const { text, element } = targetElementsRef.current[index];
    // 移除上一个元素的高亮
    if (index > 0) {
      targetElementsRef.current[index - 1].element.classList.remove('highlighted');
    }
    // 高亮当前元素
    element.classList.add('highlighted');
    // 滚动到当前元素(可选)
    element.scrollIntoView({ behavior: 'smooth', block: 'center' });

    setCurrentIndex(index);
    const utterance = new SpeechSynthesisUtterance(text);
    utteranceRef.current = utterance;

    // 朗读结束后读取下一个
    utterance.onend = () => {
      index++;
      readNext();
    };

    synthRef.current.speak(utterance);
  };

  readNext();
};

// 停止朗读
const stopReading = () => {
  synthRef.current.cancel();
  setIsReading(false);
  setCurrentIndex(-1);
  targetElementsRef.current.forEach(item => item.element.classList.remove('highlighted'));
};

4. 播放按钮与样式

添加播放/暂停/停止按钮,以及高亮样式:

return (
  <div>
    <nav className="navbar">
      <button onClick={startReading}>
        {isReading ? '暂停朗读' : '开始朗读'}
      </button>
      <button onClick={stopReading} disabled={!isReading}>
        停止朗读
      </button>
    </nav>
    <main>
      <p className="read-target">这是第一段需要朗读的文本内容。</p>
      <ul>
        <li className="read-target">列表项一:测试朗读功能</li>
        <li className="read-target">列表项二:同步高亮效果</li>
      </ul>
      <img className="read-target" alt="一只可爱的猫咪" src="cat.jpg" />
    </main>
    <style jsx>{`
      .highlighted {
        background-color: #fff3cd;
        transition: background-color 0.3s ease;
      }
    `}</style>
  </div>
);
}

export default App;

三、注意事项

  • 兼容性:Web Speech API支持Chrome、Edge、Firefox等现代浏览器,移动端部分浏览器可能有限制,可提前做兼容性检测。
  • 语音选择:可通过speechSynthesis.getVoices()获取系统可用语音,设置给utterance.voice实现多语言朗读。
  • 性能优化:如果页面内容较多,可分批加载朗读元素,避免一次性占用过多内存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 00:05:13