vue实现滚动到视频离开可视区后出现小窗(类似b站小窗)
文章目录前言一、实现原理二、实现过程1.创建出所需的元素和数据2.监听 mainVideo总结前言最近在做的仿网易云播放器项目中,视频界面有个需求:当滚动条滚动到主视频界面离开可视窗口时,出现小窗继续播放。HTML5 video 标签的画中画功能只能实现用户点击才会出现,滚动事件不能触发画中画所以只能自己手写视频小窗播放一、实现原理创建一个主视频元素(以下简称mainVideo),和一个用于小窗播
·
前言
最近在做的仿网易云播放器项目中,视频界面有个需求:当滚动条滚动到主视频界面离开可视窗口时,出现小窗继续播放。
HTML5 video 标签的画中画功能只能实现用户点击才会出现,滚动事件不能触发画中画
所以只能自己手写视频小窗播放
一、实现原理
创建一个主视频元素(以下简称mainVideo),和一个用于小窗播放的视频元素(以下简称miniVideo)。miniVideo 可以用 fixed 固定定位到想要的位置,然后隐藏。两个 video 共用同一个 src 视频地址。待 mainVideo 随页面滚动要一定位置而离开可视区域后,显示 miniVideo ,同步播放时间和播放状态。mainVideo 进入可视区后,隐藏 miniVideo, 同步播放时间和播放状态。
二、实现过程
1.创建出所需的元素和数据
html 代码如下(css样式就不贴了):
<!-- 主视频 -->
<div class="video">
<video
:src="url" data 中的数据
controls
ref="video"
class="player"
:poster="detail.cover || detail.coverUrl"
@play="isVideoPlay = true" 记录主视频的播放状态,这里也可以不用记录,后面
@pause="isVideoPlay = false" 通过videoElement.paused 判断
></video>
</div>
<!-- 小窗视频 -->
<div class="miniVideo" v-show="showMiniVideo">
<video
:src="url"
ref="miniVideo"
class="player"
:poster="detail.cover || detail.coverUrl"
></video>
<!-- 遮罩,参考b站小窗 -->
<div class="mask">
<i
class="iconfont"
:class="{
'icon-icon_play': !isMiniVideoPlay, 通过miniVideo的播放状态显示不同的按钮,如:播放,暂停
'icon-zanting2': isMiniVideoPlay,
}"
@click="miniVideoChangePlay(!isMiniVideoPlay)" 改变播放状态函数
></i>
</div>
</div>
2.监听 mainVideo
利用 Intersection Observer API 实现
vue代码如下(我写在 mounted 生命周期函数中):
// 滚动 出现小窗播放
let video = this.$refs.video;
let miniVideo = this.$refs.miniVideo;
let videoOnce = false; // 是否执行过一次
let miniVideoOnce = false;
// 网页支持播放视频时
video.oncanplay = () => {
let observer = new IntersectionObserver((entries) => {
// 视频窗口出现在可视窗口时
if (entries[0].isIntersecting) {
if (!videoOnce) {
// 隐藏小窗
this.showMiniVideo = false;
// 同步播放时间
video.currentTime = miniVideo.currentTime;
// 同步播放状态
this.isVideoPlay = this.isMiniVideoPlay;
this.isVideoPlay ? video.play() : video.pause();
// 暂停小窗
this.isMiniVideoPlay = false;
miniVideo.pause();
// 因为会出现执行两次的情况,所有用这个变量来判断是否执行过一次
// 执行过一次后要在执行else里的动作才会解除执行过一次的状态
// 避免出现视频已暂停还执行暂停而报错,或其他问题
videoOnce = true;
miniVideoOnce = false;
}
} else {
if (!miniVideoOnce) {
this.showMiniVideo = true;
miniVideo.currentTime = video.currentTime;
this.isMiniVideoPlay = this.isVideoPlay;
this.isVideoPlay = false;
this.isMiniVideoPlay ? miniVideo.play() : miniVideo.pause();
video.pause();
miniVideoOnce = true;
videoOnce = false;
}
}
});
observer.observe(video);
};
总结
有个缺点就是 miniVideo 隐藏或显示时,会有一瞬间的卡顿。
更多推荐
已为社区贡献1条内容
所有评论(0)