feat: VideoPlayer
parent
5bee1a0303
commit
7b5bbedbcc
@ -0,0 +1,27 @@
|
|||||||
|
import { VNode, createVNode, render } from 'vue'
|
||||||
|
import VideoPlayer from './src/VideoPlayer.vue'
|
||||||
|
import { isClient } from '@/utils/is'
|
||||||
|
import { VideoPlayerViewer } from '@/components/VideoPlayerViewer'
|
||||||
|
import { toAnyString } from '@/utils'
|
||||||
|
|
||||||
|
export { VideoPlayer }
|
||||||
|
|
||||||
|
let instance: Nullable<VNode> = null
|
||||||
|
|
||||||
|
export function createVideoViewer(options: { url: string; poster?: string; show?: boolean }) {
|
||||||
|
if (!isClient) return
|
||||||
|
const { url, poster } = options
|
||||||
|
|
||||||
|
const propsData: Partial<{ url: string; poster?: string; show?: boolean; id?: string }> = {}
|
||||||
|
const container = document.createElement('div')
|
||||||
|
const id = toAnyString()
|
||||||
|
container.id = id
|
||||||
|
propsData.url = url
|
||||||
|
propsData.poster = poster
|
||||||
|
propsData.show = true
|
||||||
|
propsData.id = id
|
||||||
|
|
||||||
|
document.body.appendChild(container)
|
||||||
|
instance = createVNode(VideoPlayerViewer, propsData)
|
||||||
|
render(instance, container)
|
||||||
|
}
|
||||||
@ -0,0 +1,59 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import Player from 'xgplayer'
|
||||||
|
import { ref, unref, onMounted, watch, onBeforeUnmount, nextTick } from 'vue'
|
||||||
|
import 'xgplayer/dist/index.min.css'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
url: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
poster: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const playerRef = ref<Player>()
|
||||||
|
|
||||||
|
const videoEl = ref<HTMLDivElement>()
|
||||||
|
|
||||||
|
const intiPlayer = () => {
|
||||||
|
if (!unref(videoEl)) return
|
||||||
|
new Player({
|
||||||
|
autoplay: false,
|
||||||
|
...props,
|
||||||
|
el: unref(videoEl)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
intiPlayer()
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props,
|
||||||
|
async (newProps) => {
|
||||||
|
await nextTick()
|
||||||
|
if (newProps) {
|
||||||
|
unref(playerRef)?.setConfig(newProps)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deep: true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
unref(playerRef)?.destroy()
|
||||||
|
})
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
playerExpose: () => unref(playerRef)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div ref="videoEl"></div>
|
||||||
|
</template>
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
import VideoPlayerViewer from './src/VideoPlayerViewer.vue'
|
||||||
|
|
||||||
|
export { VideoPlayerViewer }
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { VideoPlayer } from '@/components/VideoPlayer'
|
||||||
|
import { ElOverlay } from 'element-plus'
|
||||||
|
import { ref, nextTick } from 'vue'
|
||||||
|
import { Icon } from '@/components/Icon'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
show: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
url: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
poster: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
id: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const visible = ref(props.show)
|
||||||
|
|
||||||
|
const close = async () => {
|
||||||
|
visible.value = false
|
||||||
|
await nextTick()
|
||||||
|
const wrap = document.getElementById(props.id)
|
||||||
|
if (!wrap) return
|
||||||
|
document.body.removeChild(wrap)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<ElOverlay v-show="visible" @click="close">
|
||||||
|
<div class="w-full h-full flex justify-center items-center relative" @click="close">
|
||||||
|
<div
|
||||||
|
class="w-44px h-44px color-[#fff] bg-[var(--el-text-color-regular)] rounded-full border-[#fff] flex justify-center items-center cursor-pointer absolute top-40px right-40px"
|
||||||
|
@click="close"
|
||||||
|
>
|
||||||
|
<Icon icon="ep:close" :size="24" />
|
||||||
|
</div>
|
||||||
|
<VideoPlayer :url="url" :poster="poster" />
|
||||||
|
</div>
|
||||||
|
</ElOverlay>
|
||||||
|
</template>
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { VideoPlayer, createVideoViewer } from '@/components/VideoPlayer'
|
||||||
|
import { ContentWrap } from '@/components/ContentWrap'
|
||||||
|
import { ElButton, ElDivider } from 'element-plus'
|
||||||
|
|
||||||
|
const showVideo = () => {
|
||||||
|
createVideoViewer({
|
||||||
|
url: '//sf1-cdn-tos.huoshanstatic.com/obj/media-fe/xgplayer_doc_video/mp4/xgplayer-demo-720p.mp4',
|
||||||
|
poster: '//lf3-static.bytednsdoc.com/obj/eden-cn/nupenuvpxnuvo/xgplayer_doc/poster.jpg'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ContentWrap title="视频播放器">
|
||||||
|
<VideoPlayer
|
||||||
|
url="//sf1-cdn-tos.huoshanstatic.com/obj/media-fe/xgplayer_doc_video/mp4/xgplayer-demo-720p.mp4"
|
||||||
|
poster="//lf3-static.bytednsdoc.com/obj/eden-cn/nupenuvpxnuvo/xgplayer_doc/poster.jpg"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ElDivider />
|
||||||
|
<ElButton type="primary" @click="showVideo">弹窗展示</ElButton>
|
||||||
|
</ContentWrap>
|
||||||
|
</template>
|
||||||
Loading…
Reference in New Issue