已被阅读 1042 次 | 文章分类:javascript | 2021-12-03 23:58
全景图,即通过广角的表现手段以及绘画、相片、视频、三维模型等形式,尽可能多表现出周围的环境;
1 效果一
官网实现方式,效果如下
实现该效果需要这样一张图片
全部代码
import * as THREE from 'three'
let scene,camera,gridHelper,axes,renderer;
initScene();
function initScene(){
// ---------------------------------------------------------------------
// 场景和相机
// ---------------------------------------------------------------------
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1000);
// 环境光
var ambientLight = new THREE.AmbientLight("white");
scene.add(ambientLight);
// ---------------------------------------------------------------------
// 渲染器
// ---------------------------------------------------------------------
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
// 添加球体模型
let path="./statics/imgs/texture1.jpg";
const geometry = new THREE.SphereGeometry(500,60,40 );
geometry.scale(-1, 1, 1 ); // 翻转几何体,让所有面指向内心
const texture = new THREE.TextureLoader().load(path);
const material = new THREE.MeshBasicMaterial( { map: texture } );
const mesh = new THREE.Mesh( geometry, material );
scene.add(mesh);
animate();
document.body.style.touchAction = 'none';
document.body.addEventListener('pointerdown', onPointerDown );
document.addEventListener('wheel', onDocumentMouseWheel );
document.addEventListener('dragover', function (event) {
event.preventDefault();
event.dataTransfer.dropEffect = 'copy';
});
document.addEventListener('dragenter', function () {
document.body.style.opacity = 0.5;
});
document.addEventListener('dragleave', function () {
document.body.style.opacity = 1;
});
document.addEventListener('drop', function (event) {
event.preventDefault();
const reader = new FileReader();
reader.addEventListener( 'load', function ( event ) {
material.map.image.src = event.target.result;
material.map.needsUpdate = true;
});
reader.readAsDataURL( event.dataTransfer.files[ 0 ] );
document.body.style.opacity = 1;
});
window.addEventListener('resize', onWindowResize );
}
var isUserInteracting = false,
onPointerDownMouseX = 0,
onPointerDownMouseY = 0,
lon = 0, onPointerDownLon = 0,
lat = 0, onPointerDownLat = 0,
phi = 0, theta = 0;
// 浏览器窗口
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
// 鼠标按下事件
function onPointerDown( event ) {
if ( event.isPrimary === false ) return;
isUserInteracting = true;
onPointerDownMouseX = event.clientX;
onPointerDownMouseY = event.clientY;
onPointerDownLon = lon;
onPointerDownLat = lat;
document.addEventListener( 'pointermove', onPointerMove );
document.addEventListener( 'pointerup', onPointerUp );
}
// 鼠标移动事件
function onPointerMove( event ) {
if ( event.isPrimary === false ) return;
lon = ( onPointerDownMouseX - event.clientX ) * 0.1 + onPointerDownLon;
lat = ( event.clientY - onPointerDownMouseY ) * 0.1 + onPointerDownLat;
}
// 鼠标抬起事件
function onPointerUp() {
if ( event.isPrimary === false ) return;
isUserInteracting = false;
document.removeEventListener( 'pointermove', onPointerMove );
document.removeEventListener( 'pointerup', onPointerUp );
}
// 滚轮滚动事件
function onDocumentMouseWheel( event ) {
const fov = camera.fov + event.deltaY * 0.05;
camera.fov = THREE.MathUtils.clamp( fov, 10, 75 );
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame(animate);
update();
renderer.render(scene, camera);
}
// 自动传动事件
function update() {
if (isUserInteracting === false ) {
lon += 0.1;
}
lat = Math.max(-85, Math.min( 85, lat) );
phi = THREE.MathUtils.degToRad( 90 - lat );
theta = THREE.MathUtils.degToRad( lon );
const x = 500 * Math.sin( phi ) * Math.cos( theta );
const y = 500 * Math.cos( phi );
const z = 500 * Math.sin( phi ) * Math.sin( theta );
camera.lookAt( x, y, z );
}
2 用球体(SphereGeometry)方式实现以上效果
实现原理较为简单,给球体贴图就可以;前提是要制作出如上提供的纹理图片,代码如下
import * as THREE from 'three'
import { OrbitControls } from '../utils/controls/OrbitControls';
let scene,camera,gridHelper,axes,renderer,controls;
// ---------------------------------------------------------------------
// 场景和相机
// ---------------------------------------------------------------------
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(157, 73, 241);
// 环境光
var ambientLight = new THREE.AmbientLight("white");
scene.add(ambientLight);
// ---------------------------------------------------------------------
// 渲染器
// ---------------------------------------------------------------------
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
controls = new OrbitControls( camera, renderer.domElement );
// 添加球体模型
let path="./statics/imgs/texture1.jpg";
// 添加背景模型
let texture = new THREE.TextureLoader().load(path);
let backgroundBall = new THREE.Mesh(
new THREE.SphereGeometry(500, 128, 128),
new THREE.MeshBasicMaterial({
map: texture,
// side:THREE.DoubleSide
})
);
backgroundBall.geometry.scale(-1, 1, 1);
scene.add(backgroundBall);
animate();
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
3 效果二
也是官方提供的demo,效果如下
依赖图片
实现原理:利用BoxGeometry几何体,然后给六个面分别创建贴图材质实现;六个纹理分别从图片中根据宽度读取像素,使用canvas绘制
import * as THREE from 'three'
import { Reflector } from "three/examples/jsm/objects/Reflector.js"
import { OBJLoader } from '../utils/OBJLoader.js';
import { MTLLoader } from '../utils/MTLLoader.js';
import { OrbitControls } from '../utils/controls/OrbitControls';
let scene,camera,gridHelper,axes,renderer,controls;
initScene();
function initScene(){
// ---------------------------------------------------------------------
// 场景和相机
// ---------------------------------------------------------------------
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 90, window.innerWidth / window.innerHeight, 0.1, 100 );
camera.position.z = 0.01;
//光源一定要添加,模型没有光 肯定是黑色
var light = new THREE.DirectionalLight(0xffffff);//光源颜色
light.position.set(2000, 1000, 305);//光源位置
scene.add(light);//光源添加到场景中
//环境光
var ambientLight = new THREE.AmbientLight("white");
scene.add(ambientLight);
// ---------------------------------------------------------------------
// 渲染器
// ---------------------------------------------------------------------
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
controls = new OrbitControls( camera, renderer.domElement );
controls.enableZoom = false;
controls.enablePan = false;
controls.enableDamping = true;
controls.rotateSpeed = - 0.25;
animate();
let path="./statics/imgs/sun_temple_stripe.jpg";
// 创建6个面的纹理
const textures = getTexturesFromAtlasFile(path,6);
const materials = [];
// 创建6个面的材质
for ( let i = 0; i < 6; i++) {
materials.push(new THREE.MeshBasicMaterial({ map:textures[i]}));
}
// 创建mesh
const skyBox = new THREE.Mesh(new THREE.BoxGeometry(1,1,1), materials );
skyBox.geometry.scale(1,1,-1);
scene.add(skyBox);
// 注册浏览器窗口改变事件
window.addEventListener( 'resize', onWindowResize );
}
function getTexturesFromAtlasFile( atlasImgUrl, tilesNum ) {
const textures = [];
for ( let i = 0; i < tilesNum; i ++ ) {
textures[i] = new THREE.Texture();
}
new THREE.ImageLoader().load(atlasImgUrl, (image) => {
let canvas, context;
const tileWidth = image.height;
for ( let i = 0; i < textures.length; i ++ ) {
canvas = document.createElement( 'canvas' );
context = canvas.getContext( '2d' );
canvas.height = tileWidth;
canvas.width = tileWidth;
context.drawImage(image, tileWidth * i, 0, tileWidth, tileWidth, 0, 0, tileWidth, tileWidth );
textures[i].image = canvas;
textures[i].needsUpdate = true;
}
});
return textures;
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
controls.update();
renderer.render( scene, camera );
}
QQ:3410192267 | 技术支持 微信:popstarqqsmall
Copyright ©2017 xiaobaigis.com . 版权所有 鲁ICP备17027716号