需求描述:
咱们播放一个视频,然后当咱们向下滚动直至离开可视区域的时候,会在右下角出现一个小窗口继续咱们的视频播放。
效果:
需求分析:
1. 初始化一个播放器
2. 大视频播放区域如果出现在视口外,小窗口出现
3. 大小视频切换的时候,保持视频状态不变
主要用到:
1. 一个成熟的播放器
2. vueuse中的 useIntersectionObserver API来监视某个dom元素是否离开了可视区域
3. Vue3中的 Teleport 内置组件 传送门 保持dom的前提下完成传送
接下来正题:
播放器
这里不是重点,选择一个自己喜欢的播放器就可以啦,就是随便播放个视频,我这里用的西瓜播放器,我将xgPlayer封装成了一个公共组件,在我上一篇 博客有写,感兴趣的话可以去踩踩,链接:vue使用西瓜播放器
useIntersectionObserver API
这个api可以帮我们很方便的监测到 某个dom元素 是否离开了 我们的可视区域
安装
npm install @vueuse/core
引入
import { useIntersectionObserver } from '@vueuse/core'
使用
const { stop } = useIntersectionObserver(document.getElementById('bigBox'), ([{ isIntersecting }]) => {
// isIntersecting 一个布尔值, true -> 代表在可视区域; false -> 表示不再可是区域
isTeleport.value = isIntersecting
})
// setTimeout(() => {
// stop() // 不需要监听的时候 调用stop函数
// },10000)
Teleport 传送门
官网:Teleport·传送门
这个是Vue3提供的内置组件,可以直接使用,to属性传送到目标dom下,disabled控制什么时候传送
注意: 我们传送的时候to的那个目标dom,必须要挂载到Teleport之前才行
所以我们采用 v-if 来控制 Teleport 组件的挂载时机,保证Teleport挂载时,to 目标已经存在于dom之中
完整代码
<template>
<div class="TeleportVideo">
<!-- 要播放的大视频窗口 -->
<div id="bigBox">
<Teleport to="#smallBox" :disabled="isTeleport" v-if="isShow">
<XgPlayer :id="'xgPlayerId'" />
</Teleport>
</div>
<!-- 要传送的小视频窗口 -->
<div id="smallBox"></div>
<!-- 模拟滚动 -->
<div style="height: 2000px;"></div>
</div>
</template>
<script setup>
import { onMounted, ref } from 'vue'
import XgPlayer from '@/components/xgPlayer/xgPlayer.vue'
import { useIntersectionObserver } from '@vueuse/core'
let isTeleport = ref(true) // 控制什么时候传送
let isShow = ref(false) // 控制 Teleport内置组件的挂载时机(要延迟一下)
onMounted(() => {
intersectionObserver()
// 为了确保传送的目标dom挂载时机在Teleport组件之间 所以这里延迟挂载Teleport内置组件
setTimeout(() => { // 这里不用setTimeOut也是可以的,咱们就是想让Teleport内置组件在最后的时候挂载,onMounted执行的时候,dom元素已经挂载完成了
isShow.value = true
})
})
// 监听 指定的dom元素是否在 可视区域内
const intersectionObserver = () => {
const { stop } = useIntersectionObserver(document.getElementById('bigBox'), ([{ isIntersecting }]) => {
// isIntersecting 一个布尔值, true -> 代表在可视区域; false -> 表示不再可是区域
isTeleport.value = isIntersecting
})
// setTimeout(() => {
// stop() // 不需要监听的时候 调用stop
// },10000)
}
</script>
<style scoped>
.TeleportVideo {
width: 100%;
height: 100%;
overflow: auto;
}
#bigBox {
width: 640px;
height: 360px;
/* border: 10px solid red; */
z-index: 99;
}
#smallBox {
position: fixed;
bottom: 20px;
right: 60px;
width: 320px;
height: 180px;
/* border: 1px solid red; */
}
</style>