|
@@ -6,10 +6,10 @@ import {
|
|
|
render,
|
|
|
toRefs,
|
|
|
watch
|
|
|
-} from 'vue'
|
|
|
-import 'plyr/dist/plyr.css'
|
|
|
-import Plyr from 'plyr'
|
|
|
-import styles from './index.module.less'
|
|
|
+} from 'vue';
|
|
|
+import 'plyr/dist/plyr.css';
|
|
|
+import Plyr from 'plyr';
|
|
|
+import styles from './index.module.less';
|
|
|
|
|
|
import {
|
|
|
iconVideoBg,
|
|
@@ -18,9 +18,9 @@ import {
|
|
|
iconPlay,
|
|
|
iconPause,
|
|
|
iconSpeed
|
|
|
-} from '../../image/icons.json'
|
|
|
-import { Popup, Slider } from 'vant'
|
|
|
-import { useElementBounding } from '@vueuse/core'
|
|
|
+} from '../../image/icons.json';
|
|
|
+import { Popup, Slider } from 'vant';
|
|
|
+import { useElementBounding } from '@vueuse/core';
|
|
|
|
|
|
export default defineComponent({
|
|
|
name: 'video-play',
|
|
@@ -28,7 +28,7 @@ export default defineComponent({
|
|
|
item: {
|
|
|
type: Object,
|
|
|
default: () => {
|
|
|
- return {}
|
|
|
+ return {};
|
|
|
}
|
|
|
},
|
|
|
activeModel: {
|
|
@@ -38,7 +38,7 @@ export default defineComponent({
|
|
|
},
|
|
|
emits: ['play', 'pause', 'ended', 'close'],
|
|
|
setup(props, { emit, expose }) {
|
|
|
- const { item } = toRefs(props)
|
|
|
+ const { item } = toRefs(props);
|
|
|
const data = reactive({
|
|
|
videoContianerRef: null as unknown as HTMLAudioElement,
|
|
|
videoState: 'pause' as 'init' | 'play' | 'pause',
|
|
@@ -49,77 +49,77 @@ export default defineComponent({
|
|
|
left: '1px'
|
|
|
},
|
|
|
defaultSpeed: 1 // 默认速度
|
|
|
- })
|
|
|
- const controlID = 'v' + Date.now() + Math.floor(Math.random() * 100)
|
|
|
- const playBtnId = 'play' + Date.now() + Math.floor(Math.random() * 100)
|
|
|
- const loopBtnId = 'loop' + Date.now() + Math.floor(Math.random() * 100)
|
|
|
- const speedBtnId = 'speed' + Date.now() + Math.floor(Math.random() * 100)
|
|
|
+ });
|
|
|
+ const controlID = 'v' + Date.now() + Math.floor(Math.random() * 100);
|
|
|
+ const playBtnId = 'play' + Date.now() + Math.floor(Math.random() * 100);
|
|
|
+ const loopBtnId = 'loop' + Date.now() + Math.floor(Math.random() * 100);
|
|
|
+ const speedBtnId = 'speed' + Date.now() + Math.floor(Math.random() * 100);
|
|
|
const speedPopoverId =
|
|
|
- 'popover' + Date.now() + Math.floor(Math.random() * 100)
|
|
|
+ 'popover' + Date.now() + Math.floor(Math.random() * 100);
|
|
|
|
|
|
const togglePlay = (e: Event) => {
|
|
|
- e.stopPropagation()
|
|
|
- data.speedControl = false
|
|
|
+ e.stopPropagation();
|
|
|
+ data.speedControl = false;
|
|
|
if (!data.videoContianerRef.paused) {
|
|
|
- data.videoItem?.pause()
|
|
|
+ data.videoItem?.pause();
|
|
|
} else {
|
|
|
- data.videoContianerRef?.play()
|
|
|
+ data.videoContianerRef?.play();
|
|
|
}
|
|
|
- }
|
|
|
+ };
|
|
|
const toggleLoop = () => {
|
|
|
- data.speedControl = false
|
|
|
- const loopBtn = document.getElementById(loopBtnId)
|
|
|
- if (!loopBtn || !data.videoItem) return
|
|
|
- const isLoop = data.videoItem.loop
|
|
|
+ data.speedControl = false;
|
|
|
+ const loopBtn = document.getElementById(loopBtnId);
|
|
|
+ if (!loopBtn || !data.videoItem) return;
|
|
|
+ const isLoop = data.videoItem.loop;
|
|
|
if (isLoop) {
|
|
|
- loopBtn.classList.remove(styles.active)
|
|
|
+ loopBtn.classList.remove(styles.active);
|
|
|
} else {
|
|
|
- loopBtn.classList.add(styles.active)
|
|
|
+ loopBtn.classList.add(styles.active);
|
|
|
}
|
|
|
- data.videoItem.loop = !data.videoItem.loop
|
|
|
- }
|
|
|
+ data.videoItem.loop = !data.videoItem.loop;
|
|
|
+ };
|
|
|
const onDefault = () => {
|
|
|
document
|
|
|
.getElementById(controlID)
|
|
|
?.addEventListener('click', (e: Event) => {
|
|
|
- e.stopPropagation()
|
|
|
- data.speedControl = false
|
|
|
- if (data.videoContianerRef.paused) return
|
|
|
- emit('close')
|
|
|
- })
|
|
|
+ e.stopPropagation();
|
|
|
+ data.speedControl = false;
|
|
|
+ if (data.videoContianerRef.paused) return;
|
|
|
+ emit('close');
|
|
|
+ });
|
|
|
document.getElementById(controlID)?.addEventListener('touchmove', () => {
|
|
|
- data.speedControl = false
|
|
|
- if (data.videoContianerRef.paused) return
|
|
|
- emit('close')
|
|
|
- })
|
|
|
- document.getElementById(playBtnId)?.addEventListener('click', togglePlay)
|
|
|
- document.getElementById(loopBtnId)?.addEventListener('click', toggleLoop)
|
|
|
+ data.speedControl = false;
|
|
|
+ if (data.videoContianerRef.paused) return;
|
|
|
+ emit('close');
|
|
|
+ });
|
|
|
+ document.getElementById(playBtnId)?.addEventListener('click', togglePlay);
|
|
|
+ document.getElementById(loopBtnId)?.addEventListener('click', toggleLoop);
|
|
|
|
|
|
document.getElementById(speedBtnId)?.addEventListener('click', e => {
|
|
|
- e.stopPropagation()
|
|
|
- data.speedControl = !data.speedControl
|
|
|
- })
|
|
|
+ e.stopPropagation();
|
|
|
+ data.speedControl = !data.speedControl;
|
|
|
+ });
|
|
|
|
|
|
- setName()
|
|
|
- }
|
|
|
+ setName();
|
|
|
+ };
|
|
|
const setName = () => {
|
|
|
- const nameEl = document.getElementById('videoItemName')
|
|
|
+ const nameEl = document.getElementById('videoItemName');
|
|
|
if (nameEl) {
|
|
|
- nameEl.innerHTML = item.value.name || ''
|
|
|
+ nameEl.innerHTML = item.value.name || '';
|
|
|
}
|
|
|
- }
|
|
|
+ };
|
|
|
|
|
|
const changePlayBtn = (code: string) => {
|
|
|
- const playBtn = document.getElementById(playBtnId)
|
|
|
- if (!playBtn) return
|
|
|
+ const playBtn = document.getElementById(playBtnId);
|
|
|
+ if (!playBtn) return;
|
|
|
if (code == 'play') {
|
|
|
- playBtn.classList.remove(styles.btnPause)
|
|
|
- playBtn.classList.add(styles.btnPlay)
|
|
|
+ playBtn.classList.remove(styles.btnPause);
|
|
|
+ playBtn.classList.add(styles.btnPlay);
|
|
|
} else {
|
|
|
- playBtn.classList.remove(styles.btnPlay)
|
|
|
- playBtn.classList.add(styles.btnPause)
|
|
|
+ playBtn.classList.remove(styles.btnPlay);
|
|
|
+ playBtn.classList.add(styles.btnPause);
|
|
|
}
|
|
|
- }
|
|
|
+ };
|
|
|
const controls = `
|
|
|
<div id="${controlID}" class="plyr__controls bottomFixed ${styles.controls}">
|
|
|
<div class="${styles.time}">
|
|
@@ -152,7 +152,7 @@ export default defineComponent({
|
|
|
</div>
|
|
|
<div id="videoItemName"></div>
|
|
|
</div>
|
|
|
- </div>` as any
|
|
|
+ </div>`;
|
|
|
|
|
|
onMounted(() => {
|
|
|
data.videoItem = new Plyr(data.videoContianerRef, {
|
|
@@ -162,79 +162,79 @@ export default defineComponent({
|
|
|
hideControls: false, // 在 2 秒没有鼠标或焦点移动、控制元素模糊(制表符退出)、播放开始或进入全屏时自动隐藏视频控件。只要移动鼠标、聚焦控制元素或暂停播放,控件就会立即重新出现。
|
|
|
clickToPlay: false, // 单击(或点击)视频容器将切换播放/暂停
|
|
|
fullscreen: { enabled: false, fallback: false, iosNative: false } // 不适用全屏
|
|
|
- })
|
|
|
+ });
|
|
|
|
|
|
nextTick(() => {
|
|
|
- onDefault()
|
|
|
- })
|
|
|
- })
|
|
|
+ onDefault();
|
|
|
+ });
|
|
|
+ });
|
|
|
|
|
|
const toggleHideControl = (isShow: boolean) => {
|
|
|
- data.videoItem?.toggleControls(isShow)
|
|
|
+ data.videoItem?.toggleControls(isShow);
|
|
|
|
|
|
if (!isShow) {
|
|
|
- data.speedControl = isShow
|
|
|
+ data.speedControl = isShow;
|
|
|
}
|
|
|
- }
|
|
|
+ };
|
|
|
watch(
|
|
|
() => props.activeModel,
|
|
|
() => {
|
|
|
- toggleHideControl(props.activeModel)
|
|
|
+ toggleHideControl(props.activeModel);
|
|
|
}
|
|
|
- )
|
|
|
+ );
|
|
|
|
|
|
watch(
|
|
|
() => props.item,
|
|
|
() => {
|
|
|
- setName()
|
|
|
+ setName();
|
|
|
// 设置视屏播放器的默认速度
|
|
|
- if (data.videoItem) data.videoItem.speed = data.defaultSpeed || 1
|
|
|
+ if (data.videoItem) data.videoItem.speed = data.defaultSpeed || 1;
|
|
|
|
|
|
// 切换的时候隐藏
|
|
|
- data.speedControl = false
|
|
|
+ data.speedControl = false;
|
|
|
}
|
|
|
- )
|
|
|
- let videoTimer = null as any
|
|
|
+ );
|
|
|
+ let videoTimer = null as any;
|
|
|
const handlePlayVideo = () => {
|
|
|
- clearTimeout(videoTimer)
|
|
|
+ clearTimeout(videoTimer);
|
|
|
nextTick(() => {
|
|
|
data.videoContianerRef.play().catch(err => {
|
|
|
- console.log('🚀 ~ err:', err)
|
|
|
+ console.log('🚀 ~ err:', err);
|
|
|
videoTimer = setTimeout(() => {
|
|
|
if (err?.message?.includes('play()')) {
|
|
|
- emit('play')
|
|
|
+ emit('play');
|
|
|
}
|
|
|
- handlePlayVideo()
|
|
|
- }, 1000)
|
|
|
- })
|
|
|
- })
|
|
|
- }
|
|
|
+ handlePlayVideo();
|
|
|
+ }, 1000);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ };
|
|
|
|
|
|
- let videoErrorTimer = null as any
|
|
|
- let videoErrorCount = 0
|
|
|
+ let videoErrorTimer = null as any;
|
|
|
+ let videoErrorCount = 0;
|
|
|
const handleErrorVideo = () => {
|
|
|
if (videoErrorCount > 5) {
|
|
|
- return
|
|
|
+ return;
|
|
|
}
|
|
|
- clearTimeout(videoErrorTimer)
|
|
|
+ clearTimeout(videoErrorTimer);
|
|
|
nextTick(() => {
|
|
|
videoErrorTimer = setTimeout(() => {
|
|
|
- data.videoContianerRef.src = props.item?.content
|
|
|
+ data.videoContianerRef.src = props.item?.content;
|
|
|
|
|
|
- emit('play')
|
|
|
- data.videoContianerRef.load()
|
|
|
+ emit('play');
|
|
|
+ data.videoContianerRef.load();
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
|
- handleErrorVideo()
|
|
|
- }, 1000)
|
|
|
- })
|
|
|
- videoErrorCount++
|
|
|
- }
|
|
|
+ handleErrorVideo();
|
|
|
+ }, 1000);
|
|
|
+ });
|
|
|
+ videoErrorCount++;
|
|
|
+ };
|
|
|
const getVideoRef = () => {
|
|
|
- return data.videoContianerRef
|
|
|
- }
|
|
|
+ return data.videoContianerRef;
|
|
|
+ };
|
|
|
expose({
|
|
|
getVideoRef
|
|
|
- })
|
|
|
+ });
|
|
|
|
|
|
return () => (
|
|
|
<div class={styles.videoWrap}>
|
|
@@ -249,61 +249,57 @@ export default defineComponent({
|
|
|
playsinline
|
|
|
x5-video-player-type="h5"
|
|
|
onLoadedmetadata={() => {
|
|
|
- data.videoState = 'pause'
|
|
|
- changePlayBtn('play')
|
|
|
+ data.videoState = 'pause';
|
|
|
+ changePlayBtn('play');
|
|
|
nextTick(() => {
|
|
|
- data.videoContianerRef.currentTime = 0
|
|
|
- nextTick(handlePlayVideo)
|
|
|
- })
|
|
|
+ data.videoContianerRef.currentTime = 0;
|
|
|
+ nextTick(handlePlayVideo);
|
|
|
+ });
|
|
|
}}
|
|
|
onPlay={() => {
|
|
|
- videoErrorCount = 0
|
|
|
+ videoErrorCount = 0;
|
|
|
// console.log('开始播放')
|
|
|
- data.videoState = 'play'
|
|
|
- changePlayBtn('pause')
|
|
|
- emit('close')
|
|
|
- emit('play')
|
|
|
- clearTimeout(videoErrorTimer)
|
|
|
+ data.videoState = 'play';
|
|
|
+ changePlayBtn('pause');
|
|
|
+ emit('close');
|
|
|
+ emit('play');
|
|
|
+ clearTimeout(videoErrorTimer);
|
|
|
}}
|
|
|
onPause={() => {
|
|
|
// console.log('暂停播放')
|
|
|
- data.videoState = 'pause'
|
|
|
- changePlayBtn('play')
|
|
|
- emit('pause')
|
|
|
+ data.videoState = 'pause';
|
|
|
+ changePlayBtn('play');
|
|
|
+ emit('pause');
|
|
|
}}
|
|
|
onEnded={() => {
|
|
|
// console.log('播放结束')
|
|
|
- data.videoState = 'pause'
|
|
|
- changePlayBtn('play')
|
|
|
- emit('ended')
|
|
|
+ data.videoState = 'pause';
|
|
|
+ changePlayBtn('play');
|
|
|
+ emit('ended');
|
|
|
}}
|
|
|
- onError={handleErrorVideo}
|
|
|
- ></video>
|
|
|
+ onError={handleErrorVideo}></video>
|
|
|
|
|
|
<div
|
|
|
style={{
|
|
|
display: data.speedControl ? 'block' : 'none'
|
|
|
- }}
|
|
|
- >
|
|
|
+ }}>
|
|
|
<div
|
|
|
class={styles.sliderPopup}
|
|
|
onClick={(e: Event) => {
|
|
|
- e.stopPropagation()
|
|
|
- }}
|
|
|
- >
|
|
|
+ e.stopPropagation();
|
|
|
+ }}>
|
|
|
<i
|
|
|
class={styles.iconAdd}
|
|
|
onClick={() => {
|
|
|
if (data.defaultSpeed >= 1.5) {
|
|
|
- return
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
if (data.videoItem) {
|
|
|
- data.defaultSpeed = (data.defaultSpeed * 10 + 1) / 10
|
|
|
- data.videoItem.speed = data.defaultSpeed
|
|
|
+ data.defaultSpeed = (data.defaultSpeed * 10 + 1) / 10;
|
|
|
+ data.videoItem.speed = data.defaultSpeed;
|
|
|
}
|
|
|
- }}
|
|
|
- ></i>
|
|
|
+ }}></i>
|
|
|
<Slider
|
|
|
min={0.5}
|
|
|
max={1.5}
|
|
@@ -314,10 +310,9 @@ export default defineComponent({
|
|
|
reverse
|
|
|
onChange={() => {
|
|
|
if (data.videoItem) {
|
|
|
- data.videoItem.speed = data.defaultSpeed
|
|
|
+ data.videoItem.speed = data.defaultSpeed;
|
|
|
}
|
|
|
- }}
|
|
|
- >
|
|
|
+ }}>
|
|
|
{{
|
|
|
button: () => (
|
|
|
<div class={styles.sliderPoint}>
|
|
@@ -331,17 +326,16 @@ export default defineComponent({
|
|
|
class={[styles.iconCut]}
|
|
|
onClick={() => {
|
|
|
if (data.defaultSpeed <= 0.5) {
|
|
|
- return
|
|
|
+ return;
|
|
|
}
|
|
|
if (data.videoItem) {
|
|
|
- data.defaultSpeed = (data.defaultSpeed * 10 - 1) / 10
|
|
|
- data.videoItem.speed = data.defaultSpeed
|
|
|
+ data.defaultSpeed = (data.defaultSpeed * 10 - 1) / 10;
|
|
|
+ data.videoItem.speed = data.defaultSpeed;
|
|
|
}
|
|
|
- }}
|
|
|
- ></i>
|
|
|
+ }}></i>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- )
|
|
|
+ );
|
|
|
}
|
|
|
-})
|
|
|
+});
|