three.js全景漫游实践

Hello 小伙伴们,如果觉得本文还不错,记得给个 star , 小伙伴们的 star 是我持续更新的动力!GitHub 地址

简介

全景图分两种
  1. 由六张正方形图片组成的SkyBox
  2. 一整张的宽高比为2比1的全景图片。

今天我就实现一整张全景图的案例。

思路

我们超赞的设计师画的中秋全景图(利用透视网格辅助PS绘制)


创建一个球体网格,对网格进行x轴反转,使所有的面点向内

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);
}

简单案例代码

DEMO: http://songdy.github.io/panorama/simple-index.html

这就简单实现了一个全景图,贴出以上的全部代码

<!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: http://songdy.github.io/panorama/camera-index.html

辅助理解DEMO: http://songdy.github.io/panorama/camera-help.html

把简单版加入进场效果

<!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 进行全景漫游,你可以按照以下步骤进行操作: 1. 首先,确保你已经在网页中引入了 three.js 库文件。你可以通过在 HTML 文件中添加以下代码来引入: ```html <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script> ``` 2. 创建一个场景(Scene)和一个相机(Camera)。你可以使用透视相机(PerspectiveCamera)来模拟真实的视角。 ```javascript var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); ``` 3. 创建一个渲染器(Renderer),并将其添加到页面中的某个容器中。 ```javascript var renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); ``` 4. 创建一个全景球体(SphereGeometry),并将其作为场景的一个子对象。 ```javascript var geometry = new THREE.SphereGeometry(500, 60, 40); geometry.scale(-1, 1, 1); // 反转球体的法线,使其内部可见 var texture = new THREE.TextureLoader().load('your-panorama-image.jpg'); var material = new THREE.MeshBasicMaterial({ map: texture }); var sphere = new THREE.Mesh(geometry, material); scene.add(sphere); ``` 5. 设置相机的位置和目标点。 ```javascript camera.position.set(0, 0, 0); camera.lookAt(scene.position); ``` 6. 添加交互控制(Optional)。你可以使用一些库,如 OrbitControls,来实现用户与全景的交互,例如通过鼠标或触摸移动视角。 ```javascript var controls = new THREE.OrbitControls(camera, renderer.domElement); ``` 7. 渲染场景。 ```javascript function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); } animate(); ``` 通过按照以上步骤进行操作,你就可以在网页中实现基本的 three.js 全景漫游效果了。当然,你还可以根据自己的需求进一步定制和优化。希望对你有帮助!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值