html5新增了音頻/視頻(audio/video)的API。
這次我們先來(lái)了解video。
video 元素支持三種視頻格式:
.ogg
.mp4
. webm
<video src="movie.ogg" >
你的瀏覽器不支持video
</video>
video 元素允許多個(gè) source 元素。source 元素可以鏈接不同的視頻文件。瀏覽器將使用第一個(gè)可識(shí)別的格式:
<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>
知道視頻在移動(dòng)端播放會(huì)出現(xiàn)很多坑,我們來(lái)踩踩坑。首先對(duì)video的Api還不熟悉,所以先不考慮移動(dòng)端的兼容問(wèn)題。首先來(lái)實(shí)現(xiàn)video的播放等功能。
video Api

這是我寫(xiě)的html元素標(biāo)簽。
??現(xiàn)在我是把Dom元素和js都放在了body標(biāo)簽中。dom中綁定的onclick之類的事件,必須是全局的才能夠正確獲取。像settimeout函數(shù)里面定義的函數(shù)不是全局的,是局部的。出了settimeout函數(shù)就獲取不到了,所以綁定的事件不能寫(xiě)在任何函數(shù)里。如果不想污染全局可以選擇寫(xiě)一個(gè)匿名自執(zhí)行函數(shù)里寫(xiě)響應(yīng)事件,然后通過(guò)addEventListener綁定監(jiān)聽(tīng),而不是在html綁定監(jiān)聽(tīng)事件。

