react-native-lyric如何实现歌词逐字绿色高亮播放效果
逐字高亮歌词实现方案

核心逻辑:你当前使用的歌词组件仅支持行级激活状态,没有内置逐字渲染能力,要实现参考动图的卡拉OK效果,需要在自定义行渲染函数里自行拆分单字做状态判断,具体实现步骤如下:
- 前置准备:逐字高亮的精准度依赖时间戳精度,如果有带逐字时间标签的歌词数据(比如KRC格式转换后的逐字歌词)效果最好;如果只有普通行级LRC歌词,可以按行总时长平均分配每个字的播放时间,实现近似效果。
- 行渲染改造:非当前播放行直接渲染整行灰色文字即可,当前激活行把整句歌词拆成单字数组,结合全局播放进度
currentTime判断每个字是否已经播放完成,播放完成的字设置为绿色,未播放的保持灰色。 - 丝滑效果优化:如果要实现动图里逐字扫过、不是整字突然变色的效果,可以给正在播放的单字加一层同内容的绿色文字遮罩,用动画驱动遮罩宽度从0到100%增长,配合
overflow: hidden就能实现颜色从左到右平滑过渡的效果。
基础实现代码
以下是基于你现有代码改造的基础版本,采用行时长平均分配的方案,如果你有逐字时间戳,替换掉单字时间计算逻辑即可:
<Lyric style={{ height: 500 }} lrc={lrc} currentTime={this.state.currentTime} lineHeight={40} activeLineHeight={50} lineRenderer={({ lrcLine: { millisecond, content }, index, active, }) => { // 非激活行直接渲染灰色文字 if (!active) { return ( <Text style={{ fontSize: 30, textAlign: "center", color: "gray", }} > {content} </Text> ) } // 计算当前行总时长:取下一行起始时间作为当前行结束时间,最后一行兜底3秒 const currentLineEnd = parsedLrcList[index + 1] ? parsedLrcList[index + 1].millisecond : millisecond + 3000 const lineTotalDuration = currentLineEnd - millisecond const charArray = content.split('') const perCharDuration = lineTotalDuration / charArray.length // 逐字渲染判断高亮状态 return ( <Text style={{ fontSize: 30, textAlign: "center" }}> {charArray.map((char, charIndex) => { const charEndTime = millisecond + (charIndex + 1) * perCharDuration const isPlayed = this.state.currentTime >= charEndTime return ( <Text key={charIndex} style={{ color: isPlayed ? '#22c55e' : 'gray' }} > {char} </Text> ) })} </Text> ) }} />
注意:代码里的
parsedLrcList是你把LRC文本解析后得到的行数组,结构和组件回调里的lrcLine一致,为[{millisecond: 数字时间戳, content: 歌词文本}]格式,你可以用任意LRC解析工具提前解析好传入。
进阶平滑效果实现思路
如果要完全匹配参考动图的扫字效果,不要用整字切换颜色的逻辑:
- 每个激活行的底层渲染整行灰色文字
- 上层盖一个
overflow: hidden的同尺寸容器,内部放整行绿色文字 - 用当前播放时间计算当前行的播放进度,驱动上层容器的宽度从0到整行宽度线性增长,就能实现字从左到右逐像素变绿的丝滑效果,性能比逐字做动画更好。
内容的提问来源于stack exchange,提问作者user998405
相关产品推荐
相关产品推荐

