跳到主要内容

室内预览 VR

预览

安装

yarn add three

实现

Vue 实现

:::details 点击 Three.vue 代码

<template>
<div id="container"></div>
</template>

<script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";

export default {
components: {},
data() {
return {
scene: null,
camera: null,
renderer: null,
width: "",
height: 800,
hotPoints: [
{
position: {
x: 0,
y: 0,
z: -0.2,
},
detail: {
title: "信息点1",
},
},
{
position: {
x: -0.2,
y: -0.05,
z: 0.2,
},
detail: {
title: "信息点2",
},
},
],
hot:require("./images/hot.png") ,
scenes:require("./images/scene.jpeg") ,
scene_back:require("./images/scene_back.jpeg"),
scene_bottom:require("./images/scene_bottom.jpeg"),
scene_front:require("./images/scene_front.jpeg"),
scene_left:require("./images/scene_left.jpeg"),
scene_right:require("./images/scene_right.jpeg"),
scene_top:require("./images/scene_top.jpeg")
};
},
mounted() {
this.width = this.$el.clientWidth;
this.initThree();
},
watch: {},
methods: {
initThree() {
this.scene = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera(
90,
this.width / this.height,
0.1,
100
);
this.camera.position.set(0, 0, 0.01);
this.renderer = new THREE.WebGLRenderer();
this.renderer.setSize(this.width, this.height);
this.$el.appendChild(this.renderer.domElement);
const controls = new OrbitControls(this.camera, this.renderer.domElement);
this.useSphere();
// useBox();
this.initPoints();
this.loop();
},
useBox() {
const materials = [];
const texture_left = new THREE.TextureLoader().load(this.hot);
materials.push(new THREE.MeshBasicMaterial({ map: texture_left }));
const texture_right = new THREE.TextureLoader().load(this.scene_right);
materials.push(new THREE.MeshBasicMaterial({ map: texture_right }));
const texture_top = new THREE.TextureLoader().load(this.scene_top);
materials.push(new THREE.MeshBasicMaterial({ map: texture_top }));
const texture_bottom = new THREE.TextureLoader().load(this.scene_bottom);
materials.push(new THREE.MeshBasicMaterial({ map: texture_bottom }));
const texture_front = new THREE.TextureLoader().load(this.scene_front);
materials.push(new THREE.MeshBasicMaterial({ map: texture_front }));
const texture_back = new THREE.TextureLoader().load(this.scene_back);
materials.push(new THREE.MeshBasicMaterial({ map: texture_back }));
const box = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), materials);
box.geometry.scale(1, 1, -1);
this.scene.add(box);
},
useSphere() {
const sphereGeometry = new THREE.SphereGeometry(1, 50, 50);
sphereGeometry.scale(1, 1, -1);
// sphereGeometry.rotateY(180*Math.PI/180);
const texture = new THREE.TextureLoader().load(this.scenes);
const sphereMaterial = new THREE.MeshBasicMaterial({ map: texture });
// var sphereGeometry = new THREE.SphereGeometry(50, 20, 20);
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
// sphere.material.wireframe = true;
this.scene.add(sphere);
},
loop() {
requestAnimationFrame(this.loop);
this.renderer.render(this.scene, this.camera);
},
initPoints() {
const pointTexture = new THREE.TextureLoader().load(this.hot);
const material = new THREE.SpriteMaterial({ map: pointTexture });
const poiObjects = [];
for (let i = 0; i < this.hotPoints.length; i++) {
const sprite = new THREE.Sprite(material);
sprite.scale.set(0.1, 0.1, 0.1);
sprite.position.set(
this.hotPoints[i].position.x,
this.hotPoints[i].position.y,
this.hotPoints[i].position.z
);
this.scene.add(sprite);
sprite.detail = this.hotPoints[i].detail;
poiObjects.push(sprite);
}
this.$el.addEventListener("click", function(event) {
event.preventDefault();
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
mouse.x = (event.clientX / this.width) * 2 - 1;
mouse.y = -(event.clientY / this.height) * 2 + 1;
raycaster.setFromCamera(mouse, this.camera);
const intersects = raycaster.intersectObjects(poiObjects);
if (intersects.length > 0) {
alert("点击了热点" + intersects[0].object.detail.title);
}
});
},
},
};
</script>

