html5新增了音频/视频(audio/video)的API。
这次我们先来了解video。
video 元素支持三种视频格式:
.ogg
.mp4
. webm
<video src="movie.ogg" >
你的浏览器不支持video
</video>
video 元素允许多个 source 元素。source 元素可以链接不同的视频文件。浏览器将使用第一个可识别的格式:
<video width="320" height="240" controls="controls">
<source src="movie.ogg" type="video/ogg">
<source src="movie.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
知道视频在移动端播放会出现很多坑,我们来踩踩坑。首先对video的Api还不熟悉,所以先不考虑移动端的兼容问题。首先来实现video的播放等功能。
video Api
这是我写的html元素标签。
现在我是把Dom元素和js都放在了body标签中。dom中绑定的onclick之类的事件,必须是全局的才能够正确获取。像settimeout函数里面定义的函数不是全局的,是局部的。出了settimeout函数就获取不到了,所以绑定的事件不能写在任何函数里。如果不想污染全局可以选择写一个匿名自执行函数里写响应事件,然后通过addEventListener绑定监听,而不是在html绑定监听事件。
html中事件里面的this代表什么?
this作为事件的参数传递的话,指的是触发事件的html element。如果不传this,第一个参数是event, event.target 和这里的this是等价的。
onclick事件之类的event.offsetX 和 event.target.offsetWidth。一个在target上获取。一个直接获取。
var video = document.querySelector('.videoSource');
获取视频总时长
video元素属性duration返回音频视频长度,单位为s。初始化显示获取需要用到video的loadeddata事件。
鼠标点击快进或者后退
直接修改video.currentTime属性即可。
全屏播放
h5暴露了一个webkitRequestFullScreen方法,可以让每个dom都请求全屏,当然video标签也可以使用。
但是一些安卓机不支持该属性,如小米手机,所以需要在调用的时候进行一下判断
if (video.webkitSupportsFullscreen) {
video.webkitEnterFullscreen();
} else {
video.webkitRequestFullScreen();
}
页面生成二维码扫描
这几天总看h5通过一个二维码扫描就可以访问了。于是搜了一下。
二维码生成方法
只需在页面中加一段代码
thisURL = document.URL;
strwrite =
"<img src='https://chart.googleapis.com/chart?cht=qr&chs=150x150&choe=UTF-8&chld=L|4&chl="
+ thisURL + "' width='150' height='150' alt='网址URL 二维码生成' />";
document.write( strwrite );
二维码是生成了,但是手机扫描却会出现网络错误打不开,我本地写了个项目,打开是file:// 这种方式。其实手机扫二维码也就是通过手机打开的生成二维码的document.URL。手机上去访问file:// 肯定是加载不到的。于是我就用http-sever生成一个web服务器。一般可以生成两个可访问的地址
http://127.0.0.1:8000
http://172.16.222.157:8000
我开始用第一个地址打开,不行,还是网络错误。因为手机也无法识别127.0.0.1。我突然就想到一个局域网内是可以互相访问ip的。第二个不就是ip吗。我的手机和电脑都连接的是公司的无线,应该可以访问了吧。果然换成第二个地址手机就可以访问了。不过微信扫描二维码会出现缓存问题。
android video播放进度控制
页面内联播放问题
在iOS Safari和一些安卓的一些浏览器下播放视频的时候,不能在h5页面中播放视频,系统会自动接管视频,就是会默认全屏播放。如何禁止呢?
增加属性webkit-playsinline playsinline
就可以了
<video id="player" webkit-playsinline playsinline >
移动端手势触发事件
移动端多用touch事件,而不是click事件。并且click有两个著名的bug,移动端300ms点击延迟和点击穿透问题。所以有很多库对事件进行封装,用封装的tap代替click事件。
我们这个视频播放的例子主要是看video在手机端的一些问题。设计手势事件很少,并且设置了content="width=device-width"
所以移动端浏览器自动就取消了300ms的延迟。
遇到的问题
-
给video绑定的loadeddata事件怎么不触发了呢
找了快一早上的原因。
最后发现问题的根本是因为link引入外部css会阻塞后面内联脚本的执行。所以css还没加载完,video元素就已经加载完了因为css不会会阻塞DOM的加载会阻塞DOM的渲染。这时候该video响应的loadeddata绑定的事件没响应呢video的状态都已经变了,早都已经过了。结果等css加载完成之后,已经不会响应loadeddata的事件了。如果绑定的是onplay事件还是可以响应的,因为这个是视频播放时候才会触发的。或者把css异步加载,给link添加media="none"就可以异步加载。 -
给video绑定loadeddata的函数传入一个函数执行就可以触发?
答案肯定是否定的,给ele.addEventListener('click', func)这是给ele绑定click事件,但是如果变成ele.addEventListener('click', func())。就是js解析到这句会执行func函数。如果func函数没有return一个函数,则就没有绑定上事件。 - 判断是否移动端
//如果没有触摸事件 判定为PC
var ua = navigator.userAgent.toLowerCase();
var isTocuh = ("ontouchstart" in window) || (ua.indexOf("touch") !== -1) || (ua.indexOf("mobile") !== -1);
-
视频旋转尺寸问题
防止视频尺寸因为宽高设置乱掉,需要给video设置object-fit: contain;
把视频旋转90deg。再把宽和高重新设置一下。这就可以实现旋转全屏了呀。可是结果出来为什么是这个样子?
左边和下边都有空隙并且视频内容偏移了。
所以不能单单的旋转90°,还要设置translate
var info = [
document.documentElement.clientWidth || document.body.clientWidth,
document.documentElement.clientHeight || document.body.clientHeigth
],
w = info[0],
h = info[1],
cha = Math.abs(h - w) / 2;
videoBox.style.transform = 'translate(-' + cha + 'px,' + cha + 'px) rotate(90deg)';
H5 直播避坑指南
html5 实现video标签的自定义播放进度条
HTML5 VideoAPI,打造自己的Web视频播放器