监听 HTMLMediaElement 播放状态的 RxJS 观察器
这是一个用于监听 HTMLMediaElement 播放状态的自定义 RxJS 观察器。当满足以下条件时,会自动输出播放记录:
- 播放时间超过指定秒数。
- 用户触发了暂停、播放、快进、快退、停止、结束等操作会自动输出播放记录。
整体设计思路
- 使用 RxJS 的 Subject 监听 HTMLMediaElement 的事件。
- 使用一个 Subject 作为检测的标记,当用户操作或超时时触发检测。
- 使用
onTimeUpdate
事件监听播放时间的变化。
参数
element
(HTMLMediaElement):需要监听的媒体元素。seconds
(Number):正常播放时间超过这个时间才会调用回调函数。
示例代码
import {
fromEvent,
bufferWhen,
merge,
filter,
map,
Subject,
switchMap,
interval,
takeUntil,
} from 'rxjs';
/**
* 订阅HTML媒体元素的事件并缓冲播放记录。
*
* @param {HTMLMediaElement} element - 要监听的HTML媒体元素。
* @param {number} seconds - 缓冲播放记录的间隔(秒)。
* @returns {Observable} - 一个发出缓冲播放记录的Observable。
*/
function subscribeEventToHtmlMediaElement(element, seconds) {
// 创建一个关于媒体元素用户操作的Observable
const userActionMap$ = merge(
...['play', 'pause', 'seeking', 'seeked', 'ended'].map(
action => fromEvent(element, action)
)
);
// 创建一个在每次用户操作后间隔一段时间的Observable,直到下一次操作
const intervalAfterEachUserActionSubject$ = userActionMap$.pipe(
switchMap(() => {
return interval(seconds * 1000).pipe(
takeUntil(userActionMap$)
);
})
);
// 用于缓冲用户操作和间隔的主题
const bufferWhenSubject$ = new Subject();
merge(userActionMap$, intervalAfterEachUserActionSubject$).subscribe(bufferWhenSubject$);
// 基于时间更新发出缓冲播放记录的Observable
return fromEvent(element, 'timeupdate').pipe(
map(() => element.currentTime),
bufferWhen(() => bufferWhenSubject$),
filter((timeList) => timeList.length > 0),
map((timeList) => [timeList[0], timeList[timeList.length - 1]]),
);
}
客户端使用
// 首先选中元素
const element = document.querySelector('.video');
// 每5秒记录一次播放时间
subscribeEventToHtmlMediaElement(element, 5).subscribe((timeList)=>{
// timeList形如[0, 5], 但是由于timeupdate事件的特性,很多时候都不是整数
console.log(timeList);
});
下图是里面一个不容易理解的switchMap的图解,觉得挺好,就贴到这儿
- switchMap原文参考(dev.to/rxjs/about-…)