html中事件里面的this代表什么?
this作為事件的參數(shù)傳遞的話,指的是觸發(fā)事件的html element。如果不傳this,第一個(gè)參數(shù)是event, event.target 和這里的this是等價(jià)的。
onclick事件之類的event.offsetX 和 event.target.offsetWidth。一個(gè)在target上獲取。一個(gè)直接獲取。
var video = document.querySelector('.videoSource');
獲取視頻總時(shí)長(zhǎng)
video元素屬性duration返回音頻視頻長(zhǎng)度,單位為s。初始化顯示獲取需要用到video的loadeddata事件。
鼠標(biāo)點(diǎn)擊快進(jìn)或者后退
直接修改video.currentTime屬性即可。
全屏播放
h5暴露了一個(gè)webkitRequestFullScreen方法,可以讓每個(gè)dom都請(qǐng)求全屏,當(dāng)然video標(biāo)簽也可以使用。
但是一些安卓機(jī)不支持該屬性,如小米手機(jī),所以需要在調(diào)用的時(shí)候進(jìn)行一下判斷
if (video.webkitSupportsFullscreen) {
video.webkitEnterFullscreen();
} else {
video.webkitRequestFullScreen();
}
頁(yè)面生成二維碼掃描
這幾天總看h5通過(guò)一個(gè)二維碼掃描就可以訪問(wèn)了。于是搜了一下。
二維碼生成方法
只需在頁(yè)面中加一段代碼
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='網(wǎng)址URL 二維碼生成' />";
document.write( strwrite );
二維碼是生成了,但是手機(jī)掃描卻會(huì)出現(xiàn)網(wǎng)絡(luò)錯(cuò)誤打不開(kāi),我本地寫(xiě)了個(gè)項(xiàng)目,打開(kāi)是file:// 這種方式。其實(shí)手機(jī)掃二維碼也就是通過(guò)手機(jī)打開(kāi)的生成二維碼的document.URL。手機(jī)上去訪問(wèn)file:// 肯定是加載不到的。于是我就用http-sever生成一個(gè)web服務(wù)器。一般可以生成兩個(gè)可訪問(wèn)的地址
http://127.0.0.1:8000
http://172.16.222.157:8000
我開(kāi)始用第一個(gè)地址打開(kāi),不行,還是網(wǎng)絡(luò)錯(cuò)誤。因?yàn)槭謾C(jī)也無(wú)法識(shí)別127.0.0.1。我突然就想到一個(gè)局域網(wǎng)內(nèi)是可以互相訪問(wèn)ip的。第二個(gè)不就是ip嗎。我的手機(jī)和電腦都連接的是公司的無(wú)線,應(yīng)該可以訪問(wèn)了吧。果然換成第二個(gè)地址手機(jī)就可以訪問(wèn)了。不過(guò)微信掃描二維碼會(huì)出現(xiàn)緩存問(wèn)題。
android video播放進(jìn)度控制
頁(yè)面內(nèi)聯(lián)播放問(wèn)題
在iOS Safari和一些安卓的一些瀏覽器下播放視頻的時(shí)候,不能在h5頁(yè)面中播放視頻,系統(tǒng)會(huì)自動(dòng)接管視頻,就是會(huì)默認(rèn)全屏播放。如何禁止呢?
增加屬性webkit-playsinline playsinline就可以了
<video id="player" webkit-playsinline playsinline >
移動(dòng)端手勢(shì)觸發(fā)事件
移動(dòng)端多用touch事件,而不是click事件。并且click有兩個(gè)著名的bug,移動(dòng)端300ms點(diǎn)擊延遲和點(diǎn)擊穿透問(wèn)題。所以有很多庫(kù)對(duì)事件進(jìn)行封裝,用封裝的tap代替click事件。
我們這個(gè)視頻播放的例子主要是看video在手機(jī)端的一些問(wèn)題。設(shè)計(jì)手勢(shì)事件很少,并且設(shè)置了content="width=device-width"所以移動(dòng)端瀏覽器自動(dòng)就取消了300ms的延遲。
遇到的問(wèn)題
-
給video綁定的loadeddata事件怎么不觸發(fā)了呢
找了快一早上的原因。
??最后發(fā)現(xiàn)問(wèn)題的根本是因?yàn)?strong>link引入外部css會(huì)阻塞后面內(nèi)聯(lián)腳本的執(zhí)行。所以css還沒(méi)加載完,video元素就已經(jīng)加載完了因?yàn)?a target="_blank" rel="nofollow">css不會(huì)會(huì)阻塞DOM的加載會(huì)阻塞DOM的渲染。這時(shí)候該video響應(yīng)的loadeddata綁定的事件沒(méi)響應(yīng)呢video的狀態(tài)都已經(jīng)變了,早都已經(jīng)過(guò)了。結(jié)果等css加載完成之后,已經(jīng)不會(huì)響應(yīng)loadeddata的事件了。如果綁定的是onplay事件還是可以響應(yīng)的,因?yàn)檫@個(gè)是視頻播放時(shí)候才會(huì)觸發(fā)的?;蛘甙裞ss異步加載,給link添加media="none"就可以異步加載。 -
給video綁定loadeddata的函數(shù)傳入一個(gè)函數(shù)執(zhí)行就可以觸發(fā)?
?? 答案肯定是否定的,給ele.addEventListener('click', func)這是給ele綁定click事件,但是如果變成ele.addEventListener('click', func())。就是js解析到這句會(huì)執(zhí)行func函數(shù)。如果func函數(shù)沒(méi)有return一個(gè)函數(shù),則就沒(méi)有綁定上事件。 - 判斷是否移動(dòng)端
//如果沒(méi)有觸摸事件 判定為PC
var ua = navigator.userAgent.toLowerCase();
var isTocuh = ("ontouchstart" in window) || (ua.indexOf("touch") !== -1) || (ua.indexOf("mobile") !== -1);
-
視頻旋轉(zhuǎn)尺寸問(wèn)題
?防止視頻尺寸因?yàn)閷捀咴O(shè)置亂掉,需要給video設(shè)置object-fit: contain;
?把視頻旋轉(zhuǎn)90deg。再把寬和高重新設(shè)置一下。這就可以實(shí)現(xiàn)旋轉(zhuǎn)全屏了呀??墒墙Y(jié)果出來(lái)為什么是這個(gè)樣子?

左邊和下邊都有空隙并且視頻內(nèi)容偏移了。
所以不能單單的旋轉(zhuǎn)90°,還要設(shè)置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 實(shí)現(xiàn)video標(biāo)簽的自定義播放進(jìn)度條
HTML5 VideoAPI,打造自己的Web視頻播放器