<style lang="scss" scoped></style>

:::

React 实现

:::details 点击查看 App.tsx 代码

import React, {useEffect} from 'react';
import Three from './Components/Three';

function App() {
return <Three></Three>;
}

export default App;

:::

:::details 点击查看 Three.tsx 代码

import React, {useEffect} from 'react';
import * as THREE from 'three';
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js';

import hot from '../assets/images/hot.png';
import scenes from '../assets/images/scene.jpeg';
import scene_back from '../assets/images/scene_back.jpeg';
import scene_bottom from '../assets/images/scene_bottom.jpeg';
import scene_front from '../assets/images/scene_front.jpeg';
import scene_left from '../assets/images/scene_left.jpeg';
import scene_right from '../assets/images/scene_right.jpeg';
import scene_top from '../assets/images/scene_top.jpeg';

let scene, camera, renderer;
const hotPoints = [
{
position: {
x: 0,
y: 0,
z: -0.2,
},
detail: {
title: '信息点1',
},
},
{
position: {
x: -0.2,
y: -0.05,
z: 0.2,
},
detail: {
title: '信息点2',
},
},
];
function initThree() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(
90,
document.body.clientWidth / document.body.clientHeight,
0.1,
100,
);
camera.position.set(0, 0, 0.01);
renderer = new THREE.WebGLRenderer();
renderer.setSize(document.body.clientWidth, document.body.clientHeight);
document.getElementById('container').appendChild(renderer.domElement);
const controls = new OrbitControls(camera, renderer.domElement);
useSphere();
// useBox();
initPoints();
loop();
}
function useBox() {
const materials = [];
const texture_left = new THREE.TextureLoader().load(hot);
materials.push(new THREE.MeshBasicMaterial({map: texture_left}));
const texture_right = new THREE.TextureLoader().load(scene_right);
materials.push(new THREE.MeshBasicMaterial({map: texture_right}));
const texture_top = new THREE.TextureLoader().load(scene_top);
materials.push(new THREE.MeshBasicMaterial({map: texture_top}));
const texture_bottom = new THREE.TextureLoader().load(scene_bottom);
materials.push(new THREE.MeshBasicMaterial({map: texture_bottom}));
const texture_front = new THREE.TextureLoader().load(scene_front);
materials.push(new THREE.MeshBasicMaterial({map: texture_front}));
const texture_back = new THREE.TextureLoader().load(scene_back);
materials.push(new THREE.MeshBasicMaterial({map: texture_back}));
const box = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), materials);
box.geometry.scale(1, 1, -1);
scene.add(box);
}
function useSphere() {
const sphereGeometry = new THREE.SphereGeometry(1, 50, 50);
sphereGeometry.scale(1, 1, -1);
// sphereGeometry.rotateY(180*Math.PI/180);
const texture = new THREE.TextureLoader().load(scenes);
const sphereMaterial = new THREE.MeshBasicMaterial({map: texture});
// var sphereGeometry = new THREE.SphereGeometry(50, 20, 20);
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
// sphere.material.wireframe = true;
scene.add(sphere);
}
function loop() {
requestAnimationFrame(loop);
renderer.render(scene, camera);
}
function initPoints() {
const pointTexture = new THREE.TextureLoader().load(hot);
const material = new THREE.SpriteMaterial({map: pointTexture});
const poiObjects = [];
for (let i = 0; i < hotPoints.length; i++) {
const sprite = new THREE.Sprite(material);
sprite.scale.set(0.1, 0.1, 0.1);
sprite.position.set(
hotPoints[i].position.x,
hotPoints[i].position.y,
hotPoints[i].position.z,
);
scene.add(sprite);
sprite.detail = hotPoints[i].detail;
poiObjects.push(sprite);
}
document
.querySelector('#container')
.addEventListener('click', function (event) {
event.preventDefault();
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
mouse.x = (event.clientX / document.body.clientWidth) * 2 - 1;
mouse.y = -(event.clientY / document.body.clientHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(poiObjects);
if (intersects.length > 0) {
alert('点击了热点' + intersects[0].object.detail.title);
}
});
}

function Three() {
useEffect(() => {
initThree();
});
return <div id="container" style={{height: '100vh'}}></div>;
}

export default Three;

:::