HTML5 视频事件提供改进和提高网页效率的方法。
- 为什么要使用事件?
- 我的网页准备好了么?
- 我处于什么位置?
- 现在该按钮可执行哪些操作?
- 该操作已完成?
- 相关主题
为什么要使用事件?
HTML5 视频对象提供了很多事件,这些事件可以帮助简化和增强网页的内容。 在此处将看到使用事件检查内容是否可用、视频播放状态以及如何在视频中监视当前播放位置的示例。
我的网页准备好了么?
对于使用视频的网页,你会对两种级别的“准备”感兴趣;当加载页面元素时以及当可以播放内容时。
HTML5 视频页面中最常用的第一个任务就是查看浏览器是否支持视频。完成此操作的方法通常为:查看是否在页面上创建了视频元素,以及脚本所需的属性是否可用。如果已在文档对象模型 (DOM) 中加载或创建了元素,则脚本只能检查元素。检查网页元素是否完成加载的最好方法是在 document 对象上使用 DOMContentLoaded 事件。当页面元素完成加载并且基本 DOM 可用时引发此事件。 以下示例为调用网页的 "init()" 函数的 DOMContentLoaded 创建处理程序。
document.addEventListener("DOMContentLoaded", function () { init(); }, false);
该示例的 "init()" 函数封装了页面脚本部分的所有功能。"init()" 函数设置多个全局变量,即 "video"、"vLength" 和 "pgFlag"。这些变量提供视频对象、当前已加载的视频的长度(之后用于计算)以及用于跟踪进度的标志。
var video = document.getElementById("Video1"); var vLength; var pgFlag =""; // used for progress tracking
然后,测试视频变量以查看 canPlayType 属性是否可用。如果可用,则支持 HTML5 video 元素并且执行所有其他代码。如果不支持视频,则语句 (video.canPlayType) 将返回 False 并显示一条消息。确认支持视频后,通过显示样式启用输入字段。
if (video.canPlayType) { // tests that we have HTML5 video support // show the input field and load button document.getElementById("inputField").style.display = "block";
此时,可以在输入字段中键入文件并进行加载。根据视频文件所在的位置,如果任何网络或服务器速度缓慢,则可能会在加载其余部分网页时阻止准备视频。以下示例使用oncanplay 事件通知何时视频加载内容已足够用于开始播放。引发 oncanplay 事件时,处理程序显示播放控件以通知它已准备就绪可以开始播放了。
// content has loaded, display buttons and set up events video.addEventListener("canplay", function () { document.getElementById("buttonbar").style.display = "block"; }, false);
视频加载到视频对象中时,要加载的首要内容之一就是元数据,它包含有关视频的信息。以下示例使用 onloadedmetadata 事件来确定视频有多长。 当 video 对象获取有关内容的足够信息以了解持续时间后,引发 onloadedmetadata 事件。
// display video duration when available video.addEventListener("loadedmetadata", function () { vLength = video.duration.toFixed(1); document.getElementById("vLen").textContent = vLength; // global variable }, false);
我处于什么位置?
上一示例显示了如何在加载视频后获取视频的持续时间或长度。视频开始播放后,可以使用 ontimeupdate 事件来获取视频中的当前位置。当 currentTime 属性发生更改时,引发 ontimeupdate 事件。在事件处理程序中,从视频对象中检索 currentTime 的值并进行显示。currentTime 属性是浮点型变量,该变量可以从 12 位中获取小数位置。但是,出于性能方面的考虑,在 Windows Internet Explorer 中一秒内仅引发该事件四次。若要在示例中显示,则需要使用 "toFixed()" 方法将 currentTime 取舍为一位。运行视频时,会更新和显示当前时间。
// display the current and remaining times video.addEventListener("timeupdate", function () { // Current time var vTime = video.currentTime; document.getElementById("curTime").textContent = vTime.toFixed(1); document.getElementById("vRemaining").textContent = (vLength - vTime).toFixed(1); }, false);
该示例还通过从持续时间中减去当前时间来报告剩余时间。
现在该按钮可执行哪些操作?
在视频播放器控件中的一个常见趋势是在两个状态之间切换按钮,如“播放”和“暂停”或者“声音”和“静音”。使用 JavaScript 控制 HTML5 视频播放器中的示例在按钮处理程序中实现该操作。例如,在单击“播放”按钮时,单击处理程序检查 paused 属性并播放或暂停视频播放。播放视频时,它还会将该按钮切换为暂停文本,暂停视频时将该按钮切换为播放文本。大多数时间它都是这样工作的,但如果视频元素启用了 controls,则两个按钮设置无法同步。此示例显示在播放按钮处理程序中暂停属性的用法。
// play video function vidplay(evt) { if (video.src == "") { // inital source load getVideo(); } button = evt.target; // get the button id to swap the text based on the state if (video.paused) { // play the file, and display pause symbol video.play(); button.textContent = "||"; } else { // pause the file, and display play symbol video.pause(); button.textContent = ">"; } }
最好是使用 onpause 和 onplaying 事件保持按钮同步。与在单击按钮时只检查暂停属性的上一示例不同,下一示例在视频播放状态更改时切换按钮,而不管按钮如何切换。
// paused and playing events to control buttons video.addEventListener("pause", function () { document.getElementById("play").textContent = ">"; }, false); video.addEventListener("playing", function () { document.getElementById("play").textContent = "||"; }, false);
在此页面的结尾处尝试该示例并注意外部按钮和视频对象中的内置控件如何保持同步。
可以对 onvolumechange 事件使用相同的技术以控制静音按钮上的图形。由于没有单独的静音和音量事件,因此下一示例使用 onvolumechange 来处理两个状态。
video.addEventListener("volumechange", function () { if (video.muted) { // if muted, show mute image document.getElementById("mute").innerHTML = "<img alt='volume off button' src='mute2.png' />" } else { // if not muted, show not muted image document.getElementById("mute").innerHTML = "<img alt='volume on button' src='vol2.png' />" } }, false);
在此示例中,引发 onvolumechange 事件时,"if" 语句测试 muted 属性。如果 video 对象的声道为静音,则显示静音图形;否则显示声音图形。随着图形更改,alt 文本也会更改以提供精确描述作为辅助功能。
注意 在用户将其鼠标悬停在元素上方时,所有按钮、输入元素以及视频元素都使用 title 特性来提供工具提示。这种做法还会为屏幕读取器设备提供标识文本。
该操作已完成?
HTML5 视频播放器需要缓冲用于播放的内容。如果视频内容较大,在页面可能需要管理播放并发送消息以为用户提供更好的体验。例如,如果下载需要的时间较长,则可以使用事件来通知用户出现的问题,而不只是在没有任何说明的情况下停止视频。可以使用 onstalled、onwaiting 或 onended 来确定视频中断时的操作。 下表描述可以用来管理播放和用户期望的事件。
事件 | 说明 |
---|---|
oncanplaythrough | 在不需要进一步缓冲就可以播放直至文件结束时引发。 |
onloadstart | 在 Internet Explorer 开始查找媒体数据时引发。在从站点请求视频(或音频)资源时发生此事件,并且每个请求只发生一次。 |
onloadeddata | 在当前播放位置加载媒体数据时引发。视频可以开始播放。 |
onended | 在播放结束时引发。 |
onemptied | 在视频对象重置为其初始状态时引发。 |
onstalled | 在下载被中断三秒以上时引发。这可以指示网络问题。 |
onwaiting | 在播放由于视频的下一帧不可用(可能需要缓冲)而停止时引发。 |
onprogress | 引发此事件以指示正在下载媒体内容。下载完成后停止引发。 |
ondurationchange | 在 onloadstart 之后和 onloadedmetadata 之前立即引发。 |
此代码示例是本主题中所示示例的完整代码,它包含显示适用于此处提到的下载和缓冲的事件的内容。
注意 此示例使用图像来表示声音打开 和声音关闭 。
<html > <head> <title>Video events example</title> <!-- Uncomment the following meta tag if you have issues rendering this page on an intranet or local site. --> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <script type="text/javascript"> document.addEventListener("DOMContentLoaded", function () { init(); }, false); function init() { // Master function, encapsulates all functions var video = document.getElementById("Video1"); var vLength; var pgFlag =""; // used for progress tracking if (video.canPlayType) { // tests that we have HTML5 video support // show the input field and load button document.getElementById("inputField").style.display = "block"; // video button helper functions // play video function vidplay(evt) { if (video.src == "") { // inital source load getVideo(); } if (video.paused) { // play the file, and display pause symbol video.play(); } else { // pause the file, and display play symbol video.pause(); } } // load video file from input field function getVideo() { var fileURL = document.getElementById("videoFile").value; // get input field if (fileURL != "") { video.src = fileURL; video.load(); // if HTML source element is used document.getElementById("play").click(); // start play } else { errMessage("Enter a valid video URL"); // fail silently } } // button helper functions // skip forward, backward, or restart function setTime(tValue) { // if no video is loaded, this throws an exception try { if (tValue == 0) { video.currentTime = tValue; } else { video.currentTime += tValue; } } catch (err) { // errMessage(err) // show exception errMessage("Video content might not be loaded"); } } // change volume based on incoming value function setVol(value) { var vol = video.volume; vol += value; // test for range 0 - 1 to avoid exceptions if (vol >= 0 && vol <= 1) { // if valid value, use it video.volume = vol; } else { // otherwise substitute a 0 or 1 video.volume = (vol < 0) ? 0 : 1; } } // button events // Play document.getElementById("play").addEventListener("click", vidplay, false); // Restart document.getElementById("restart").addEventListener("click", function () { setTime(0); }, false); // Skip backward 10 seconds document.getElementById("rew").addEventListener("click", function () { setTime(-10); }, false); // Skip forward 10 seconds document.getElementById("fwd").addEventListener("click", function () { setTime(10); }, false); // set src == latest video file URL document.getElementById("loadVideo").addEventListener("click", getVideo, false); // volume buttons document.getElementById("volDn").addEventListener("click", function () { setVol(-.1); // down by 10% }, false); document.getElementById("volUp").addEventListener("click", function () { setVol(.1); // up by 10% }, false); // playback speed buttons document.getElementById("slower").addEventListener("click", function () { video.playbackRate -= .25; }, false); document.getElementById("faster").addEventListener("click", function () { video.playbackRate += .25; }, false); document.getElementById("normal").addEventListener("click", function () { video.playbackRate = 1; }, false); document.getElementById("mute").addEventListener("click", function (evt) { if (video.muted) { video.muted = false; } else { video.muted = true; } }, false); // any video error will fail with message video.addEventListener("error", function (err) { errMessage(err); }, true); // content has loaded, display buttons and set up events video.addEventListener("canplay", function () { document.getElementById("buttonbar").style.display = "block"; }, false); // display video duration when available video.addEventListener("loadedmetadata", function () { vLength = video.duration.toFixed(1); document.getElementById("vLen").textContent = vLength; // global variable }, false); // display the current and remaining times video.addEventListener("timeupdate", function () { // Current time var vTime = video.currentTime; document.getElementById("curTime").textContent = vTime.toFixed(1); document.getElementById("vRemaining").textContent = (vLength - vTime).toFixed(1); }, false); // paused and playing events to control buttons video.addEventListener("pause", function () { document.getElementById("play").textContent = ">"; }, false); video.addEventListener("playing", function () { document.getElementById("play").textContent = "||"; }, false); video.addEventListener("volumechange", function () { if (video.muted) { // if muted, show mute image document.getElementById("mute").innerHTML = "<img alt='volume off button' src='mute2.png' />" } else { // if not muted, show not muted image document.getElementById("mute").innerHTML = "<img alt='volume on button' src='vol2.png' />" } }, false); // Download and playback status events. video.addEventListener("loadstart", function () { document.getElementById("ls").textContent = "Started"; }, false); video.addEventListener("loadeddata", function () { document.getElementById("ld").textContent = "Data was loaded"; }, false); video.addEventListener("ended", function () { document.getElementById("ndd").textContent = "Playback ended"; }, false); video.addEventListener("emptied", function () { document.getElementById("mt").textContent = "Video reset"; }, false); video.addEventListener("stalled", function () { document.getElementById("stall").textContent = "Download was stalled"; }, false); video.addEventListener("waiting", function () { document.getElementById("waiting").textContent = "Player waited for content"; }, false); video.addEventListener("progress", function () { pgFlag += "+"; if (pgFlag.length > 10) { pgFlag = "+"; } document.getElementById("pg").textContent = pgFlag; }, false); video.addEventListener("durationchange", function () { document.getElementById("dc").textContent = "Duration has changed"; }, false); video.addEventListener("canplaythrough", function () { document.getElementById("cpt").textContent = "Ready to play whole video"; }, false); } else { errMessage("HTML5 Video is required for this example"); // end of runtime } // display an error message function errMessage(msg) { // displays an error message for 5 seconds then clears it document.getElementById("errorMsg").textContent = msg; setTimeout("document.getElementById('errorMsg').textContent=''", 5000); } }// end of master </script> </head> <body > <div id= "inputField" style="display:none;" > <label>Type or paste a video URL: <br/> <input type="text" id="videoFile" style="width: 300px;" title="video file input field" value="http://ie.microsoft.com/testdrive/ieblog/2011/nov/pp4_blog_demo.mp4" /> <button id="loadVideo" title="Load video button" >Load</button> </label> </div> <video id="Video1" controls style="border: 1px solid blue;" height="240" width="320" title="video element"> HTML5 Video is required for this example </video> <div id="buttonbar" style="display: none; font-size:larger;")> <button id="restart" title="Restart button">[]</button> <button id="slower" title="Slower playback button">-</button> <button id="rew" title="Rewind button" ><<</button> <button id="play" title="Play button">></button> <button id="fwd" title="Forward button" >>></button> <button id="faster" title="Faster playback button">+</button> <button id="mute" title="Mute button" ><img alt="Volume on button" src="vol2.png" /></button> <br /> <label>Reset playback rate: </label><button id="normal" title="Reset playback rate button">=</button> <br /> <label> Volume: </label> <button id="volDn" title="Volume down button">-</button> <button id="volUp" title="Volume up button">+</button> <br /> <div id="status" >Length(seconds): <span id="vLen"></span> <br /> Current time: <span id="curTime" title="Current time"></span><br /> Remaining time: <span id="vRemaining" title="Remaining time"></span></div> </div> <br/> <div title="Error message area" id="errorMsg" style="color:Red;"></div> <div title="Event status area" > <label>oncanplaythrough: </label><span class="stats" id="cpt"></span><br /> <label>onloadstart: </label><span class="stats" id="ls"></span><br /> <label>onprogress: </label><span class="stats" id="pg"></span><br /> <label>onloadeddata: </label><span class="stats" id="ld"></span><br /> <label>onended: </label><span class="stats" id="ndd"></span><br /> <label>onemptied: </label><span class="stats" id="mt"></span><br /> <label>onstalled: </label><span class="stats" id="stall"></span><br /> <label>onwaiting: </label><span class="stats" id="waiting"></span><br /> <label>ondurationchange: </label><span class="stats" id="dc"></span><br /> </div> </body> </html>