As we all know, there are many different ways to achieve panorama. Today we mainly introduce the use of three.js to achieve the effect. Three.js is a three-dimensional engine running based on the native WebGL package. Among all WebGL engines, Three.js is the one with the most domestic literature and the most used The most extensive 3D engine.
1: Initialization settings
All initialization operations are implemented in mounted. Why not use created here? Because we need to operate dom,
And created cannot obtain dom.
? //Create scene const scene = new THREE.Scene() //Initialize scene var ambient = new THREE.AmbientLight(0xfffffff, 2) //Add light source color and light intensity scene.add(ambient) //Add light source to the scene
First of all, for the initial scene, a light source must be added. However, there are also some special materials that can emit light without adding a light source. Of course, this is a rare situation. No light source will cause a black screen.
? //Create camera var width = 800 //Window width var height = 800 //Window height const camera = new THREE.PerspectiveCamera(90, width / height, 1, 1000) //Use perspective camera camera.position.set(30, 0, 10) //Set camera position camera.lookAt(new THREE.Vector3(30, 0, 0)) // Camera looking direction ?
Here we use a perspective camera, which is the closest to a natural view and conforms to the rules of near and far.
// Create renderer width = window.innerWidth //Window width window.innerWidth browser window visual area width (excluding browser console, menu bar, toolbar) including scroll bar height = window.innerHeight //Window height window.innerHeight const renderer = new THREE.WebGLRenderer() //Create renderer renderer.setSize(width, height) //Set the renderer size renderer.setPixelRatio(window.devicePixelRatio) this.$refs.container.appendChild(renderer.domElement) //Pass this.$ref
The renderer is equivalent to the canvas. All display effects need to be displayed on the canvas. We need to add a box with a ref of container in the html. Of course, you can also name it yourself.
// Create controller const controls = new OrbitControls(camera, renderer.domElement) controls.enableDamping = true // zoom limit controls.maxDistance = 12 controls.target.set(30, 0, 0) ?
Here we need to impose a zoom limit on the controller, because the principle of panorama is to create a cube or a sphere, and then let the perspective be inside the box, so we cannot expose the outer box to the user.
2: Add model
Next is the most critical step. We need to create a sphere or cube. Different materials require different panoramas. A sphere only requires a complete panoramic photo to achieve a panoramic view. The disadvantage is that it may be possible from certain viewing angles. The effect is not very good, and the cube requires six photos in different directions. This is too difficult for beginners and often cannot achieve seamless fit. However, it avoids the shortcomings of the sphere and the display effect is very good.
// Add a sphere const geometry = new THREE.SphereGeometry(130, 256, 256) var textureLoader = new THREE.TextureLoader() //Create texture map var img = textureLoader.load(require('../../../public/image/vrTest3.jpg')) const material = new THREE.MeshLambertMaterial({ map: img, //Set the color map attribute value side: THREE.DoubleSide //Double-sided rendering }) const cube = new THREE.Mesh(geometry, material) scene.add(cube)
Finally, the rendering scene
// Render scene const animate = function () { requestAnimationFrame(animate) renderer.render(scene, camera) } animate()
You can also add animation here to make the scene move by itself.
After completing the appeal, you should have completed a most basic VR panorama.
Here I add a 3D model in it, and you can also expand it based on your own business.
3: Scene roaming
Scene roaming is divided into same scene roaming and different scene roaming
1: Roaming in different scenes
Since they are different scenes, one scene is an object. Here we need to create multiple spheres in a loop. Remember that scenes cannot overlap. The principle is mainly to change the position of the camera and the position of the control center when switching, because we are At the beginning, there were zoom restrictions so that users could not find them. During testing, the restrictions can be commented out for debugging.
<template> <div class="home"> <div ref="container"></div> <!-- Scene switching point --> <div class="switch"> <span class="buttons" v-for="(room, index) in rooms" :key="index" @click="handleSwitchButtonClick(room.key)" v-show="room.key !== currentRoom" > <b class="text">{<!-- -->{ room.name }}</b> <i class="icon"></i> </span> </div> </div> </template>
Parallel to the canvas, fix the switching box to the right side of the panorama. The index of the box needs to be greater than the canvas.
For the creation and addition of multiple scenes, you can refer to the above code and create them in a loop. I will not elaborate here.
// Click to switch scenes async handleSwitchButtonClick(key) { if (key == 'internet-hall') { this.cameras.position.set(280, 0, 10) this.cameras.lookAt(new THREE.Vector3(280, 0, 0)) this.controles.target.set(280, 0, 0) this.currentRoom = 'internet-hall' } else if (key == 'insect-hall') { this.cameras.position.set(0, 0, 10) this.cameras.lookAt(new THREE.Vector3(0, 0, 0)) this.controles.target.set(0, 0, 0) this.currentRoom = 'insect-hall' } else if (key == 'agriculture-hall') { this.cameras.position.set(580, 0, 10) this.cameras.lookAt(new THREE.Vector3(580, 0, 0)) this.controles.target.set(580, 0, 0) this.currentRoom = 'agriculture-hall' } }
You can use my method to switch scenes when there are not many scenes. Of course, you can also put the data in data and use loops to switch different scenes.
2: Roaming in the same scene
For roaming in the same scene, I used mobile to achieve
window.addEventListener( 'keydown', (e) => { var ev = e || window.event switch (ev.keyCode) { case 87: camera.position.x + = 2 controls.target.x + = 2 break case 83: camera.position.x -= 2 controls.target.x -= 2 break case 65: camera.position.z -= 2 controls.target.z -= 2 break case 68: camera.position.z + = 2 controls.target.z + = 2 break default: break } }, false )
If you have any questions, please leave them in the comments.