项目介绍: 前后端分离,前端使用vue开发,有 android 和 iOS 原生开发,前端开发负责页面。
该项目为一款关注健康的软甲,涉及到健身的动作,存在很多视频播放的问题。在此过程中遇到很多困难和难题,主要包括,自动播放,iOS会自动打开他的播放器,视频全屏,插入音频,特在此记录一下,本文主要提供一些解决思路。
1. 非静音条件下实现 Android 和 iOS 自动播放
思路一:video 标签的 autoplay 属性,
该方法为大家比较熟知的方法,但是他的兼容性比较差,有些浏览器要求静音下才可以达到效果(muted)。
思路二:通过点击事件播放
这里包括诱导用户点击来播放视频,该方法较为简单,不讨论。
通过JS点击触发视频播放。该方法会报错,简单来说就是浏览器会识别出来这是非用户进行的点击,不能实现自动播放(是否可以通过 JS 点击事件的底层原理来实现,这个暂时未知,没有往这条路下面走)。
思路三: 先给 video 添加 muted 属性,视频播放之后再移除 muted 属性
该方法本人在 iOS 上测试时,添加 muted 属性确实可以实现自动播放,但是移除 muted属性之后,视频又暂停了。
思路四:和原生开发合作,模拟用户点击事件
关于移动端开发,前端负责页面,但很多方法和权限都是原生开发来提供接口的,关于视频是否能自动播放,原生开发那边是能够有权限的,原生开发那边是否允许视频自动播放也是可能的影响因素之一。
本项目是通过原生提供了一个事件,在该事件的回调方法中,调用自己的事件,调用自己的点击视频播放事件,这样能够绕过浏览器的识别,不会报思路二的错误。
这个方法,和思路二本质上是一样的,都是通过点击事件触发视频播放,思路二是通过 JS 直接点击,会被浏览器识别报错,而该方法往原生那边绕了一下,没有被浏览器拦截(本项目最终采用的就是这种方法)。
2. iOS 视频实现自动播放后,会自己打开他的播放页面
这个情况前端需要做的是在 video 标签中添加一些属性
主要是
webkit-playsinline
playsinline
x5-playsinline
这几个,如果还不能实现则需要 iOS 原生开发配合。
以下是本人视频标签所用到的一些属性
<template v-for="(item, index) in video">
<video
class="video"
:id="`myVideo-${index}`"
:src="item.src"
:key="`myVideo-${index}`"
v-show="index === currVideoIndex"
preload="auto"
:poster="item.img"
webkit-playsinline
playsinline
x5-playsinline
x-webkit-airplay="allow"
x5-video-player-type="h5"
:x5-video-player-fullscreen="true"
></video>
></template>
3. 关于视频全屏的问题
该项目的需求是当视频进入播放时,能够根据用户手机方向,自动旋转,且可以锁定在竖屏和横屏状态。在其他页面不能旋转。
思路一:前端实现
获取手机的宽高,通过 JS 监听 事件获取手机当前方向,需要全屏的时候,用一个<div></div>
包住视频标签,将手机的宽度给盒子作为高度,将手机的高度给盒子作为高度,然后将盒子和视频旋转90 °。
该方法需要注意的地方:
- 不同手机可能存在状态栏导航栏 高度的问题,注意获取到的高度;
- 状态栏的显示与隐藏可能需要原生开发提供接口;
- 盒子的CSS样式的调整较多,包括背景色,来回切换的边距,旋转中心,视频填充方式,不同手机的宽高比,视频是否居中等样式上的问题。
该方法本质上手机的方向并未改变,而是监听手机的方向,改变视频盒子样式(让盒子旋转)来达到视频全屏的效果。
思路二: 和原生开发合作
同样需要获取手机宽高以及监听手机当前方向,需要全屏的时候,调用原生方法,改变手机当前的方向。也同样需要调整视频盒子的宽高背景色及边距。
该方法需要注意的地方:
- 手机高度和状态栏导航栏高度的问题;
- 状态栏的显示与隐藏在原生那边控制旋转时就可以控制显示与隐藏;
- 该方法也需要调整盒子宽高,但不需要自己控制旋转。
该方法将旋转由原生控制,前端负责是否打开旋转,相较于第一种方法,减少了很多CSS 上的调整,避免了关于旋转上的问题。
贴一下个人在旋转时候操作样式的部分代码,仅供参考:
// 打开视频全屏播放
openFullScreenPlay() {
this.$refs.videoPlayPopup.style.marginTop = 0;
this.$refs.videoPlayPopup.style.width =
this.userMobileScreenHeight + "px";
this.$refs.videoPlayPopup.style.height =
this.userMobileScreenWidth + "px";
this.$refs.videoPlayPopup.style.backgroundColor = "black";
this.videoFullscreenControlsShow();
},
// 关闭视频全屏播放
closeFullScreenPlay() {
this.$refs.videoPlayPopup.style.width = this.userMobileScreenWidth + "px";
this.$refs.videoPlayPopup.style.height = null;
this.$refs.videoPlayPopup.style.backgroundColor = "transparent";
this.$refs.videoPlayPopup.style.marginTop = 40 + "vw";
document.body.style.height = 716;
document.body.style.margin = 0;
document.body.style.padding = 0;
this.videoFullscreenControlsShow();
},
4. 视频常用的一些方法事件等
关于视频控件的问题,本次项目没有单独封装一个控件,只用到了进度条,暂停,播放。
暂停: video.play()
播放: video.pause()
进度条可以通过 video.currentTime / video.duration *100
得到百分比
let _this = this;
let myVideo = document.getElementById(`myVideo`);
myVideo.ontimeupdate = () => {
_this.videoCurrPercentage = myVideo.currentTime / myVideo.duration *100
};
在视频指定位置插入语音也是利用 currentTime这个方法来实现的。
比如当视频播放到二十秒的时候播放一条语音
let myVideo = document.getElementById(`myVideo`);
myVideo.ontimeupdate = () => {
if (myVideo.currentTime>=20){
document.getElementById('audio').play()
}
};
除了timeupdate还有ended 和error 分别对视频播放结束,和视频播放错误等做出处理。
6.移动端视频优化方面
目前对于移动端视频优化方面,只做了一个load(),暂时还没有其他优化,欢迎大家讨论。
如何错误,欢迎指正。欢迎大家一起讨论。谢谢大家。