WebGL3D引擎
http://www.webgl3d.cn/threejs/docs/#api/zh/core/Raycaster
一.客户端,加载六张图及按钮位置,点击按钮删除旧的图及按钮,加载下一组图
<template>
<div class="home">
<div>
<div id="container" style="height: 900px;transition:all 0.5s"></div>
</div>
</div>
</template>
<script>
// @ is an alias to /src
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
export default {
name: "Home",
components: {
},
data(){
return {
camera:null,
scene: null,
renderer: null,
controls: null,
poiObjects: [],
box:null,
button:[],
text:[],
}
},
mounted() {
this.scene = new THREE.Scene()
this.initThree();
this.drawOut()
this.scroll()
this.func()
this.scecond();
},
methods: {
scecond() {
document.getElementById('container').style.transform = 'scale(1,1)'
if(this.scene){
this.button.forEach((item)=>{
this.scene.remove(item)
})
this.scene.remove(this.box)
this.text.forEach((item)=>{
this.scene.remove(item)
})
}
let data = {
left:require("./images/scene_left1.jpg"),
right:require("./images/scene_right1.jpg"),
top:require("./images/scene_top1.jpg"),
bottom:require("./images/scene_bottom1.jpg"),
front:require("./images/scene_front1.jpg"),
back:require("./images/scene_back1.jpg")
}
let hotPoints = [
{
position: {
x: 0.45,
y: 0,
z: -0.3,
},
detail: {
title: "卧室",
path:'卧室'
},
},
// {
// position: {
// x: -0.2,
// y: -0.05,
// z: 0.45,
// },
// detail: {
// title: "信息点2",
// },
// },
];
this.draw(data)
this.firstButton(hotPoints)
this.showText(hotPoints)
},
first() {
document.getElementById('container').style.transform = 'scale(1,1)'
if(this.scene){
this.button.forEach((item)=>{
this.scene.remove(item)
})
this.scene.remove(this.box)
this.text.forEach((item)=>{
this.scene.remove(item)
})
}
// var texture = new THREE.TextureLoader().load("./images/scene.jpeg");
// var sphereMaterial = new THREE.MeshBasicMaterial({ map: texture });
// var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
// // sphere.material.wireframe = true;
// var sphereGeometry = new THREE.SphereGeometry(/*半径*/ 1, 50, 50);
// sphereGeometry.scale(1, 1, -1);
let data = {
left:require("./images/scene_left.jpg"),
right:require("./images/scene_right.jpg"),
top:require("./images/scene_top.jpg"),
bottom:require("./images/scene_bottom.jpg"),
front:require("./images/scene_front.jpg"),
back:require("./images/scene_back.jpg")
}
let hotPoints = [
{
position: {
x: 0.05,
y: -0.2,
z: -0.45,
},
detail: {
title: "看书",
path:'看书'
},
},
{
position: {
x: 0.45,
y: 0,
z: -0.05,
},
detail: {
title: "大厅",
path:'大厅'
},
},
];
this.draw(data)
this.firstButton(hotPoints)
this.showText(hotPoints)
},
firstButton(hotPoints){
var pointTexture = new THREE.TextureLoader().load(
require("./images/button.png")
);
var material = new THREE.SpriteMaterial({ map: pointTexture });
this.poiObjects = [];
this.button = []
for (var i = 0; i < hotPoints.length; i++) {
var sprite = new THREE.Sprite(material);
sprite.scale.set(0.05, 0.05, 0.05);
sprite.position.set(
hotPoints[i].position.x,
hotPoints[i].position.y,
hotPoints[i].position.z
);
this.button.push(sprite)
this.scene.add(sprite);
sprite.detail = hotPoints[i].detail;
this.poiObjects.push(sprite);
}
},
showText(hotPoints) {
this.text = []
for (var i = 0; i < hotPoints.length; i++) {
// var text = new THREE.FontLoader().load(require("./font/NotoKR-Black_Black.json"), function(text) {
// console.log(123)
// var gem = new THREE.TextGeometry('51JOB', {
// size: 20, //字号大小,一般为大写字母的高度
// height: 10, //文字的厚度
// weight: 'normal', //值为'normal'或'bold',表示是否加粗
// font: text, //字体,默认是'helvetiker',需对应引用的字体文件
// style: 'normal', //值为'normal'或'italics',表示是否斜体
// bevelThickness: 1, //倒角厚度
// bevelSize: 1, //倒角宽度
// curveSegments: 30,//弧线分段数,使得文字的曲线更加光滑
// bevelEnabled: true, //布尔值,是否使用倒角,意为在边缘处斜切
// });
// gem.center();
// var mat = new THREE.MeshPhongMaterial({
// color: 0xffe502,
// specular: 0x009900,
// shininess: 30,
// shading: THREE.FlatShading
// });
// var textObj = new THREE.Mesh(gem, mat);
// textObj.castShadow = true;
// console.log('!!!!',textObj)
// scene.add(textObj);
// new TWEEN.Tween(textObj.rotation).to({y: Math.PI * 2}, 2000).repeat(Infinity).yoyo(true).start();
// });
//创建canvas对象用来绘制文字
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
ctx.fillStyle = "red";
ctx.font = "bolder 10px Arial ";
ctx.fillText(hotPoints[i].detail.title, 140, 65);
ctx.globalAlpha = 1;
// 将画布生成的图片作为贴图给精灵使用,并将精灵创建在设定好的位置
let texture = new THREE.Texture(canvas);
texture.needsUpdate = true;
//创建精灵,将该材质赋予给创建的精灵
// let spriteMaterial = new THREE.PointsMaterial({
// map: texture,
// // sizeAttenuation: true,
// // size: 30,
// transparent: true,
// opacity: 1,
// });
// //创建坐标点,并将材质给坐标
// let geometry = new THREE.BufferGeometry();
// let vertices = [0, 0, 0];
// geometry.setAttribute(
// "position",
// new THREE.Float32BufferAttribute(vertices, 3)
// );
// let sprite = new THREE.Points(geometry, spriteMaterial);
// sprite.position.set(position.x, position.y, position.z);
// sprite.scale.set(0.01, 0.01, 0.01);
// this.scene.add(sprite);
// const canvasTexture = new THREE.CanvasTexture(
// document.querySelector("#canvas")
// )
// //canvasTexture.needsUpdate = true; //注意这句不能少
const spritMaterial = new THREE.SpriteMaterial({
map: texture
})
let sprite = new THREE.Sprite(spritMaterial)
sprite.position.set(hotPoints[i].position.x, hotPoints[i].position.y, hotPoints[i].position.z);
//精灵的默认大小很小估计是[1,1,1]
sprite.scale.set(0.5, 0.5, 0.5);
this.text.push(sprite)
this.scene.add(sprite)
}
},
initThree() {
//镜头
this.camera = new THREE.PerspectiveCamera(
90,
document.body.clientWidth / 900,
0.1,
100
);
// document.body.clientWidth / document.body.clientHeight
this.camera.up.x = 0; //相机以哪个方向为上方
this.camera.up.y = 1;
this.camera.up.z = 0; //默认值
// 镜头初始位置
this.camera.position.set(0, 0, 0.01);
// camera.lookAt(0,0,0) //使用了OrbitControls导致无法使用 改用controls的target
//渲染器
this.renderer = new THREE.WebGLRenderer({ antialias: true });
this.renderer.setPixelRatio(window.devicePixelRatio);
this.renderer.setSize(document.body.clientWidth, 900);
this.renderer.shadowMap.enabled = true; //告诉渲染器需要阴影效果
document.getElementById("container").appendChild(this.renderer.domElement);
//镜头控制器
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
this.controls.enableDamping = true; //动态阻尼系数 就是鼠标拖拽旋转灵敏度
this.controls.dampingFactor = 0.14; //动态阻尼系数 就是鼠标拖拽旋转灵敏度
this.controls.enableZoom = true; //是否可以缩放
this.controls.zoomSpeed = 5;
this.controls.autoRotate = true; //是否自动旋转
this.controls.autoRotateSpeed = 0.5;
this.controls.minDistance = 0; //设置相机距离原点的最小距离
this.controls.maxDistance = 10; //设置相机距离原点的最远距离
this.controls.enablePan = false; //是否开启右键拖拽平移
this.controls.panSpeed = 10; //平移速度
this.controls.enableKeys = false; //启用或禁用键盘控制
this.controls.keyPanSpeed = 30; //键盘平移速度
this.controls.keys = {
LEFT: 37, //left arrow
UP: 38, // up arrow
RIGHT: 39, // right arrow
BOTTOM: 40, // down arrow
};
let m = new THREE.Vector3();
m.x = 0;
m.y = 0;
m.z = 0;
this.controls.target = m; //控制看向某个方向
//一会儿在这里添加3D物体
this.loop();
},
//帧同步重绘
loop() {
this.controls.update();
requestAnimationFrame(this.loop);
this.renderer.render(this.scene, this.camera);
},
// 绘制六张图
draw(datas){
var materials = [];
//根据左右上下前后的顺序构建六个面的材质集
var texture_left = new THREE.TextureLoader().load(
datas.left
);
materials.push(new THREE.MeshBasicMaterial({ map: texture_left }));
var texture_right = new THREE.TextureLoader().load(
datas.right
);
materials.push(new THREE.MeshBasicMaterial({ map: texture_right }));
var texture_top = new THREE.TextureLoader().load(
datas.top
);
materials.push(new THREE.MeshBasicMaterial({ map: texture_top }));
var texture_bottom = new THREE.TextureLoader().load(
datas.bottom
);
materials.push(new THREE.MeshBasicMaterial({ map: texture_bottom }));
var texture_front = new THREE.TextureLoader().load(
datas.front
);
materials.push(new THREE.MeshBasicMaterial({ map: texture_front }));
var texture_back = new THREE.TextureLoader().load(
datas.back
);
materials.push(new THREE.MeshBasicMaterial({ map: texture_back }));
var box = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), materials);
this.box = box
this.scene.add(box);
box.geometry.scale(1, 1, -1);
},
//绘制外层圆形轮廓
drawOut(){
var sphereGeometry = new THREE.SphereGeometry(
/*半径*/ 1,
/*垂直节点数量*/ 50,
/*水平节点数量*/ 50
); //节点数量越大,需要计算的三角形就越多,影响性能
var sphere = new THREE.Mesh(sphereGeometry);
sphere.material.wireframe = true; //用线框模式大家可以看得清楚是个球体而不是圆形
this.scene.add(sphere);
},
// 滚动事件
scroll(){
var fov = 90;
var near = 45;
var far = 100;
var scrollFunc = (event) => {
// event.preventDefault();
//event.stopPropagation();
if (event.wheelDelta) {
//判断浏览器IE,谷歌滑轮事件
if (event.wheelDelta > 0) {
//当滑轮向上滚动时
fov -= near < fov ? 1 : 0;
} else {
//当滑轮向下滚动时
fov += fov < far ? 1 : 0;
}
}
//改变fov值,并更新场景的渲染
this.camera.fov = fov;
this.camera.updateProjectionMatrix();
this.renderer.render(this.scene, this.camera);
};
/*IE、Opera注册事件*/
if (document.attachEvent) {
document.attachEvent("onmousewheel", scrollFunc);
}
//Firefox使用addEventListener添加滚轮事件
if (document.addEventListener) {
//firefox
document.addEventListener("DOMMouseScroll", scrollFunc, false);
}
//Safari与Chrome属于同一类型
window.onmousewheel = document.onmousewheel = scrollFunc;
},
func(){
document
.querySelector("#container")
.addEventListener("click", (event) => {
event.preventDefault();
var raycaster = new THREE.Raycaster();
var 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, this.camera);
var intersects = raycaster.intersectObjects(this.poiObjects);
if (intersects.length > 0) {
// camera.position.set(0, 0.1, 0.01);
if(intersects[0].object.detail.path === '看书'){
alert(intersects[0].object.detail.title)
}else if(intersects[0].object.detail.path === '卧室'){
document.getElementById('container').style.transform = 'scale(100,100)'
setTimeout(()=>{
this.first()
},250)
}else if(intersects[0].object.detail.path === '大厅'){
document.getElementById('container').style.transform = 'scale(100,100)'
setTimeout(()=>{
this.scecond()
},250)
}
// controls.screenSpacePanning = true
// alert("点击了热点" + intersects[0].object.detail.title);
}
});
}
},
};
</script>
二、后台,上传六张图片后,开始创建场景scene,右上角设置了多个按钮,点击不同按钮可设置不同的功能(通过status显示到客户端,如弹窗介绍,跳转场景),点击按钮后场景中会按钮,可调整位置,并将位置保存
<template>
<div class="home">
<!-- <div id="pre" style="position:absolute;left:0;top:0;height:900px">
<img style="height:900px;" :src="loadPic[now]" alt="">
<div @click="this.preview" style="position:absolute;left:0;top:0">预览</div>
<div style="position:absolute;left:50%;top:0">{{now}}</div>
</div> -->
<div>
<div id="container" style="height: 900px;position:relative"></div>
<!-- <canvas canvas-id="canvas"></canvas> -->
</div>
<div style="position:fixed;right:0;top:0;display:flex;flex-direction:column;">
<img @click="addButton(item)" v-for="(item, index) in someButton" :key="index" style="width:40px;height:40px;" :src="item.img" alt="">
</div>
<div v-if="select" style="position:fixed;right:50%;bottom:0;display:flex;flex-direction:column;">
<div>
当前选中: <input type="text" v-model="select.detail.title">
</div>
<div>
<span>
x: <input type="text" v-model="select.position.x">
y: <input type="text" v-model="select.position.y">
z: <input type="text" v-model="select.position.z">
</span>
</div>
<div @click="confirm">确认</div>
<div @click="del">删除</div>
</div>
</div>
</template>
<script>
// @ is an alias to /src
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
export default {
name: "Home",
components: {
},
data(){
return {
loadPic:{
left:require("./images/scene_left.jpg"),
right:require("./images/scene_right.jpg"),
top:require("./images/scene_top.jpg"),
bottom:require("./images/scene_bottom.jpg"),
front:require("./images/scene_front.jpg"),
back:require("./images/scene_back.jpg")
},
someButton:[
{
img:require("./images/button.png"),
status:1
},
{
img:require("./images/button.png"),
status:2
},
{
img:require("./images/button.png"),
status:3
},
],
point: [],
select:null,
now:'left',
camera:null,
scene: null,
renderer: null,
controls: null,
poiObjects: [],
}
},
mounted() {
this.preview()
},
methods: {
addButton(item){
var detail = prompt("输入名称")
let id = new Date().getTime()
this.point.push({
position:{
x:0,
y:0,
z:-0.2
},
detail: {
title: detail,
path:'大厅',
status:item.status,
id
}
})
this.firstButton([{
position:{
x:0,
y:0,
z:-0.2
},
detail: {
title: detail,
path:'大厅',
status:item.status,
id
}
}])
this.showText([{
position:{
x:0,
y:0,
z:-0.2
},
detail: {
title: detail,
path:'大厅',
status:item.status,
id
}
}])
},
preview(){
this.scene = new THREE.Scene()
this.initThree();
this.drawOut()
this.scroll()
this.func()
this.first();
},
first() {
document.getElementById('container').style.transform = 'scale(1,1)'
// var texture = new THREE.TextureLoader().load("./images/scene.jpeg");
// var sphereMaterial = new THREE.MeshBasicMaterial({ map: texture });
// var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
// // sphere.material.wireframe = true;
// var sphereGeometry = new THREE.SphereGeometry(/*半径*/ 1, 50, 50);
// sphereGeometry.scale(1, 1, -1);
let data = this.loadPic
let hotPoints = this.point
this.draw(data)
this.firstButton(hotPoints)
this.showText(hotPoints)
},
firstButton(hotPoints){
var pointTexture = new THREE.TextureLoader().load(
require("./images/button.png")
);
var material = new THREE.SpriteMaterial({ map: pointTexture });
this.poiObjects = [];
for (var i = 0; i < hotPoints.length; i++) {
var sprite = new THREE.Sprite(material);
sprite.scale.set(0.05, 0.05, 0.05);
sprite.position.set(
hotPoints[i].position.x,
hotPoints[i].position.y,
hotPoints[i].position.z
);
this.scene.add(sprite);
sprite.detail = hotPoints[i].detail;
this.poiObjects.push(sprite);
}
},
showText(hotPoints) {
this.text = []
for (var i = 0; i < hotPoints.length; i++) {
// var text = new THREE.FontLoader().load(require("./font/NotoKR-Black_Black.json"), function(text) {
// console.log(123)
// var gem = new THREE.TextGeometry('51JOB', {
// size: 20, //字号大小,一般为大写字母的高度
// height: 10, //文字的厚度
// weight: 'normal', //值为'normal'或'bold',表示是否加粗
// font: text, //字体,默认是'helvetiker',需对应引用的字体文件
// style: 'normal', //值为'normal'或'italics',表示是否斜体
// bevelThickness: 1, //倒角厚度
// bevelSize: 1, //倒角宽度
// curveSegments: 30,//弧线分段数,使得文字的曲线更加光滑
// bevelEnabled: true, //布尔值,是否使用倒角,意为在边缘处斜切
// });
// gem.center();
// var mat = new THREE.MeshPhongMaterial({
// color: 0xffe502,
// specular: 0x009900,
// shininess: 30,
// shading: THREE.FlatShading
// });
// var textObj = new THREE.Mesh(gem, mat);
// textObj.castShadow = true;
// console.log('!!!!',textObj)
// scene.add(textObj);
// new TWEEN.Tween(textObj.rotation).to({y: Math.PI * 2}, 2000).repeat(Infinity).yoyo(true).start();
// });
//创建canvas对象用来绘制文字
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
ctx.fillStyle = "red";
ctx.font = "bolder 10px Arial ";
ctx.fillText(hotPoints[i].detail.title, 140, 65);
ctx.globalAlpha = 1;
// 将画布生成的图片作为贴图给精灵使用,并将精灵创建在设定好的位置
let texture = new THREE.Texture(canvas);
texture.needsUpdate = true;
const spritMaterial = new THREE.SpriteMaterial({
map: texture
})
let sprite = new THREE.Sprite(spritMaterial)
sprite.position.set(hotPoints[i].position.x, hotPoints[i].position.y, hotPoints[i].position.z);
//精灵的默认大小很小估计是[1,1,1]
sprite.scale.set(0.5, 0.5, 0.5);
sprite.detail = hotPoints[i].detail;
this.text.push(sprite)
this.scene.add(sprite)
}
},
initThree() {
//镜头
this.camera = new THREE.PerspectiveCamera(
90,
document.body.clientWidth / 900,
0.1,
100
);
// document.body.clientWidth / document.body.clientHeight
this.camera.up.x = 0; //相机以哪个方向为上方
this.camera.up.y = 1;
this.camera.up.z = 0; //默认值
// 镜头初始位置
this.camera.position.set(0, 0, 0.01);
// camera.lookAt(0,0,0) //使用了OrbitControls导致无法使用 改用controls的target
//渲染器
this.renderer = new THREE.WebGLRenderer({ antialias: true });
this.renderer.setPixelRatio(window.devicePixelRatio);
this.renderer.setSize(document.body.clientWidth, 900);
this.renderer.shadowMap.enabled = true; //告诉渲染器需要阴影效果
document.getElementById("container").appendChild(this.renderer.domElement);
//镜头控制器
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
this.controls.enableDamping = true; //动态阻尼系数 就是鼠标拖拽旋转灵敏度
this.controls.dampingFactor = 0.14; //动态阻尼系数 就是鼠标拖拽旋转灵敏度
this.controls.enableZoom = true; //是否可以缩放
this.controls.zoomSpeed = 5;
// this.controls.autoRotate = true; //是否自动旋转
// this.controls.autoRotateSpeed = 0.5;
this.controls.minDistance = 0; //设置相机距离原点的最小距离
this.controls.maxDistance = 10; //设置相机距离原点的最远距离
this.controls.enablePan = false; //是否开启右键拖拽平移
this.controls.panSpeed = 10; //平移速度
this.controls.enableKeys = false; //启用或禁用键盘控制
this.controls.keyPanSpeed = 30; //键盘平移速度
this.controls.keys = {
LEFT: 37, //left arrow
UP: 38, // up arrow
RIGHT: 39, // right arrow
BOTTOM: 40, // down arrow
};
let m = new THREE.Vector3();
m.x = 0;
m.y = 0;
m.z = 0;
this.controls.target = m; //控制看向某个方向
//一会儿在这里添加3D物体
this.loop();
},
//帧同步重绘
loop() {
this.controls.update();
requestAnimationFrame(this.loop);
this.renderer.render(this.scene, this.camera);
},
// 绘制六张图
draw(datas){
var materials = [];
//根据左右上下前后的顺序构建六个面的材质集
var texture_left = new THREE.TextureLoader().load(
datas.left
);
materials.push(new THREE.MeshBasicMaterial({ map: texture_left }));
var texture_right = new THREE.TextureLoader().load(
datas.right
);
materials.push(new THREE.MeshBasicMaterial({ map: texture_right }));
var texture_top = new THREE.TextureLoader().load(
datas.top
);
materials.push(new THREE.MeshBasicMaterial({ map: texture_top }));
var texture_bottom = new THREE.TextureLoader().load(
datas.bottom
);
materials.push(new THREE.MeshBasicMaterial({ map: texture_bottom }));
var texture_front = new THREE.TextureLoader().load(
datas.front
);
materials.push(new THREE.MeshBasicMaterial({ map: texture_front }));
var texture_back = new THREE.TextureLoader().load(
datas.back
);
materials.push(new THREE.MeshBasicMaterial({ map: texture_back }));
var box = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), materials);
this.box = box
this.scene.add(box);
box.geometry.scale(1, 1, -1);
},
//绘制外层圆形轮廓
drawOut(){
var sphereGeometry = new THREE.SphereGeometry(
/*半径*/ 1,
/*垂直节点数量*/ 50,
/*水平节点数量*/ 50
); //节点数量越大,需要计算的三角形就越多,影响性能
var sphere = new THREE.Mesh(sphereGeometry);
sphere.material.wireframe = true; //用线框模式大家可以看得清楚是个球体而不是圆形
this.scene.add(sphere);
},
// 滚动事件
scroll(){
var fov = 90;
var near = 45;
var far = 100;
var scrollFunc = (event) => {
// event.preventDefault();
//event.stopPropagation();
if (event.wheelDelta) {
//判断浏览器IE,谷歌滑轮事件
if (event.wheelDelta > 0) {
//当滑轮向上滚动时
fov -= near < fov ? 1 : 0;
} else {
//当滑轮向下滚动时
fov += fov < far ? 1 : 0;
}
}
//改变fov值,并更新场景的渲染
this.camera.fov = fov;
this.camera.updateProjectionMatrix();
this.renderer.render(this.scene, this.camera);
};
/*IE、Opera注册事件*/
if (document.attachEvent) {
document.attachEvent("onmousewheel", scrollFunc);
}
//Firefox使用addEventListener添加滚轮事件
if (document.addEventListener) {
//firefox
document.addEventListener("DOMMouseScroll", scrollFunc, false);
}
//Safari与Chrome属于同一类型
window.onmousewheel = document.onmousewheel = scrollFunc;
},
func(){
document
.querySelector("#container")
.addEventListener("click", (event) => {
event.preventDefault();
var raycaster = new THREE.Raycaster();
var 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, this.camera);
var intersects = raycaster.intersectObjects(this.poiObjects);
console.log(intersects, mouse)
if (intersects.length > 0) {
this.select = {
position:intersects[0].object.position,
detail:intersects[0].object.detail
}
// camera.position.set(0, 0.1, 0.01);
// if(intersects[0].object.detail.path === '看书'){
// alert(intersects[0].object.detail.title)
// }else if(intersects[0].object.detail.path === '卧室'){
// document.getElementById('container').style.transform = 'scale(100,100)'
// setTimeout(()=>{
// this.first()
// },250)
// }else if(intersects[0].object.detail.path === '大厅'){
// document.getElementById('container').style.transform = 'scale(100,100)'
// setTimeout(()=>{
// this.scecond()
// },250)
// }
}
});
// document
// .querySelector("#container")
// .addEventListener("mousemove", (event) => {
// console.log(123)
// event.preventDefault();
// var raycaster = new THREE.Raycaster();
// var 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, this.camera);
// var intersects = raycaster.intersectObjects(this.poiObjects);
// if (intersects.length > 0) {
// // camera.position.set(0, 0.1, 0.01);
// if(intersects[0].object.detail.path === '看书'){
// alert(intersects[0].object.detail.title)
// }else if(intersects[0].object.detail.path === '卧室'){
// document.getElementById('container').style.transform = 'scale(100,100)'
// setTimeout(()=>{
// this.first()
// },250)
// }else if(intersects[0].object.detail.path === '大厅'){
// document.getElementById('container').style.transform = 'scale(100,100)'
// setTimeout(()=>{
// this.scecond()
// },250)
// }
// // controls.screenSpacePanning = true
// // alert("点击了热点" + intersects[0].object.detail.title);
// }
// });
},
confirm(){
let arr = this.scene.children.filter((item)=>{
if(!item.detail) return false
return item.detail.id === this.select.detail.id
})
let index = this.point.findIndex(item=>item.detail.id === this.select.detail.id)
this.point.splice(index,1,this.select)
arr.forEach((item)=>{
this.scene.remove(item)
})
this.firstButton([this.select])
this.showText([this.select])
this.select = null
},
del(){
let arr = this.scene.children.filter((item)=>{
if(!item.detail) return false
return item.detail.id === this.select.detail.id
})
let index = this.point.findIndex(item=>item.detail.id === this.select.detail.id)
this.point.splice(index,1)
arr.forEach((item)=>{
this.scene.remove(item)
})
this.select = null
}
},
};
</script>
借鉴于https://blog.csdn.net/weixin_36774307/article/details/118090868
功能 Three.js清除场景/模型释放内存
https://blog.csdn.net/qq_44375977/article/details/115871217
THREE.js创建三维文字TextGeometry
https://blog.csdn.net/unirrrrr/article/details/80651837
一张全景图
<template>
<div class="home">
<div ref="container" id="container" style="width: 100%; height: 800px"></div>
</div>
</template>
<script>
// @ is an alias to /src
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
export default {
name: "Home",
components: {
},
data(){
return {
sceneUrl: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.zcool.cn%2Fcommunity%2F01dead58f03a61a8012049ef124133.jpg%403000w_1l_2o_100sh.jpg&refer=http%3A%2F%2Fimg.zcool.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1636353181&t=8986b8074d4093d2fdc187ee5f562bd0', // 需要预览的图片绝对路径
camera: null,
scene: null,
renderer: null,
isUserInteracting: false,
onPointerDownPointerX: 0,
onPointerDownPointerY: 0,
lon: 0,
onPointerDownLon: 0,
lat: 0,
onPointerDownLat: 0,
phi: 0,
theta: 0,
target: new THREE.Vector3()
}
},
mounted() {
this.init()
},
methods: {
init() {
let textureLoader = new THREE.TextureLoader();
textureLoader.load(this.sceneUrl, (texture) => {
texture.mapping = THREE.UVMapping;
this.initImg(texture);
this.render();
});
},
initImg(texture) {
let container, mesh;
// 容器宽度、高度
let containerWidth = this.$refs.container.offsetWidth;
let containerHeight = this.$refs.container.offsetHeight;
container = document.getElementById('container');
this.renderer = new THREE.WebGLRenderer({ antialias: true });
this.renderer.setPixelRatio(window.devicePixelRatio);
// this.renderer.setSize(window.innerWidth, window.innerHeight);
this.renderer.setSize(containerWidth, containerHeight);
let childs = container.childNodes;
if (container.childNodes.length > 0) {
container.removeChild(childs[0]);
container.appendChild(this.renderer.domElement);
} else {
container.appendChild(this.renderer.domElement);
}
this.scene = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera(60, containerWidth / containerHeight , 1, 1000);
mesh = new THREE.Mesh(new THREE.SphereBufferGeometry(500, 32, 16), new THREE.MeshBasicMaterial({ map: texture }));
mesh.geometry.scale(-1, 1, 1);
this.scene.add(mesh);
container.addEventListener('mousedown', this.onDocumentMouseDown, false);
container.addEventListener('mousemove', this.onDocumentMouseMove, false);
container.addEventListener('mouseup', this.onDocumentMouseUp, false);
container.addEventListener('mousewheel', this.onDocumentMouseWheel, false);
container.addEventListener('touchstart', this.onDocumentTouchStart, false);
container.addEventListener('touchmove', this.onDocumentTouchMove, false);
},
onDocumentMouseDown(event) {
event.preventDefault();
this.isUserInteracting = true;
this.onPointerDownPointerX = event.clientX;
this.onPointerDownPointerY = event.clientY;
this.onPointerDownLon = this.lon;
this.onPointerDownLat = this.lat;
},
onDocumentMouseMove(event) {
if (this.isUserInteracting) {
this.lon = (this.onPointerDownPointerX - event.clientX) * 0.1 + this.onPointerDownLon;
this.lat = (event.clientY - this.onPointerDownPointerY) * 0.1 + this.onPointerDownLat;
this.render();
}
},
onDocumentMouseUp(event) {
this.isUserInteracting = false;
this.render();
},
onDocumentMouseWheel(event) {
this.camera.fov -= event.wheelDeltaY * 0.05;
this.camera.updateProjectionMatrix();
event = event || window.event;
if (event.stopPropagation) { // 这是取消冒泡
event.stopPropagation();
} else {
event.cancelBubble = true;
};
if (event.preventDefault) { // 这是取消默认行为
event.preventDefault();
} else {
event.returnValue = false;
};
this.render();
},
onDocumentTouchStart(event) {
if (event.touches.length == 1) {
event.preventDefault();
this.onPointerDownPointerX = event.touches[0].pageX;
this.onPointerDownPointerY = event.touches[0].pageY;
this.onPointerDownLon = this.lon;
this.onPointerDownLat = this.lat;
}
},
onDocumentTouchMove(event) {
if (event.touches.length == 1) {
event.preventDefault();
this.lon = (this.onPointerDownPointerX - event.touches[0].pageX) * 0.1 + this.onPointerDownLon;
this.lat = (event.touches[0].pageY - this.onPointerDownPointerY) * 0.1 + this.onPointerDownLat;
this.render();
}
},
render() {
this.lon += 0.15;
this.lat = Math.max(-85, Math.min(85, this.lat));
this.phi = THREE.Math.degToRad(90 - this.lat);
this.theta = THREE.Math.degToRad(this.lon);
this.camera.position.x = 100 * Math.sin(this.phi) * Math.cos(this.theta);
this.camera.position.y = 100 * Math.cos(this.phi);
this.camera.position.z = 100 * Math.sin(this.phi) * Math.sin(this.theta);
this.camera.lookAt(this.scene.position);
this.renderer.render(this.scene, this.camera);
}
},
};
</script>