three.js全景漫游实践
Hello 小伙伴们,如果觉得本文还不错,记得给个 star , 小伙伴们的 star 是我持续更新的动力!GitHub 地址
简介
全景图分两种
- 由六张正方形图片组成的SkyBox
- 一整张的宽高比为2比1的全景图片。
今天我就实现一整张全景图的案例。
思路
我们超赞的设计师画的中秋全景图(利用透视网格辅助PS绘制)
let geometry = new THREE.SphereGeometry( 500, 60, 40 );
geometry.scale( -1, 1, 1 );
使用上面的全景贴图创建基础材质
let material = new THREE.MeshBasicMaterial({
map: new THREE.TextureLoader().load( 'panorama.jpg'),
depthTest: false//此参数控制是否使用像素深度来计算新像素的值
});
let mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
把相机设置为球的中心点
let camera = new THREE.PerspectiveCamera( 100, window.innerWidth / window.innerHeight, 1, 1100 );
camera.target = new THREE.Vector3( 0, 0, 0 );
camera.position.set(0, 0, 0);
陀螺仪相机控制器,实现移动端陀螺仪控制相机
let controls = new THREE.DeviceOrientationControls( camera );
此时还没有动画效果,还需要增加一个实时更新渲染动画
function animate() {
render();
requestAnimationFrame(animate);
}
function render() {
//更新控制器
controls.update();
camera.lookAt( camera.target );
renderer.render(scene, camera);
}
简单案例代码
这就简单实现了一个全景图,贴出以上的全部代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>简单的全景图</title>
<link rel="stylesheet" type="text/css" href="./css/simple-index.css">
</head>
<body>
<div id="container"></div>
<script type="text/javascript" src="./js/three.min.js"></script>
<script type="text/javascript" src="./js/DeviceOrientationControls.js"></script>
<script type="text/javascript">
class panorama{
constructor () {
this.scene = new THREE.Scene();
this.initCamera();
this.initMesh();
this.initRenderer();
this.animate();
} initCamera () {
let camera = this.camera = new THREE.PerspectiveCamera( 100, window.innerWidth / window.innerHeight, 1, 1100 );
camera.position.set(0, 0, 0); this.controls = new THREE.DeviceOrientationControls( camera );
this.controls.connect();
}
initMesh () {
let geometry = new THREE.SphereGeometry( 500, 60, 40 );
geometry.scale( -1, 1, 1 );
geometry.rotateY(-Math.PI / 2) let material = new THREE.MeshBasicMaterial({
map: new THREE.TextureLoader().load('./textures/SphericalMap.jpg')
}); let mesh = new THREE.Mesh( geometry, material );
this.scene.add( mesh );
}
initRenderer () {
let container = document.getElementById( 'container' );
let renderer = this.renderer = new THREE.WebGLRenderer({ logarithmicDepthBuffer: true });
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.sortObjects = false;
renderer.autoClear = false;
container.appendChild( renderer.domElement );
}
animate() {
this.render();
requestAnimationFrame( ()=>{this.animate()});
}
render() {
//更新控制器
this.controls.update();
this.renderer.render(this.scene, this.camera);
}
}
new panorama();
</script>
</body>
</html>
相机
直接上图,常规的全景漫游的进场效果:
左边是效果,右边是相机辅助效果。
思路分析
相机起始在球体接近顶部位置,从上往下看
let camera = new THREE.PerspectiveCamera( 150, window.innerWidth / window.innerHeight, 1, 2000 );
camera.position.set(0, 450, 0);//相机定位在y轴450
camera.target = new THREE.Vector3( 0, -500, 0 );//设置目标点
camera.lookAt( camera.target );//看向y轴负方向
相机有上往下移动到求的中心点(0, 0, 0)。同时,相机目标点从底部(0, -500, 0)转到背面(0, 0, -500)。把fov从150调整为100,效果更赞了。
new TWEEN.Tween( { y : 450, lat : 0, fov : 150 } )
.to( { y : 0, lat : 90, fov : 100 }, 2500 )
.onUpdate(function() {
camera.position.y = this.y;
let phi = THREE.Math.degToRad( this.lat );
camera.target.y = -500 * Math.cos( phi );
camera.target.z = -500 * Math.sin( phi );
camera.fov = this.fov;
camera.updateProjectionMatrix();
})
进场案例代码
DEMO: songdy.github.io/panorama/ca…
辅助理解DEMO: songdy.github.io/panorama/ca…
把简单版加入进场效果
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>玩转相机</title>
<link rel="stylesheet" type="text/css" href="./css/simple-index.css">
</head>
<body>
<div id="container"></div>
<script type="text/javascript" src="./js/three.min.js"></script>
<script type="text/javascript" src="./js/DeviceOrientationControls.js"></script>
<script type="text/javascript" src="./js/Tween.js"></script>
<script type="text/javascript">
class panorama{
constructor () {
this.SCREEN_WIDTH = window.innerWidth;
this.SCREEN_HEIGHT = window.innerHeight;
this.scene = new THREE.Scene();
this.initCamera();
this.initMesh();
this.initRenderer();
this.animate();
this.start();
}
initCamera () {
let aspect = this.SCREEN_WIDTH / this.SCREEN_HEIGHT;
this.camera = new THREE.PerspectiveCamera( 150, 0.5 * aspect, 1, 2000 );
this.camera.position.set(0, 450, 0);
this.camera.target = new THREE.Vector3( 0, -1, 0 ); }
initMesh () {
let geometry = new THREE.SphereGeometry( 500, 60, 40 );
geometry.scale( -1, 1, 1 );
geometry.rotateY(-Math.PI / 2)
let material = new THREE.MeshBasicMaterial({
map: new THREE.TextureLoader().load('./textures/SphericalMap.jpg')
});
this.mesh = new THREE.Mesh( geometry, material );
this.scene.add( this.mesh );
}
initRenderer () {
let container = document.getElementById( 'container' );
let renderer = this.renderer = new THREE.WebGLRenderer({ logarithmicDepthBuffer: true });
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.sortObjects = false;
renderer.autoClear = false;
container.appendChild( renderer.domElement );
}
start () {
let {camera} = this;
new TWEEN.Tween( { lat : 0, y : camera.position.y, fov : camera.fov } )
.to( { lat: 90, y : 0, fov : 100 }, 2500 )
.delay(1000)
.easing(TWEEN.Easing.Cubic.InOut)
.repeat(Infinity)
.onUpdate(function() {
let phi = THREE.Math.degToRad( this.lat );
camera.target.y = -500 * Math.cos( phi );
camera.target.z = -500 * Math.sin( phi );
camera.position.y = this.y;
camera.fov = this.fov;
camera.updateProjectionMatrix();
})
.start()
}
animate() {
this.render();
requestAnimationFrame( ()=>{this.animate()});
}
render() {
TWEEN.update();
this.camera.lookAt( this.camera.target );
this.renderer.clear();
this.renderer.render( this.scene, this.camera );
}
}
new panorama();
</script>
</body>
</html>
three.js全景漫游实践的更多相关文章
- <Three.js>(第三节)全景漫游
一.实验内容 通过上次实验,了解了Three.js创建场景的基本步骤.这一节,我们将通过Three.js实现全景漫游功能.如下图: 全景图是获取一个3D场景中的不同角度的图片,然后通过拼接.融合实现3 ...
- 打造H5里的“3D全景漫游”秘籍
近来风生水起的VR虚拟现实技术,抽空想起年初完成的“星球计划”项目,总结篇文章与各位分享一下制作基于Html5的3D全景漫游秘籍. QQ物联与深圳市天文台合作,在手Q“发现新设备”-“公共设备”里,连 ...
- 打造自己的3D全景漫游
three.js 示例: 打造H5里的"3D全景漫游"秘籍 - 腾讯ISUX QQ物联星球计划 通过pano2vr直接将鱼眼全景图生成立体空间的六个面:也可通过Photos ...
- JS编程最佳实践
最近花了一周时间把<编写可维护的js> 阅读了一遍, 现将全书提到的JS编程最佳实践总结如下, 已追来者! 1.return 之后不可直接换行, 否则会导致ASI(自动分号插入机制)会在r ...
- Atitit.angular.js 使用最佳实践 原理与常见问题解决与列表显示案例 attilax总结
Atitit.angular.js 使用最佳实践 原理与常见问题解决与列表显示案例 attilax总结 1. 本文范围 1 2. Angular的优点 1 2.1. 双向数据绑定 1 2.2. dsl ...
- Cookie和Session在Node.JS中的实践(三)
Cookie和Session在Node.JS中的实践(三) 前面作者写的COOKIE篇.SESSION篇,算是已经比较详细的说明了两者间的区别.机制.联系了.阅读时间可能稍长,因为作者本身作图也做了不 ...
- Cookie和Session在Node.JS中的实践(二)
Cookie和Session在Node.JS中的实践(二) cookie篇在作者的上一篇文章Cookie和Session在Node.JS中的实践(一)已经是写得算是比较详细了,有兴趣可以翻看,这篇是s ...
- 《Vue.js 2.x实践指南》 已出版
<Vue.js 2.x实践指南>其实在一年前就已经完稿了,只是由于疫情的缘故耽搁了很久才下厂印刷.阅读本书需要具备HTML.CSS和JS基础,本书针对的用户群体主要是:想要快速学习vue技 ...
- 轩辕展览-VR虚拟展厅设计如何实现全景漫游功能
什么是在线3d漫游?如何在VR虚拟展厅设计之中实现3d漫游功能?让我们来分享3dVR虚拟展厅的在线漫游. 实际上,在线3d漫游就是通过3d仿真场景,使用鼠标和键盘在虚拟空间之中自由漫游,它可以从高空俯 ...
随机推荐
- git20181122
git 在线编辑器 http://www.mdeditor.com/git add commit diff log status 代码撤消 # git https://github.com/gyz41 ...
- windows10下面部署nginx(解决文件名中文乱码问题)
由于开发需要,我们总是需要先在windows环境下面部署项目进行测试,通过之后才会移植到linux系统进行测试部署. 本篇文章会介绍一下windows终端下面部署nginx WEB服务的一些步骤流程, ...
- 分支界定( BRANCH-AND-BOUND)
分支定界法(branch and bound)是一种求解整数规划问题的最常用算法.这种方法不但可以求解纯整数规划,还可以求解混合整数规划问题.分支定界法是一种搜索与迭代的方法,选择不同的分支变量和子问 ...
- 闲谈REST API
REST 表述性状态传递(英文:Representational State Transfer,简称REST). 资源: 资源由URI(统一资源定位符)的来指定. 通过资源的表现形式来操作资源 对资源 ...
- 关于<超文本>定义
百度百科定义: 1, 超文本是用超链接的方法,将各种不同空间的文字信息组织在一起的网状文本.它更是一种用户界面范式,用以显示文本及与文本之间相关的内容.现时超文本普遍以电子文档方式存在,其中的文字包含 ...
- python 在ubuntu下安装pycurl
https://www.linuxidc.com/Linux/2016-05/131574.htm
- Metasploit运行环境内存不要低于2GB
Metasploit运行环境内存不要低于2GB Metasploit启用的时候,会占用大量的内存.如果所在系统剩余内存不足(非磁盘剩余空间),会直接导致运行出错.这种情况特别容易发生在虚拟机Kali ...
- 操作系统PV编程题目总结一
1.今有一个文件F供进程共享,现把这些进程分为A.B两组,规定同组的进程可以同时读文件F:但当有A组(或B组)的进程在读文件F时就不允许B组(或A组)的进程读文件F.试用P.V操作(记录型信号量)来进 ...
- android BLE Peripheral 做外设模拟设备,供ios、android 连接通讯。
为了能让其它设备可以发现其设备,先启动特定广播.看自己需要什么广播格式. 对于广播可见的mac address: 在调用startAdvertising();时,mac address 就会改变. 并 ...
- 学习--->更新集合/内存/深浅拷贝
一.计算机基础 1..软件(应用程序) 2.解释器/编译器 - 解释型语言:将代码每一行传递给计算机一行,常用编程语言python,PHP,Ruby. - 编译型语言:将代码完全执行完后会形成一个文 ...