如何在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
相关产品推荐
相关产品推荐

