zoukankan      html  css  js  c++  java
  • 分享一个基于HTML5实现的视频播放器

    原文:http://www.cnblogs.com/w-wanglei/p/5763103.html

     

    什么是hivideo?

        最近一段时间在使用PhoneGap开发一个App应用,App需要播放视频,本想直接使用html5的video,但使用它在全屏播放时不支持横屏播放,只能放弃。最终决定还是自己封装一个播放器算了,免得以后要扩展功能麻烦。

        最近迷上hi这个单词,所以我给这个播放器取名叫做:hivideo。

        hivideo是一款基于html5的视频播放器,摒弃video原有的播放控制条样式,自己重写了一次。支持暂停、播放进度控制、声音控制、全屏播放。如果是要在手机端使用hivideo,全屏播放时还支持横屏播放。

        hivideo最终实现的效果如下:

    image

    如何使用hivideo?

        hivideo目录结构:

    复制代码
    assets
    
    ----images
    
    ----hivideo.css
    
    hivideo.js
    复制代码

        要想使用hivideo,首先得在主界面引入样式hivideo.css文件。

    <link rel="stylesheet" href="assets/hivideo.css" />

        hivideo.js文件可在主页面直接引用,同时也支持CommonJs、AMD规范。

        在需要转换为hivideo播放器的video标签上添加属性:

    <video ishivideo="true"></video>

        hivideo会自动把上面的video元素转换为hivideo播放器。我们还可以在video标签上设置播放属性:

        1.autoplay: 自动播放。

        2.isrotate:全屏是否横屏播放,如果在手机端使用hivideo,我们可以设置该属性为true,表示全屏播放时横屏显示。

        3.autoHide:播放视频时自动隐藏控制条。

        使用方式:

    <video ishivideo="true" autoplay="true" isrotate="false" autoHide="true">
        <source src="http://www.html5videoplayer.net/videos/madagascar3.mp4" type="video/mp4">
    </video>

        如果是后期动态添加的video元素,也可以通过hivideo动态加载。例如页面动态添加了一个id为”player”的video元素,可通过如下方式把video转换为hivideo播放器:

    hivideo(document.getElementById("player"));

        在线演示Demo:https://heavis.github.io/hivideo/index.html

        开源地址:https://github.com/heavis/hivideo

    如何隐藏浏览器的播放器样式

        目前大多数浏览器都支持video元素,并且不同浏览器实现的video样式也不尽相同。

        chrome实现的播放器样式:

    image

        Firefox实现的播放器样式:

    image

        IE实现的播放器样式:

    image

       

        为了让播放器在各个浏览器下样式统一,首先要隐藏各个浏览器实现的样式。但一般我们通过浏览器开发工具查看不到播放器下的元素,因为这些元素都是阴影元素,它们是通过文档片段附加到video上,对于文档流是不可见的。
        如何查看浏览器下的阴影元素?Chrome为开发人员提供了可选项,打开开发者工具->Settings->General页签,我们能看到Elments有一个叫做”Show user agent shadow DOM”的选项:

    image

        勾选上该选项,现在我们通过开发工具可以查看到video下的播放元素:

    image

        上图中<div pseudo=”-webkit-media-controls”>元素就是控制条的容器,我们只要设置它的display为none就可以隐藏掉控制条,但也需要兼容各个浏览器:

    复制代码
    video[ishivideo="true"]::-webkit-media-controls{
    display:none !important;
    }
    
    video[ishivideo="true"]::-moz-media-controls{
    display:none !important;
    }
    
    video[ishivideo="true"]::-o-media-controls{
    display:none !important;
    }
    
    video[ishivideo="true"]::media-controls{
    display:none !important;
    }
    复制代码

        这里我遇到一个费解的问题,把上面的样式通过合并的方式写是无效的,下面的写法不能隐藏掉阴影元素:

    复制代码
    video[ishivideo="true"]::-webkit-media-controls,
    video[ishivideo="true"]::-moz-media-controls,
    video[ishivideo="true"]::-o-media-controls,
    video[ishivideo="true"]::media-controls{
        display:none !important;
    }
    复制代码

        隐藏浏览器阴影元素后就可以开始动手实现自己的控制条了。实现之前,我们得了解video提供的API。

    播放器常用API

        各个浏览器操作播放器提供的API名称一般都带有厂商前缀,所有基本上每一个API函数都对应多个版本,需要考虑兼容性。

        1.全屏事件

    ["fullscreenchange", "webkitfullscreenchange", "mozfullscreenchange", "MSFullscreenChange"].forEach(function(eventType){
        document.addEventListener(eventType, function(event){
    
        })
    });

        如果播放器全屏状态放生变化上面的事件就会触发。上面的事件我们只知道全屏状态发生变化,但不知道当前是进入全屏还是退出全屏。还需要结合全屏状态API。

        2.当前是否全屏状态

    复制代码
    hivideo.prototype.isFullScreen = function(){
        return document.fullscreenElement ||
            document.webkitFullscreenElement ||
            document.mozFullScreenElement || 
            document.msFullscreenElement;
    };
    复制代码

        上面是hivideo封装的判断是否全屏的函数。

        3.进入全屏模式

    复制代码
    if (video.requestFullscreen) {
        video.requestFullscreen();
    } else if (video.webkitRequestFullscreen) {
        video.webkitRequestFullscreen();
    } else if (video.mozRequestFullScreen) {
        video.mozRequestFullScreen();
    } else if (video.msRequestFullscreen) {
        video.msRequestFullscreen();
    }
    复制代码

         

        4.退出全屏模式

    复制代码
    if (document.exitFullscreen) {
        document.exitFullscreen();
    } else if (document.webkitExitFullscreen) {
        document.webkitExitFullscreen();
    } else if (document.mozCancelFullScreen) {
        document.mozCancelFullScreen();
    } else if (document.msExitFullscreen) {
        document.msExitFullscreen();
    }
    复制代码

       

        5.播放状态

        video.paused:true表示未播放, false表示正在播放。

        6.播放视频

        video.play()

        7.暂停播放
        video.pause()

        8.是否静音
        video.muted = true, 静音
        Video.muted = false,不静音

        9.声音控制

        设置video.volume控制声音,值的范围0到100。

        10.当前播放时间
        video.currentTime,可读可写,单位为妙。可通过<input type=’range’>的值显示播放进度。
       

        11.视频总周期
        video.duration,单位为妙。

        12.播放时间更新事件

    video.addEventListener("timeupdate", function(){
    });

       

        13.视频元数据加载完成事件

        一般播放视频时都会显示视频总时长,触发loadedmetadata事件时元数据已经加载完成,所以可以在该事件中设置总时长的显示。

    video.addEventListener("loadedmetadata", function(){
    }

        14.视频播放结束事件

    video.addEventListener("ended", function(){
    }

        有了上面列出的API,要实现自定义播放器就比较容易了,在自己实现播放器的过程中对应位置调用对应API即可。

    如何实现横屏播放

        原理很简单,在全屏时播放器容器沾满了整个屏幕,我们可以给容器附加一个自定义样式,让容器旋转90度。

    复制代码
    .rotate90{
        -webkit-transform: rotate(90deg);
        -moz-transform: rotate(90deg);
        -ms-transform: rotate(90deg);
        -o-transform: rotate(90deg);
        transform: rotate(90deg);
    }
    复制代码

        旋转后的容器宽度和高度也要调整,需要把屏幕的高度screen.height赋给容器的宽度,而容器的高度设置为屏幕的宽度。这样就实现了全屏播放效果。下面是全屏播放控制的完整代码:

    复制代码
    hivideo.prototype.bindFullEvent = function(){
        var self = this;
        var origWidth = origHeight = 0;
    
        ["fullscreenchange", "webkitfullscreenchange", "mozfullscreenchange", "MSFullscreenChange"].forEach(function(eventType){
            var curFullhivideoId = null;
            document.addEventListener(eventType, function(event){
            if((curFullhivideoId = document.body.getAttribute("curfullHivideo")) && curFullhivideoId !== self.videoId_ ){
                return;
            }
            var isRotate = self.options.isrotate;
            if(self.isFullScreen()){
                var cltHeight = isRotate ? window.screen.width : window.screen.height;
                var cltWidth = isRotate ? window.screen.height : window.screen.width;
                if(isRotate && !hivideo.hasClass(self.videoParent, "rotate90")){
                    hivideo.addClass(self.videoParent, "rotate90");
                }
                self.videoParent.style.height = cltHeight + "px";
                self.videoParent.style.width = cltWidth + "px";
            }else{
                if(isRotate) self.videoParent.className = self.videoParent.className.replace("rotate90", "").trim();
                    self.videoParent.style.height = origHeight + "px";
                    self.videoParent.style.width = origWidth + "px";
                }
                })
            });
    
            self.fullBtn && self.fullBtn.addEventListener("click", function(){
            if(!self.isFullScreen()){
                document.body.setAttribute("curfullHivideo", self.videoId_);
                origWidth = self.videoParent.offsetWidth;
                origHeight = self.videoParent.offsetHeight;
                // go full-screen
                if (self.videoParent.requestFullscreen) {
                self.videoParent.requestFullscreen();
                } else if (self.videoParent.webkitRequestFullscreen) {
                self.videoParent.webkitRequestFullscreen();
                } else if (self.videoParent.mozRequestFullScreen) {
                    self.videoParent.mozRequestFullScreen();
                } else if (self.videoParent.msRequestFullscreen) {
                    self.videoParent.msRequestFullscreen();
                }
                    self.exchangeBtnStatus(this, false);
            }else{
            // exit full-screen
                if (document.exitFullscreen) {
                    document.exitFullscreen();
                } else if (document.webkitExitFullscreen) {
                    document.webkitExitFullscreen();
                } else if (document.mozCancelFullScreen) {
                    document.mozCancelFullScreen();
                } else if (document.msExitFullscreen) {
                    document.msExitFullscreen();
                }
    
                self.exchangeBtnStatus(this, true);
            }
        });
    
        return self;
    };
    复制代码

    支持CommonJS、AMD规范

        1.CommonJS支持

    复制代码
    (function(global, factory){
        "use strict";
        //支持commonJs规范
        if(typeof module === "object" && typeof module.exports === "object"){
            module.exports = factory(global);
        }else{
            factory(global);
        }
    }(typeof window !== "undefined" ? window : this, function(window)
    }
    复制代码

        2.AMD支持

    复制代码
    //支持AMD规范
    if (typeof define === "function" && define.amd){
        define("hivideo", [], function(){
            return hivideo;
        })
    }
  • 相关阅读:
    JavaEE中Filter实现用户登录拦截
    【Tomcat】如何注册Tomcat到Window Service服务
    案例分析:项目组内踢皮球事件
    最大子序列求和问题
    《游戏脚本的设计与开发》-第一部分总结 文字脚本的功能扩展和一个游戏测试
    ajax异步请求实例
    创建用于编译和运行Java程序的批处理文件
    Codeforces Round #189 (Div. 2)
    新的研究方向
    怎样在android实现uc和墨迹天气那样的左右拖动效果
  • 原文地址:https://www.cnblogs.com/liangbo-/p/6547298.html
Copyright © 2011-2022 走看看