three.js开发全景视频播放器的现实方法

业余弄弄three.js。想用three.js实现播放全景视频。研究了一段。搜索很多资料。感觉这一遍很棒。搜藏分享下。

原理:将video标签拉伸显示在three.js场景的一个球模型上,用相机在中间播放渲染。

基础:基于three.js官方案例中的全景视频播放(three.js webgl - equirectangular video panorama)

操作过程:对官方demo进行视频播放/暂停、视频进度条、音频控制、全屏等功能进行添加。

 

视频播放/暂停

function stop() {
                video.pause();
            }
function start() {
                video.play();
            }

视频进度条

    

       样式

标题

       作用:控制视频的播放点,实时显示视频播放位置

     html:

<div class="coll">
            <span name="progress">
                <b></b>
                <b></b>
                <b></b>
            </span>
</div>

    css:

.coll{position: absolute;bottom: 20px;left: 20px;width: 52%;}
    .coll span{display: block;height: 4px;width: 52%;margin-left: 2%;background-color: #505050;border-radius: 4px;margin-top: 11px;float:left;}
    .coll span b:nth-child(1){z-index:1;float:left;position:relative;width: 0%;background-color: #b4b4b4;display: block;height: 100%;border-radius: 4px;}
    .coll span b:nth-child(2){z-index:2;position:relative;float: left;width: 8px;height: 8px;background-color: white;border-radius: 8px;margin-top: -2px;margin-left: -8px;}
    .coll span b:nth-child(3){position: relative;background-color: white;display: block;height: 4px;border-radius: 4px;}

js:

var initProgressBar = function(){        //进度条相关操作
        var main_div = $(".coll");
        var timeDrag = false;   /* Drag status */
        $("span[name='progress']",main_div).mousedown(function(e) {     //进度条的按下操作
            timeDrag = true;
            updatebar(e.pageX);
        });
        $(document).mouseup(function(e) {               //松开
            if(timeDrag) {
                timeDrag = false;
                updatebar(e.pageX);
            }
        });
        $(document).mousemove(function(e) {  //鼠标移动事件
            if(timeDrag) {
                updatebar(e.pageX);
            }
        });


        var updatebar = function(x) {  //更新时间与播放条进度
            var progress = $("span[name='progress']",main_div);
            var maxduration = video.duration; //Video duraiton 返回视频长度
            var position = x - progress.offset().left; //Click pos
            var percentage = 100 * position / progress.width();

            if(percentage > 100) {
                percentage = 100;
            }
            if(percentage < 0) {
                percentage = 0;
            }
            //   更新进度条和视频时间
            $("span b:eq(0)",main_div).css('width', percentage+'%');
            video.currentTime = maxduration * percentage / 100;

        };

    };

    var initVideo = function(player){
        var main_div = $(".coll");

        video.ontimeupdate= function() {           //实时更新播放进度条和时间
            var currentPos = video.currentTime; //Get currenttime    //当前时间
            var maxduration = video.duration; //Get video duration   //总时间
            var percentage = 100 * currentPos / maxduration; //算出进度条此时的百分比
            $("span b:eq(0)",main_div).css("width",percentage+"%");
        };
        initProgressBar();
    };

使用注意事项:

  1. 1.$("span[name='progress']",main_div) 中为父节点main_div中找子节点 span[name='progress'],同时也限制方法的作用位置
  2. 2.video.οntimeupdate= function()   为video对象的方法,作用为实时返回视频对象当前的播放位置等参数。
  3. 3.该视频进度条的控制在tomcat中可正常使用,实测webstrom编辑打开时,火狐可正常使用,谷歌、搜狗进度条点击后视频播放位置置0。

音频控制

 音频控制同样使用视频控制相同的进度条,主要方法在与,音频的属性 video.volume,该属性值范围为0~1。通过进度条控制该属性大小即可。

全屏

    div的全屏与退出全屏:

                作用:将div全屏与退出全屏,一般播放器使用较多。

                html按钮:

<button  onclick="showFull();">
                全屏
            </button>
<button  onclick="delFull();">
                退出全屏
            </button>

                js调用:

function showFull(){
               var full=document.getElementById("container");
               launchIntoFullscreen(full);
            }

function delFull() {
                exitFullscreen();
            }

               全屏方法封装:

 function launchIntoFullscreen(element) {
                if(element.requestFullscreen){
                    element.requestFullscreen();
                }
                else if(element.mozRequestFullScreen) {
                    element.mozRequestFullScreen();
                }
                else if(element.webkitRequestFullscreen) {
                    element.webkitRequestFullscreen();
                }
                else if(element.msRequestFullscreen) {
                    element.msRequestFullscreen();
                }
            }

               退出全屏方法封装:

function exitFullscreen() {
                if(document.exitFullscreen) {
                    document.exitFullscreen();
                } else if(document.mozCancelFullScreen) {
                    document.mozCancelFullScreen();
                } else if(document.webkitExitFullscreen) {
                    document.webkitExitFullscreen();
                }
            }

总代码:

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>three.js webgl - equirectangular video panorama</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <style>
            body,html{width: 100%;}

            body {background-color: #000000;margin: 0px;overflow: hidden;}
            #info {position: absolute;top: 0px; width: 100%;color: #ffffff;padding: 5px;font-family:Monospace;font-size:13px;font-weight: bold;text-align:center;}
            a {color: #ffffff;}


            /*控制器*/
            .controll{width: 900px;padding: 10px;position: absolute;bottom:10px;left:50%;margin-left: -450px;height: 20px;background: rgba(0,0,0,0.8)}

            /*按钮组*/
            .btns>button{z-index: 100;position:absolute;bottom: 5px;border: 0;background: 0;width: 30px;height: 30px;background-size: 100% 100%;padding: 0}

            /*视频控制条样式*/
            .coll{position: absolute;bottom: 17px;left: 80px;width: 500px;}
            .coll span{display: block;height: 4px;width: 100%;margin-left: 2%;background-color: #505050;border-radius: 4px;margin-top: 11px;float:left;}
            .coll span b:nth-child(1){z-index:1;float:left;position:relative;width: 0%;background-color: #b4b4b4;display: block;height: 100%;border-radius: 4px;}
            .coll span b:nth-child(2){z-index:2;position:relative;float: left;width: 8px;height: 8px;background-color: white;border-radius: 8px;margin-top: -2px;margin-left: -8px;}
            .coll span b:nth-child(3){position: relative;background-color: white;display: block;height: 4px;border-radius: 4px;}
            /*音频控制条样式*/
            .voicecoll{position: absolute;bottom: 17px;left:680px;width:150px;}
            .voicecoll span{display: block;height: 4px;width: 100%;margin-left: 2%;background-color: #505050;border-radius: 4px;margin-top: 11px;float:left;}
            .voicecoll span b:nth-child(1){z-index:1;float:left;position:relative;width: 0%;background-color: #b4b4b4;display: block;height: 100%;border-radius: 4px;}
            .voicecoll span b:nth-child(2){z-index:2;position:relative;float: left;width: 8px;height: 8px;background-color: white;border-radius: 8px;margin-top: -2px;margin-left: -8px;}
            .voicecoll span b:nth-child(3){position: relative;background-color: white;display: block;height: 4px;border-radius: 4px;}


        </style>
    </head>
    <body>
        <script src="jquery-3.1.0.min.js"></script>
        <div id="container">
            <div class="controll">
                <div class="btns">
                    <!--<button style="right: 20px;" onclick="stop()">
                        暂停
                    </button>-->
                    <button id="video_start_btn" style="left: 30px;background-image: url('img/stop.png')" onclick="start()">

                    </button>

                    <div class="coll">
                        <span name="progress">
                            <b></b>
                            <b></b>
                            <b></b>
                        </span>
                    </div>

                    <button id="video_mutedoff_btn" style="left:620px;background-image: url('img/voice.png')" onclick="mutedoff();">

                    </button>

                    <div class="voicecoll">
                        <span name="vprogress">
                            <b></b>
                            <b></b>
                            <b></b>
                        </span>
                    </div>

                    <!--全屏-->
                    <button id="video_full_btn" style="left: 860px;background-image: url('img/full.png')" onclick="showFull();">

                    </button>
                </div>
            </div>

        </div>
        <video src=""></video>
        <script src="three.js"></script>
        <script>
            /*参数*/
            /*相机、场景、渲染器*/
            var camera, scene, renderer,video,flag,flagvoice;

            var fillbool=false;

            var texture_placeholder,
            isUserInteracting = false,
            onMouseDownMouseX = 0, onMouseDownMouseY = 0,
            lon = 0, onMouseDownLon = 0,
            lat = 0, onMouseDownLat = 0,
            phi = 0, theta = 0,
            distance = 50,
            onPointerDownPointerX = 0,
            onPointerDownPointerY = 0,
            onPointerDownLon = 0,
            onPointerDownLat = 0;

            init();
            animate();

            function init() {

                var container, mesh;
                /*绑定div*/
                container = document.getElementById( 'container' );
                /*创建相机*/
                camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1100 );
                camera.target = new THREE.Vector3( 0, 0, 0 );/*相机目标*/
                /*创建场景*/
                scene = new THREE.Scene();
                /*创建一个球*/
                var geometry = new THREE.SphereBufferGeometry( 500, 60, 40 );
                // invert the geometry on the x-axis so that all of the faces point inward
                geometry.scale( - 1, 1, 1 );/*球的大小*/
                /*创建一个video*/
                video = document.createElement( 'video' );
                video.width = 640;
                video.height = 360;
                video.loop = true;
                video.muted = false;
                video.autoplay=true;
                video.src = 'mv1.mp4';
                video.setAttribute( 'webkit-playsinline', 'webkit-playsinline' );
                video.play();
                /*video.addEventListener("canplay",function() { video.currentTime = 50;});*/

                var texture = new THREE.VideoTexture( video );
                texture.minFilter = THREE.LinearFilter;
                texture.format = THREE.RGBFormat;

                var material   = new THREE.MeshBasicMaterial( { map : texture } );

                mesh = new THREE.Mesh( geometry, material );

                scene.add( mesh );

                renderer = new THREE.WebGLRenderer();
                renderer.setPixelRatio( window.devicePixelRatio );
                renderer.setSize( window.innerWidth, window.innerHeight );
                container.appendChild( renderer.domElement );

                document.addEventListener( 'mousedown', onDocumentMouseDown, false );
                document.addEventListener( 'mousemove', onDocumentMouseMove, false );
                document.addEventListener( 'mouseup', onDocumentMouseUp, false );
                document.addEventListener( 'wheel', onDocumentMouseWheel, false );

                //

                window.addEventListener( 'resize', onWindowResize, false );

            }

            function onWindowResize() {

                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();

                renderer.setSize( window.innerWidth, window.innerHeight );

            }

            function onDocumentMouseDown( event ) {

                event.preventDefault();

                isUserInteracting = true;

                onPointerDownPointerX = event.clientX;
                onPointerDownPointerY = event.clientY;

                onPointerDownLon = lon;
                onPointerDownLat = lat;

            }

            function onDocumentMouseMove( event ) {

                if ( isUserInteracting === true ) {

                    lon = ( onPointerDownPointerX - event.clientX ) * 0.1 + onPointerDownLon;
                    lat = ( event.clientY - onPointerDownPointerY ) * 0.1 + onPointerDownLat;

                }

            }

            function onDocumentMouseUp( event ) {

                isUserInteracting = false;

            }

            function onDocumentMouseWheel( event ) {

                distance += event.deltaY * 0.05;

                distance = THREE.Math.clamp( distance, 1, 50 );

            }

            function animate() {

                requestAnimationFrame( animate );
                update();

            }

            function update() {

                lat = Math.max( - 85, Math.min( 85, lat ) );
                phi = THREE.Math.degToRad( 90 - lat );
                theta = THREE.Math.degToRad( lon );

                camera.position.x = distance * Math.sin( phi ) * Math.cos( theta );
                camera.position.y = distance * Math.cos( phi );
                camera.position.z = distance * Math.sin( phi ) * Math.sin( theta );

                camera.lookAt( camera.target );

                renderer.render( scene, camera );

            }
            /*开始/暂停*/
            function start() {
                if(video.paused==false){
                    video.pause();
                    $("#video_start_btn").css("background-image"," url('img/start.png')")
                }else{
                    video.play();
                    $("#video_start_btn").css("background-image"," url('img/stop.png')")
                }
            }
            function mutedoff(){
                if(video.muted==true){
                    video.muted=false;
                    $("#video_mutedoff_btn").css("background-image"," url('img/voice.png')")
                }else{
                    video.muted=true;
                    $("#video_mutedoff_btn").css("background-image"," url('img/voicess.png')")
                }

            }

           function showFull(){
               var full=document.getElementById("container");
               if(fillbool==false){
                   launchIntoFullscreen(full);
                   fillbool=true;
                   $("#video_full_btn").css("background-image"," url('img/fullss.png')")
               }else{
                   exitFullscreen();
                   fillbool=false;
                   $("#video_full_btn").css("background-image"," url('img/full.png')")
               }
            }


            function launchIntoFullscreen(element) {
                if(element.requestFullscreen){
                    element.requestFullscreen();
                }
                else if(element.mozRequestFullScreen) {
                    element.mozRequestFullScreen();
                }
                else if(element.webkitRequestFullscreen) {
                    element.webkitRequestFullscreen();
                }
                else if(element.msRequestFullscreen) {
                    element.msRequestFullscreen();
                }
            }

            function exitFullscreen() {
                if(document.exitFullscreen) {
                    document.exitFullscreen();
                } else if(document.mozCancelFullScreen) {
                    document.mozCancelFullScreen();
                } else if(document.webkitExitFullscreen) {
                    document.webkitExitFullscreen();
                }
            }


            //视频进度条相关操作
            var initProgressBar = function(){
                var main_div = $(".coll");
                var timeDrag = false;   /* Drag status */
                $("span[name='progress']",main_div).mousedown(function(e) {     //进度条的按下操作
                    timeDrag = true;

                    updatebar(e.pageX);
                    e.stopPropagation();
                });
                $(document).mouseup(function(e) {               //松开
                    if(timeDrag) {
                        timeDrag = false;
                        updatebar(e.pageX);
                        e.stopPropagation();
                    }
                });
                $(document).mousemove(function(e) {  //鼠标移动事件
                    if(timeDrag) {

                        updatebar(e.pageX);
                        e.stopPropagation();
                    }
                });

                //update Progress Bar control
                var updatebar = function(x) {  //更新时间与播放条进度
                    var progress = $("span[name='progress']",main_div);
                    var maxduration = video.duration; //Video duraiton 返回视频长度
                    /*alert(progress.offset().left)*/
                    var position = x - progress.offset().left; //Click pos
                    var percentage = 100 * position / progress.width();
                    /*alert(percentage)*/
                    //Check within range    检查范围内
                    if(percentage > 100) {
                        percentage = 100;
                    }
                    if(percentage < 0) {
                        percentage = 0;
                    }
                    //Update progress bar and video currenttime   更新进度条和视频时间
                    $("span b:eq(0)",main_div).css('width', percentage+'%');
                    video.currentTime = maxduration * percentage / 100;

                };

            };

            //声音进度条相关操作
            var initvoiceBar = function(){
                var main_voicediv = $(".voicecoll");
                var voicetimeDrag = false;   /* Drag status */
                $("span[name='vprogress']",main_voicediv).mousedown(function(e) {     //进度条的按下操作
                    voicetimeDrag = true;
                    voiceupdatebar(e.pageX);
                    e.stopPropagation();
                });
                $(document).mouseup(function(e) {               //松开
                    if(voicetimeDrag) {
                        voicetimeDrag = false;
                        voiceupdatebar(e.pageX);
                        e.stopPropagation();
                    }
                });
                $(document).mousemove(function(e) {  //鼠标移动事件
                    if(voicetimeDrag) {
                        voiceupdatebar(e.pageX);
                        e.stopPropagation();
                    }
                });

                //update Progress Bar control
                var voiceupdatebar = function(x) {  //更新时间与播放条进度
                    var progress = $("span[name='vprogress']",main_voicediv);
                    var maxduration = 1; //Video duraiton 返回视频长度
                    /*alert(progress.offset().left)*/
                    var position = x - progress.offset().left; //Click pos
                    var percentage = 100 * position / progress.width();
                    /*alert(percentage)*/
                    //Check within range    检查范围内
                    if(percentage > 100) {
                        percentage = 100;
                    }
                    if(percentage < 0) {
                        percentage = 0;
                    }
                    //Update progress bar and video currenttime   更新进度条和视频时间
                    $("span b:eq(0)",main_voicediv).css('width', percentage+'%');
                    video.volume = maxduration * percentage / 100;

                };
            };

            var initVideo = function(player){
                flag = true;
                flagvoice = true;

                var main_div = $(".coll");
                var main_voicediv = $(".voicecoll");

                //实时更新播放进度条和时间
                video.ontimeupdate= function() {
                    //视频进度条控制
                    var currentPos = video.currentTime; //Get currenttime    //当前时间
                    var maxduration = video.duration; //Get video duration   //总时间
                    var percentage = 100 * currentPos / maxduration; //in %
                    $("span b:eq(0)",main_div).css("width",percentage+"%");
                   //音频进度条控制
                    var currentPosvoice = video.volume; //Get currenttime    //当前时间
                    var maxdurationvoice = 1; //Get video duration   //总时间
                    var percentagevoice = 100 * currentPosvoice / maxdurationvoice; //in %
                    $("span b:eq(0)",main_voicediv).css("width",percentagevoice+"%");
                };
                initProgressBar();
                initvoiceBar();
            };

            initVideo();

        </script>
    </body>
</html>

图片文件:(图片有6张,为png白色图标)

 

样式:

three.js版本:r89

 

参考自:https://www.cnblogs.com/s313139232/p/8371295.html

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值