jiker-tcplayer
Version:
tcplayer in Jiker
197 lines (189 loc) • 6.15 kB
JavaScript
function VideoEvent(player) {
this.videoInstance = player
this.listenVideo();
}
VideoEvent.prototype.init = function init() {
this.clearWatchTimer();
this.duration = 0;
this.startPoint = 0;
this.current = null;
this.lastTimePoint = null;
this.Timer = null;
// 初始化记录数据
this.watching = []; // 正在观看
this.viewed = []; // 历史已观看
this.watchDuration = 0; // 观看时长
// 初始化播放器
this.callbackMap = new Map();
this.is_ended = false;
};
// 事件监听,把事件类型与回调放在一个map对象里
VideoEvent.prototype.on = function on(type, callback) {
this.callbackMap.set(type, callback);
};
// 视频监听事件
VideoEvent.prototype.listenVideo = function listenVideo() {
this.videoInstance.on('durationchange', () => {
this.removeNodeByClassName('custom-viewed-bar');
this.removeNodeByClassName('custom-append-bar');
this.duration = this.videoInstance.duration();
});
this.videoInstance.on('ended', () => {
this.is_ended = true;
const onEnded = this.callbackMap.get('ended');
if (onEnded instanceof Function) {
onEnded(this.is_ended);
}
});
this.videoInstance.on('ratechange', () => {
const cb = this.callbackMap.get('ratechange');
if (cb instanceof Function) {
// 获取当前播放倍数
// 暂不支持
// const rate = this.videoInstance.player().playbackRate();
const rate = 1;
cb(rate);
}
});
this.videoInstance.on('play', () => {
this.beginWatchTimer();
this.dealPlay();
});
this.videoInstance.on('timeupdate', () => {
const durCurrent = this.videoInstance.currentTime();
if (
this.current &&
this.lastTimePoint !== null &&
Math.abs(durCurrent - this.lastTimePoint) > 2
) {
this.dealPause();
this.dealPlay();
this.lastTimePoint = durCurrent;
return;
}
this.lastTimePoint = durCurrent;
if (this.current) {
this.current.style.setProperty(
'width',
`${100 * ((durCurrent - this.startPoint) / this.duration)}%`
);
}
});
this.videoInstance.on('pause', () => {
clearInterval(this.Timer);
this.dealPause();
});
};
VideoEvent.prototype.dealPlay = function dealPlay() {
this.startPoint = this.videoInstance.currentTime() - 0.5;
if (this.startPoint < 0) this.startPoint = 0;
if (!document.getElementById('tcplayer-video-player')) return;
const video = document
.getElementById('tcplayer-video-player')
.getElementsByClassName('vjs-progress-holder')[0];
this.current = document.createElement('div');
this.current.className = 'custom-append-bar';
this.current.style.setProperty('left', `${100 * (this.startPoint / this.duration)}%`);
this.current.style.setProperty('background-color', '#1764E8');
this.current.style.setProperty('height', '100%');
this.current.style.setProperty('position', 'absolute');
video.append(this.current);
};
VideoEvent.prototype.dealPause = async function dealPause() {
this.current = null;
const pauseTime = this.lastTimePoint || this.videoInstance.currentTime();
if (this.startPoint < pauseTime) {
const duration = this.watchDuration;
this.clearWatchTimer();
await this.callbackMap.get('record')({
stopTime: pauseTime,
duration,
currentPoints: [this.startPoint, pauseTime]
});
}
};
// 清除观看计时
VideoEvent.prototype.clearWatchTimer = function clearWatchTimer() {
clearInterval(this.Timer);
this.watchDuration = 0;
};
// 开始观看计时
VideoEvent.prototype.beginWatchTimer = function beginWatchTimer() {
this.Timer = setInterval(() => {
this.watchDuration += 1;
}, 1000);
};
VideoEvent.prototype.dealWatchingList = function dealWatchingList(viewed = [], watching = []) {
const list = [];
const arr = [...watching, ...viewed];
const getBlock = num => {
let min = null;
arr.forEach(item => {
if (item[0] > num) {
if (min === null) {
min = item;
} else if (item[0] < min[0]) {
min = item;
}
}
});
if (min !== null) {
arr.forEach(item => {
if (item[1] > min[1]) {
if (item[0] <= min[1]) {
// eslint-disable-next-line prefer-destructuring
min[1] = item[1];
}
}
});
list.push(min);
getBlock(min[1]);
}
};
getBlock(-1);
return list;
};
// 设置节点
VideoEvent.prototype.setViewedPoints = function setViewedPoints(duration, viewed) {
if (!document.getElementById('tcplayer-video-player')) return;
const a = document.getElementById('tcplayer-video-player').getElementsByClassName('vjs-progress-holder')[0];
viewed.forEach(arr => {
const [start, end] = arr;
const c = document.createElement('div');
// start/duration最大只能1
const p = start / duration;
c.style.setProperty('left', `${(p > 1 ? 1 : p) * 100}%`);
c.className = 'custom-viewed-bar';
const coloredWidth =
((end - start) / duration) * 100 > 100 ? 100 : ((end - start) / duration) * 100;
c.style.setProperty('width', `${coloredWidth}%`);
c.style.setProperty('background-color', '#FFCC00');
c.style.setProperty('height', '100%');
c.style.setProperty('position', 'absolute');
a.insertBefore(c, a.children[1]);
});
};
// 移除节点
VideoEvent.prototype.removeNodeByClassName = function removeNodeByClassName(name) {
const nodeList = document.getElementsByClassName(name);
const { length } = nodeList;
for (let i = length - 1; i >= 0; i -= 1) {
nodeList[i].remove();
}
};
// 设置视频上次播放时间
VideoEvent.prototype.setCurrentTime = function setCurrentTime(lastPlayPosition, viewed = []) {
if (!this.videoInstance) {
setTimeout(() => {
this.setCurrentTime(lastPlayPosition);
}, 500);
} else {
this.videoInstance.currentTime(lastPlayPosition);
this.setViewedPoints(this.videoInstance.duration(), viewed);
}
};
VideoEvent.prototype.setDefaultPlaybackRate = function setDefaultPlaybackRate() {
// 暂不支持
// this.videoInstance.defaultPlaybackRate(rate);
};
export default VideoEvent;