基于three.js开发全景播放器

基于three.js开发全景播放器

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

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

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

 

视频播放/暂停

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

视频进度条

 参照另一篇博客:视频控制的简易进度条 (地址:http://www.cnblogs.com/s313139232/p/8371407.html)

音频控制

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

全屏

 参照另一篇博客:div的全屏与退出全屏 (地址:http://www.cnblogs.com/s313139232/p/8371548.html)

 

总代码:

<!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>
View Code

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

 

样式:

three.js版本:r89

 

禁止转载。

posted @ 2018-04-19 17:18  莫小龙  阅读(2084)  评论(0编辑  收藏  举报