Hello 小伙伴们,若是以为本文还不错,记得给个 star , 小伙伴们的 star 是我持续更新的动力!GitHub 地址javascript
今天我就实现一整张全景图的案例。css
咱们超赞的设计师画的中秋全景图(利用透视网格辅助PS绘制)html
let geometry = new THREE.SphereGeometry( 500, 60, 40 );
geometry.scale( -1, 1, 1 );
复制代码
使用上面的全景贴图建立基础材质java
let material = new THREE.MeshBasicMaterial({
map: new THREE.TextureLoader().load( 'panorama.jpg'),
depthTest: false//此参数控制是否使用像素深度来计算新像素的值
});
let mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
复制代码
把相机设置为球的中心点git
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);
复制代码
陀螺仪相机控制器,实现移动端陀螺仪控制相机github
let controls = new THREE.DeviceOrientationControls( camera );
复制代码
此时尚未动画效果,还须要增长一个实时更新渲染动画bash
function animate() {
render();
requestAnimationFrame(animate);
}
function render() {
//更新控制器
controls.update();
camera.lookAt( camera.target );
renderer.render(scene, camera);
}
复制代码
DEMO: songdy.github.io/panorama/si…app
这就简单实现了一个全景图,贴出以上的所有代码dom
<!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>
复制代码