<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>
Document
</title>
<style>
* {
padding: 0;
margin: 0;
}
</style>
</head>
<body>
<script src="./script/vue.global.js"></script>
<script src="./script/DPlayer.min.js"></script>
<script src="./script/hls.min.js"></script>
<script src="./script/axios.min.js"></script>
<div id="app">
<div style="width: 100vw; height: 100vh">
<!-- -->
<!-- -->
<dplayer v-if="showVideo" :video="dplayerObj.video" ref="dplayerVideo" screenshot :loop="true" :autoplay="false"
@ended="videoFinish" @play="heartBeatApiFun(1)" @pause="heartBeatApiFun(2)" />
</div>
</div>
<script>
const timerObj = {
timer: null,
sec: 15000,
// getTime
setTimer: function (callback) {
this.timer && this.removeTimer();
this.timer = setTimeout(() => {
this.callback && this.callback();
this.setTimer();
}, this.sec);
},
removeTimer: function () {
clearTimeout(this.timer);
this.timer = null;
},
callback: () => { },
};
function guid() {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(
/[xy]/g,
function (c) {
var r = (Math.random() * 16) | 0,
v = c == "x" ? r : (r & 0x3) | 0x8;
return v.toString(16);
}
);
}
function suffix(name) {
//获取图片后缀
name = name.split("?")[0];
let fileName = name.lastIndexOf(".");
let fileNameLength = name.length;
let fileFormat = name.substring(fileName + 1, fileNameLength);
return fileFormat;
}
var videoBox = null;
const {
ref,
reactive,
onBeforeUnmount,
onMounted,
nextTick,
defineEmits,
defineProps,
defineExpose,
createApp,
} = Vue;
</script>
<script>
const videoPlayer = {
template: `
<div style="width: 100%; height: 100%" id="videoRef" ref="videoRef"></div>
`,
emits: ["ended", "play", "pause", "changeMaxTime"],
props: {
// 是否自动播放
autoplay: {
type: Boolean,
default: false,
},
// 主题色
theme: {
type: String,
default: "#0093ff",
},
// 视频是否循环播放
loop: {
type: Boolean,
default: true,
},
// 语言(可选值: 'en', 'zh-cn', 'zh-tw')
lang: {
type: String,
default: "zh-cn",
},
// 是否开启截图(如果开启,视频和视频封面需要允许跨域)
screenshot: {
type: Boolean,
default: false,
},
// 是否开启热键
hotkey: {
type: Boolean,
default: true,
},
// 视频是否预加载(可选值: 'none', 'metadata', 'auto')
preload: {
type: String,
default: "auto",
},
// 默认音量
volume: {
type: Number,
default: 0.7,
},
// 可选的播放速率,可以设置成自定义的数组
playbackSpeed: {
type: Array,
default: [0.5, 0.75, 1, 1.25, 1.5, 2],
},
disableSpeed: {
type: Boolean,
default: false,
},
disableProgress: {
type: Boolean,
default: false,
},
effMaxStudyTimes: {
type: Number,
default: 0,
},
// 在左上角展示一个 logo,你可以通过 CSS 调整它的大小和位置
logo: {
type: String,
default: "",
},
// 视频信息
video: {
type: Object,
default: {
},
},
// 外挂字幕
subtitle: {
type: Object,
default: {},
},
// 显示弹幕
danmaku: {
type: Object,
default: {},
},
// 自定义右键菜单
contextmenu: {
type: Array,
default: [],
},
// 自定义进度条提示点
highlight: {
type: Array,
default: [],
},
// 阻止多个播放器同时播放,当前播放器播放时暂停其他播放器
mutex: {
type: Boolean,
default: true,
},
},
setup(props, context) {
// const videoRef = ref(null);
// console.log(props)
const state = reactive({
instance: null,
});
const fullscreenStatus = ref({
webfullscreen: false,
fullscreen: false,
});
onMounted(() => {
var videoRef = document.getElementById("videoRef");
let player = {
container: videoRef,
autoplay: props.autoplay,
theme: props.theme,
loop: props.loop,
lang: props.lang,
screenshot: props.screenshot,
hotkey: props.hotkey,
preload: props.preload,
volume: props.volume,
playbackSpeed: props.playbackSpeed,
video: props.video,
contextmenu: props.contextmenu,
highlight: props.highlight,
mutex: props.mutex,
};
if (props.subtitle.url) {
player.subtitle = props.subtitle;
}
console.log(player);
state.instance = new DPlayer(player);
videoBox = {
isCanPlay,
switchVideo,
seekkVideo,
getSeekTime,
setSeekTime,
play,
pause,
cancelFull,
backFull,
};
state.instance.on("ended", () => {
if (props.disableProgress) {
var duration = state.instance.video.duration;
if (Math.abs(props.effMaxStudyTimes - duration)
< 5) {
context.emit("ended");
}
} else {
context.emit("ended");
}
});
state.instance.on("play", () => {
context.emit("play");
});
state.instance.on("pause", () => {
context.emit("pause");
});
state.instance.on("fullscreen", () => {
// console.log("fullscreen");
fullscreenStatus.value.fullscreen = true;
});
state.instance.on("fullscreen_cancel", () => {
// console.log("fullscreen_cancel");
fullscreenStatus.value.fullscreen = false;
});
state.instance.on("webfullscreen", () => {
// console.log("webfullscreen");
fullscreenStatus.value.webfullscreen = true;
});
state.instance.on("webfullscreen_cancel", () => {
fullscreenStatus.value.webfullscreen = false;
// console.log("webfullscreen_cancel");
});
if (props.disableSpeed) {
state.instance.container.querySelector(
".dplayer-setting-speed"
).style.display = "none";
}
if (props.disableProgress) {
var videoTime = 0;
// console.log(props.effMaxStudyTimes);
state.instance.on("timeupdate", function (e) {
var videoCurrentTime = state.instance.video.currentTime;
if (videoCurrentTime > props.effMaxStudyTimes) {
if (
videoCurrentTime - videoTime >
0.8 * state.instance.video.playbackRate
) {
state.instance.seek(videoTime);
state.instance.notice(
"最大学习时间为:" + getTime(props.effMaxStudyTimes),
2000
);
state.instance.notice("禁止快进", 2000);
} else {
if (videoCurrentTime > props.effMaxStudyTimes > 0) {
context.emit("changeMaxTime", videoCurrentTime);
}
videoTime = videoCurrentTime;
}
} else {
videoTime = videoCurrentTime;
}
// videoTime = videoCurrentTime;
});
state.instance.on("notice_show", function (e) {
if (videoTime > props.effMaxStudyTimes) {
var text = e.innerText;
//
if (
"禁止快进" != text &&
(text.indexOf("快进") > -1 || text.indexOf("快退") > -1)
) {
e.style.display = "none";
}
}
});
}
});
// 销毁
onBeforeUnmount(() => {
state.instance.destroy();
});
function switchVideo(item) {
// state.instance.pause()
console.log(item);
state.instance.switchVideo(item);
}
function seekkVideo(time) {
state.instance.seek(time);
}
function getSeekTime() {
return state.instance.video.currentTime;
}
function play() {
// state.instance.play()
state.instance.video
.play()
.then((e) => {
console.log(e);
})
.catch((e) => {
console.log(e);
});
}
function pause() {
state.instance.pause();
}
var isCanPlayFun;
function isCanPlay(callback) {
// state.instance.off('canplay',isCanPlayFun)
// state.instance.on('canplay',isCanPlayFun)
isCanPlayFun = () => {
console.log(12121212);
callback();
};
// state.instance.video.removeEventListener('canplay',isCanPlayFun,false)
state.instance.video.addEventListener("canplay", isCanPlayFun, {
once: true,
});
}
function setSeekTime(time, desc) {
if (time) {
state.instance.notice("上次记录:" + getTime(time), 2000);
}
return (state.instance.video.currentTime = time);
}
const fullscreenTempStatus = ref({});
function cancelFull() {
fullscreenTempStatus.value = { ...fullscreenStatus.value };
if (fullscreenStatus.value.fullscreen) {
state.instance.fullScreen.cancel("browser");
}
if (fullscreenStatus.value.webfullscreen) {
state.instance.fullScreen.cancel("web");
}
}
function backFull() {
if (fullscreenTempStatus.value.fullscreen) {
state.instance.fullScreen.request("browser");
}
if (fullscreenTempStatus.value.webfullscreen) {
state.instance.fullScreen.request("web");
}
}
context.expose({
isCanPlay,
switchVideo,
seekkVideo,
getSeekTime,
setSeekTime,
play,
pause,
cancelFull,
backFull,
});
},
};
</script>
<script>
const app = createApp({
components: {
dplayer: videoPlayer,
},
setup() {
const uuid = guid();
const dplayerVideo = ref(null);
const showVideo = ref(false);
const dplayerObj = reactive({
video: {
customType: {
customHls: function (video, player) {
const hls = new Hls(); //实例化Hls 用于解析m3u8
hls.loadSource(video.src);
hls.attachMedia(video);
},
},
},
});
onMounted(() => {
window.addEventListener("beforeunload", beforeunloadFun, false);
initVideo();
});
function initVideo() {
let url =
"https:\/\/******/2023\/04\/12\/100151\/100151.m3u8";
if (suffix(url) == "m3u8") {
dplayerObj.video.type = "customHls";
} else {
dplayerObj.video.type = "auto";
}
dplayerObj.video.url = url;
showVideo.value = true;
nextTick(() => {
dplayerVideo.value = videoBox;
console.log(dplayerVideo.value);
dplayerVideo.value.isCanPlay(() => {
dplayerVideo.value.play();
timerObj.callback = () => {
heartBeatApiFun(5);
};
timerObj.callback();
timerObj.setTimer();
});
});
}
function beforeunloadFun() {
heartBeatApiFun(4);
}
onBeforeUnmount(() => {
window.removeEventListener("beforeunload", beforeunloadFun, false);
heartBeatApiFun(4);
timerObj.removeTimer();
});
function videoFinish() {
heartBeatApiFun(3);
}
function heartBeatApi(data) {
return axios
.post(
"https://***************/prod-api/org/paternerStudy/heartBeat",
data
)
}
function heartBeatApiFun(type, callback = () => { }) {
const currentVideoTime = parseInt(dplayerVideo.value.getSeekTime());
heartBeatApi({
resourceId: "100151",
currentVideoTime: currentVideoTime,
// 1播放,2暂停,3结束,4关闭,5定时心跳
type: type,
sign: uuid,
patrtnerCode: "002",
})
.then((res) => {
callback && callback(res);
})
.catch((e) => {
});
}
return {
showVideo,
dplayerObj,
videoFinish,
heartBeatApiFun,
};
},
});
app.mount("#app");
</script>
</body>
</html>```
html中使用vue3中setup的dplayer播放器
于 2023-06-19 21:26:52 首次发布