react 在移动端实现视频的自动播放详细讲解请移步react 移动端 实现video的自动播放,在这篇文章里会更加详细的介绍到会有那些兼容问题
我们先来谈一谈这个需求,需求要求我们实现当一个视频被滚动到可视区内的时候自动播放,根据这个我们来分析一下怎么去实现它。
首先考虑以下两个重点问题
- 我们如何知道现在处于可视区的是那个视频
- 如何去触发视频自动播放/暂停
看过h5新增标签video
的api的同学都知道,通过document.getElementById
或者其他什么获取到这个video
,然后XX.paly()
即是播放,XX.pause()
是暂停。我们第二个问题解决了,那么第一个问题改如何解决呢,我阐述一下我的想法,直接来撸代码
我们先搭建一个结构,代码如下:
<div class="item" id="arr1">
<video
id="video-1"
controls="controls"
height="100%"
width="100%"
>
<source src="https://img.qiuchengwangluo.com/union/2019/08/3/20190917124846354378861.mp4" type="video/mp4" />
</video>
</div>
<div class="item" id="arr2">
<video
id="video-2"
controls="controls"
height="100%"
width="100%"
>
<source src="https://img.qiuchengwangluo.com/union/2019/08/3/20190917124846354378861.mp4" type="video/mp4" />
</video>
</div>
<div class="item" id="arr3">
<video
id="video-3"
controls="controls"
height="100%"
width="100%"
>
<source src="https://img.qiuchengwangluo.com/union/2019/08/3/20190917124846354378861.mp4" type="video/mp4" />
</video>
</div>
<div class="item" id="arr4">
<video
id="video-4"
controls="controls"
height="100%"
width="100%"
>
<source src="https://img.qiuchengwangluo.com/union/2019/08/3/20190917124846354378861.mp4" type="video/mp4" />
</video>
</div>
在实际的开发中这个结构基本上都是通过循环创建出来的,但是也不影响什么,我们继续,在script
设置三个初始值
let a = 1 // 设置一个初始值,
let DOMobj = '' // 用了保存getElementById获取到的元素数据
let clientData = this.getViewport() // 获取可视区的大小
这里讲解一下这三个值分别是用来干什么的
a
是用来保存当前第几个元素,与上文结构代码中的id
所对应
DOMobj
就是用了存储获取到的当前元素
clientData
是存储可视区的大小,下文要用了做判断元素是否在可视区内
这里粘贴一下阮一峰老师文章用Javascript获取页面元素的位置中的一段代码,如何获取当前页面的可视区的大小
function getViewport() {
if (document.compatMode == "BackCompat") {
return {
width: document.body.clientWidth,
height: document.body.clientHeight
}
} else {
return {
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight
}
}
}
通过阮一峰老师的代码我们获取到了当前页面的可视区的大小
然后我们需要写一个方法,其目的就是获取第一个视频所在的位置
function getDMOlocation() { // 获取元素的相关数据
DOMobj = document.getElementById(`arr${a}`)
cliHeight = (clientData.height-DOMobj.offsetHeight)/2
}
这里用到了在代码之初定义的a
,然后我们要在页面加载完以后去执行这个代码
这里的cliHeight
是计算元素距离视窗顶部多远是处于视窗中间的
window.onload = this.getDMOlocation()
这时候我们已经获取到了第一个包含视频元素的盒子所在的位置,我们只有去判断他是否被划出了可视区,或者再次进入了可视区
但是在这个之前我们应该先定义一个方法去获取当前元素的位置,这里在粘贴阮一峰老师的代码
function getElementViewTop(element) {
var actualTop = element.offsetTop;
var current = element.offsetParent;
while (current !== null) {
actualTop += current.offsetTop;
current = current.offsetParent;
}
if (document.compatMode == "BackCompat") {
var elementScrollTop = document.body.scrollTop;
} else {
var elementScrollTop = document.documentElement.scrollTop;
}
return actualTop - elementScrollTop;
}
通过上述代码我们可以获取到元素距离窗口顶部的距离,因为这个值会随着滚动而发生变化,所以我们要做滚动的时候去调用这方法,可以事实判断是否到达了想要播放的区域
首先我们先监听滚动事件
window.addEventListener('scroll', winScroll);
然后我们在写这个方法
function winScroll(e) {
let arr = this.getElementViewTop(DOMobj)
let viedos = document.getElementById(`video-${a}`)
if (arr<=cliHeight && -arr<=DOMobj.offsetHeight/2) {
viedos.play()
}else{
viedos.pause()
if (-arr>DOMobj.offsetHeight/2) {
a+=1
}else if (-arr<0) {
if (a === 1) {
return
}else{
a-=1
}
}
this.getDMOlocation()
}
};
这里解释一下这个方法是什么意思
arr
就是当前获取到的元素
viedos
是当前元素所包裹的视频元素
第一个判断是判断是否在可视区,同时满足划出可视区的区域不大于元素整体的一半,如果划出一半就暂停播放
if (-arr>DOMobj.offsetHeight/2) {
a+=1
}else if (-arr<0) {
if (a === 1) {
return
}else{
a-=1
}
}
this.getDMOlocation()
这段代码的意思就是向上划出了当前元素就获取下一个元素,如果向下划出了当前元素就减一获取之前的那元素,并且进行重新赋值。
到这里我们的代码就结束了。
这是一个很基础的写法,没有加上防抖节流什么的方法
如果有什么疑问可以留言,如果有什么高深的学问也请不吝赐教