|
@@ -1,181 +0,0 @@
|
|
|
-import { defineComponent, nextTick, onMounted, toRefs } from 'vue'
|
|
|
-import 'plyr/dist/plyr.css'
|
|
|
-import Plyr from 'plyr'
|
|
|
-import { ref } from 'vue'
|
|
|
-import styles from './video.module.less'
|
|
|
-
|
|
|
-import iconLoop from '../image/icon-loop.svg'
|
|
|
-import iconLoopActive from '../image/icon-loop-active.svg'
|
|
|
-import iconplay from '../image/icon-play.svg'
|
|
|
-import iconpause from '../image/icon-pause.svg'
|
|
|
-import { watch } from 'vue'
|
|
|
-
|
|
|
-export default defineComponent({
|
|
|
- name: 'video-play',
|
|
|
- props: {
|
|
|
- item: {
|
|
|
- type: Object,
|
|
|
- default: () => {
|
|
|
- return {}
|
|
|
- }
|
|
|
- },
|
|
|
- isEmtry: {
|
|
|
- type: Boolean,
|
|
|
- default: false
|
|
|
- },
|
|
|
- show: {
|
|
|
- type: Boolean,
|
|
|
- default: false
|
|
|
- }
|
|
|
- },
|
|
|
- emits: ['loadedmetadata', 'togglePlay', 'ended', 'reset'],
|
|
|
- setup(props, { emit, expose }) {
|
|
|
- const { item, isEmtry } = toRefs(props)
|
|
|
- const videoRef = ref()
|
|
|
- const videoItem = ref<Plyr>()
|
|
|
- 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 toggleHideControl = (isShow: false) => {
|
|
|
- videoItem.value?.toggleControls(isShow)
|
|
|
- }
|
|
|
- const togglePlay = (e: Event) => {
|
|
|
- e.stopPropagation()
|
|
|
- videoItem.value?.togglePlay()
|
|
|
- }
|
|
|
- const toggleLoop = (e: Event) => {
|
|
|
- const loopBtn = document.getElementById(loopBtnId)
|
|
|
- if (!loopBtn || !videoItem.value) return
|
|
|
- const isLoop = videoItem.value.loop
|
|
|
- if (isLoop) {
|
|
|
- loopBtn.classList.remove(styles.active)
|
|
|
- } else {
|
|
|
- loopBtn.classList.add(styles.active)
|
|
|
- }
|
|
|
- videoItem.value.loop = !videoItem.value.loop
|
|
|
- }
|
|
|
- const onDefault = () => {
|
|
|
- document.getElementById(controlID)?.addEventListener('click', (e: Event) => {
|
|
|
- e.stopPropagation()
|
|
|
- emit('reset')
|
|
|
- })
|
|
|
- document.getElementById(playBtnId)?.addEventListener('click', togglePlay)
|
|
|
- document.getElementById(loopBtnId)?.addEventListener('click', toggleLoop)
|
|
|
- }
|
|
|
-
|
|
|
- const changePlayBtn = (code: string) => {
|
|
|
- const playBtn = document.getElementById(playBtnId)
|
|
|
- if (!playBtn) return
|
|
|
- if (code == 'play') {
|
|
|
- playBtn.classList.remove(styles.btnPause)
|
|
|
- playBtn.classList.add(styles.btnPlay)
|
|
|
- } else {
|
|
|
- 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}">
|
|
|
- <div class="plyr__time plyr__time--current" aria-label="Current time">00:00</div>
|
|
|
- <div class="plyr__time plyr__time--duration" aria-label="Duration">00:00</div>
|
|
|
- </div>
|
|
|
- <div class="${styles.slider}">
|
|
|
- <div class="plyr__progress">
|
|
|
- <input data-plyr="seek" type="range" min="0" max="100" step="0.01" value="0" aria-label="Seek">
|
|
|
- <progress class="plyr__progress__buffer" min="0" max="100" value="0">% buffered</progress>
|
|
|
- <span role="tooltip" class="plyr__tooltip">00:00</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="${styles.actions}">
|
|
|
- <div class="${styles.actionWrap}">
|
|
|
- <button id="${playBtnId}" class="${styles.actionBtn}">
|
|
|
- <div class="van-loading van-loading--circular" aria-live="polite" aria-busy="true"><span class="van-loading__spinner van-loading__spinner--circular" style="color: rgb(255, 255, 255);"><svg class="van-loading__circular" viewBox="25 25 50 50"><circle cx="50" cy="50" r="20" fill="none"></circle></svg></span></div>
|
|
|
- <img class="${styles.playIcon}" src="${iconplay}" />
|
|
|
- <img class="${styles.playIcon}" src="${iconpause}" />
|
|
|
- </button>
|
|
|
- <button id="${loopBtnId}" class="${styles.actionBtn} ${styles.loopBtn}">
|
|
|
- <img class="loop" src="${iconLoop}" />
|
|
|
- <img class="loopActive" src="${iconLoopActive}" />
|
|
|
- </button>
|
|
|
- </div>
|
|
|
- <div>${item.value.name}</div>
|
|
|
- </div>
|
|
|
- </div>`
|
|
|
-
|
|
|
- onMounted(() => {
|
|
|
- console.log('onMounted')
|
|
|
- videoItem.value = new Plyr(videoRef.value, {
|
|
|
- autoplay: props.item.autoPlay,
|
|
|
- controls: controls,
|
|
|
- autopause: true, // 一次只允许
|
|
|
- ratio: '16:9', // 强制所有视频的纵横比
|
|
|
- hideControls: false, // 在 2 秒没有鼠标或焦点移动、控制元素模糊(制表符退出)、播放开始或进入全屏时自动隐藏视频控件。只要移动鼠标、聚焦控制元素或暂停播放,控件就会立即重新出现。
|
|
|
- clickToPlay: false, // 单击(或点击)视频容器将切换播放/暂停
|
|
|
- fullscreen: { enabled: false, fallback: false, iosNative: false } // 不适用全屏
|
|
|
- })
|
|
|
- if (videoItem.value) {
|
|
|
- videoItem.value.on('play', () => {
|
|
|
- if (videoItem.value) {
|
|
|
- videoItem.value.muted = false
|
|
|
- videoItem.value.volume = 1
|
|
|
- }
|
|
|
-
|
|
|
- // console.log('开始播放', item.value)
|
|
|
- if (!item.value.autoPlay && !item.value.isprepare && videoItem.value) {
|
|
|
- // 加载完成后,取消静音播放
|
|
|
- videoItem.value.pause()
|
|
|
- }
|
|
|
- changePlayBtn('')
|
|
|
- emit('togglePlay', videoItem.value?.paused)
|
|
|
- })
|
|
|
- videoItem.value.on('pause', () => {
|
|
|
- changePlayBtn('play')
|
|
|
- emit('togglePlay', videoItem.value?.paused)
|
|
|
- })
|
|
|
- videoItem.value.on('ended', (e: Event) => {
|
|
|
- emit('ended')
|
|
|
- changePlayBtn('play')
|
|
|
- })
|
|
|
- videoItem.value.once('loadedmetadata', (e: Event) => {
|
|
|
- console.log('loadedmetadata')
|
|
|
- changePlayBtn('play')
|
|
|
- if (item.value.autoPlay && videoItem.value) {
|
|
|
- videoItem.value.play()
|
|
|
- }
|
|
|
- emit('loadedmetadata', videoItem.value)
|
|
|
- })
|
|
|
-
|
|
|
- nextTick(() => {
|
|
|
- onDefault()
|
|
|
- })
|
|
|
- }
|
|
|
- })
|
|
|
- expose({
|
|
|
- changePlayBtn,
|
|
|
- toggleHideControl
|
|
|
- })
|
|
|
-
|
|
|
- /** 监听当前元素是否显示 */
|
|
|
- watch(
|
|
|
- () => props.show,
|
|
|
- val => {
|
|
|
- if (val) {
|
|
|
- videoItem.value?.play();
|
|
|
- } else {
|
|
|
- videoItem.value?.pause()
|
|
|
- }
|
|
|
- }
|
|
|
- );
|
|
|
- return () => (
|
|
|
- <div class={styles.videoWrap}>
|
|
|
- <video
|
|
|
- style={{ width: '100%', height: '100%' }}
|
|
|
- src={isEmtry.value ? '' : item.value.content}
|
|
|
- ref={videoRef}
|
|
|
- playsinline="false"
|
|
|
- ></video>
|
|
|
- </div>
|
|
|
- )
|
|
|
- }
|
|
|
-})
|