如何在视频播放到Map指定的时间节点时精准触发对应函数
问题根因
progressUpdateInterval设置为1ms会导致每秒触发1000次进度回调,性能开销过高,自然会造成视频运行异常- 原有代码逻辑存在多处错误:
- 每次触发
onProgress都重复初始化hapticMap,完全无必要 - 用全等判断
hapticMap.has(data.currentTime)不可行:视频返回的currentTime是浮点数,刚好和预设时间完全相等的概率几乎为0 hapticMap.set(hapticSet)的写法不符合Map的API规范,缺少value参数,无法正常存储映射关系
- 每次触发
解决方案
1. 调整回调触发间隔
将progressUpdateInterval调整为100ms即可,既可以保证100ms以内的触发误差(人感知不到延迟),也不会产生过高的性能开销:
<Video onEnd={onEnd} onLoad={onLoad} onLoadStart={onLoadStart} posterResizeMode={'cover'} onProgress={onProgress} progressUpdateInterval={100} paused={paused} ref={(ref) => (videoPlayer.current = ref)} source={external ? { uri: videoURL } : videoURL} resizeMode={"contain"} style={{ flex: 1 }} > </Video>
2. 预定义触发映射和去重集合
将振动触发的时间映射提到组件外部存储,同时新增已触发时间的集合,避免同一个时间点重复触发振动:
// 预设振动触发规则:key为触发时间(单位秒,支持小数),value为振动类型 const HAPTIC_TRIGGER_MAP = new Map([ [7, Haptics.ImpactFeedbackStyle.Heavy], // 其余触发点按照该格式新增即可 ]) // 存储已触发过的时间点,避免重复调用 const triggeredTimeSet = new Set()
3. 重写onProgress逻辑
用区间判断代替全等判断,适配浮点数的时间误差:
const onProgress = (data) => { if (isLoading) return const currentTime = data.currentTime setCurrentTime(currentTime) for (const [triggerTime, feedbackStyle] of HAPTIC_TRIGGER_MAP) { // 触发条件:当前时间已超过触发时间、未触发过、误差小于100ms(和回调间隔对应) if (currentTime >= triggerTime && !triggeredTimeSet.has(triggerTime) && currentTime - triggerTime < 0.1) { Haptics.impactAsync(feedbackStyle) triggeredTimeSet.add(triggerTime) } } }
4. 补充重置逻辑
如果视频支持进度拖拽、重播功能,需要在onSeek、onLoad、重播触发的回调中执行triggeredTimeSet.clear()清空已触发集合,即可支持进度调整后重新触发对应时间点的振动。
内容的提问来源于stack exchange,提问作者Paulo Henrique Leal
相关产品推荐
相关产品推荐

