业余弄弄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 posvar 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 inwardgeometry.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 controlvar 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 posvar 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 controlvar 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 posvar 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

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

  1. android vr播放器 开发,Android应用开发之Android VR Player(全景视频播放器)- ExoPlayer播放器MPEG-DASH视频播放...

    本文将带你了解Android应用开发之Android VR Player(全景视频播放器)- ExoPlayer播放器MPEG-DASH视频播放,希望本文对大家学Android有所帮助. Androi ...

  2. 全景视频播放器代码分析

    全景视频播放器代码分析 一.前期准备 (1)FFmpeg新旧接口对照使用一览 (2)libswscale图片像素数据处理类库 (3)OpenGL相关记录 (4)列队与线程 二.代码分析 来总结一下最近 ...

  3. Android VR Player(全景视频播放器) [7]:视频列表的实现-网络视频

    Android VR Player(全景视频播放器) [7]:视频列表的实现-网络视频 前期准备 在之前的博文,Android VR Player(全景视频播放器) [6]:视频列表的实现-本地视频 ...

  4. Android VR Player(全景视频播放器) [6]:视频列表的实现-本地视频

    Android VR Player(全景视频播放器) [6]:视频列表的实现-本地视频 (本篇博客参考<Android第一行代码(第二版)>中关于RecyclerView的部分) 列表的实 ...

  5. 基于Google的Android平台上GVR 3D全景视频播放器(支持本地文件和视频流传输)

    基于GVR(Google VR)安卓平台下的 3D全景视频播放器 Google GVR GVR简介 示例应用 源码实现 GVR关键的api调用 Gradle配置 效果图 布局 m3u8和hls协议(自 ...

  6. Android开发之视频播放器

    Android开发之视频播放器 一.效果图 二.build.gradle中导入依赖 三.主布局文件(activity_video) 四.布局文件(video_item) 五.布局文件(activity ...

  7. Android 全景视频播放器(VR视频播放器探索二)

        上次随便写着玩的  http://blog.csdn.net/ai_yong_jie/article/details/51159367   Android 全景视频播放器(VR视频播放器探索一 ...

  8. 基于QtAv及ffmpeg开发的视频播放器

    基于QtAv及ffmpeg开发的视频播放器 主要功能: 本地媒体文件播放,支持切换上一个下一个文件,暂停/恢复,快放/慢放,音量控制 全屏/取消全屏 播放列表,列表缩略图 播放进度,进度条展示缩略图 ...

  9. 基于MATLAB开发的视频播放器

    目录 1.算法概述 2.仿真效果 3.MATLAB仿真源码 1.算法概述 基于MATLAB开发的视频播放器 2.仿真效果 matlab2022a仿真结果如下:

最新文章

  1. Linux驱动修炼之道-SPI驱动框架源码分析(上)
  2. 我的学习笔记_Windows_HOOK编程 2009-12-03 11:19
  3. FastReport4.6程序员手册_翻译 转
  4. 关于HTTPS的七个误解
  5. LeetCode 501. 二叉搜索树中的众数(中序遍历)
  6. 【python】日志模块以及日志组件使用
  7. SAP License:ERP项目经理需求调研的惨痛经历
  8. [Python] 维度交换函数:transpose(m,n,r)和permute(m,n,r)
  9. .Net Core - 使用Supervisor进行托管部署
  10. node + node-webkit实现电脑文件信息扫描小插件
  11. 怎么在mac上更改移动硬盘的权限
  12. Stolz定理及其在求极限上的应用
  13. 微雪电子扫码模块使用
  14. 前端学习——Js(JavaScript)入门
  15. 数学建模更新7(ARCH和GARCH模型)
  16. 2019备考[嵌入式系统设计师]之基础知识
  17. vscode配置prettier格式化工具
  18. 在IDEA里gradle配置和使用
  19. PCB板HDI板几阶是什么意思
  20. Linux下Socket编程之TCP原理

热门文章

  1. 选择 FreeBSD 而不是 Linux 的技术性原因
  2. 基金从业-(1、2)
  3. 蓝桥杯——单片机赛道
  4. create与oncreate的区别
  5. ipad9.7 能搭建php,9.7寸ipad pro能用pencil吗?ipad pro全面支持Apple Pencil
  6. KVM虚拟化,超详细
  7. 利用百度poi计算城市能级及评价街道范围便利度、生活宜居情况等
  8. 《水经注地图服务》数据源说明
  9. 银联商务MISPOS接口开发demo 需要调用POSINF.DLL
  10. 你应该知道的linux命令 — lsof