代码语言:javascript复制
<template>
<div class="wrap">
<div ref="container" id="container"></div>
<div id="panel" v-if="isShowPanel" :style ="{left:left 'px',top:top 'px'}">
<div>名称:{{panel.name}}</div>
<div>温度:{{panel.temp}}</div>
<div>使用情况:{{panel.use}}</div>
</div>
</div>
</template>
<script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import {CSS3DRenderer, CSS3DObject} from "three/examples/jsm/renderers/CSS3DRenderer.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"
import { MeshBasicMaterial, TextureLoader } from 'three';
export default {
name: "ThreeTest",
data() {
return {
left:0,
top:0,
panel:{
name:"",
temp:"",
use:""
},
isShowPanel:false,
//纹理集合
maps:[],
// 机柜集合
cabinets:[],
//划入的当前机柜
curcabinet:null
};
},
mounted() {
// this.getData();
this.timer = null;
this.myReq = null;
this.container;
this.scene;
this.camera;
this.renderer;
this.labelRenderer;
this.controls;
this.initScene();
this.initCamera();
this.initRender();
this.initModel();
this.initControls();
this.initLight()
this.animate();
window.onresize = this.onWindowResize;
this.crtTexture("Cube-hover.png")
document.addEventListener('mousemove', this.onClick, false);
},
methods: {
onClick(event){
this.selectCabinet(event.clientX,event.clientY)
},
selectCabinet(x,y){
var raycaster = new THREE.Raycaster();
var pointer = new THREE.Vector2();
const {width,height} = this.renderer.domElement
console.log(width)
console.log(height)
// canvas 坐标转裁剪坐标
pointer.set((x/width)*2-1,-(y/height)*2 1)
raycaster.setFromCamera(pointer,this.camera)
console.log(this.cabinets)
// 选择机柜
const intersect = raycaster.intersectObjects(this.cabinets)[0]
let intersectObject = intersect?intersect.object:null
console.log(this.curcabinet)
console.log(intersectObject)
// 若之前已有机柜被选择,且不等于当前所选择的机柜,取消之前选择的机柜的高亮
if(this.curcabinet && this.curcabinet!=intersectObject){
const material = this.curcabinet.material
material.setValues({
map:this.getMapByName("Cube.png")
})
}
if(intersectObject){
this.onMouseMoveCabinet(x,y)
if(intersectObject != this.curcabinet){
this.curcabinet = intersectObject
const material = this.curcabinet.material
material.setValues({
map:this.getMapByName("Cube-hover.png")
})
this.onMouseOverCabinet(intersectObject)
}
}else if(this.curcabinet){
this.curcabinet = null
this.onMouseOutCabinet()
}
},
// 鼠标划入机柜的事件,参数为机柜对象
onMouseOverCabinet(){
this.isShowPanel = true
},
//在机柜上移动的事件,参数为坐标
onMouseMoveCabinet(x,y){
this.left= x
this.top= y
},
// 鼠标划出机柜的事件
onMouseOutCabinet(){
this.isShowPanel = false
},
pushMap(imageName,curTexture){
this.maps.push({name:imageName,map:curTexture})
},
getMapByName(name){
let rusult
for(let i=0;i<this.maps.length;i ){
if(this.maps[i].name == name){
rusult = this.maps[i].map
break
}
}
return rusult
},
initScene() {
this.scene = new THREE.Scene();
},
initCamera() {
this.container = document.getElementById("container");
this.camera = new THREE.PerspectiveCamera(
70,
this.container.clientWidth / this.container.clientHeight,
1,
1000
);
console.log(this.camera);
this.camera.position.z = 20; //z设置小写会使图像变形小
this.camera.position.y = 0
},
initRender: function () {
this.renderer = new THREE.WebGLRenderer({ antialias: true });
this.renderer.setSize(
this.container.clientWidth,
this.container.clientHeight
);
this.container.appendChild(this.renderer.domElement);
},
initLight() {
this.scene.add(new THREE.AmbientLight(0xb9e1fb));
this.light = new THREE.DirectionalLight(0xecfbb9,0.2);
this.light.position.set(0, 0, 50);
this.scene.add(this.light);
},
initModel() {
let loader = new GLTFLoader()
let gltScene
loader.load("models/clickTest/threebox.gltf",(gltf)=>{
for(let i=0;i<gltf.scene.children.length;i ){
console.log(gltf.scene.children[i])
let mesh = gltf.scene.children[i]
if(mesh.type == "Mesh"){
console.log(mesh)
const {map,color} = mesh.material
this.changeMat(mesh,map,color)
if(mesh.name.includes("Cube")){
this.cabinets.push(mesh)
}
// this.scene.add(mesh) 会有问题。Mesh减少
}
}
this.scene.add(...gltf.scene.children)
})
},
// 修改材质
changeMat(mesh,map,color){
let index = map.image.currentSrc.lastIndexOf("/")
let imageName = map.image.currentSrc.substring(index 1)
console.log(imageName)
if(map){
// this.maps.push({name:mesh.name,map:this.crtTexture(map.name)})
// console.log(this.maps)
mesh.material = new MeshBasicMaterial({
map:this.crtTexture(imageName)
// map:new THREE.TextureLoader().load("/models/clickTest/Cube.png")
})
}else{
mesh.material = new MeshBasicMaterial({color})
}
},
// 建立纹理对象
crtTexture(imgName){
let curTexture = this.getMapByName(imgName)
if(!curTexture){
curTexture = new THREE.TextureLoader().load(`/models/clickTest/${imgName}`)
curTexture.flipY = false
curTexture.wrapS = 1000
curTexture.wrapT = 1000
this.pushMap(imgName,curTexture)
}
return curTexture
},
initControls(){
this.controls = new OrbitControls( this.camera, this.renderer.domElement );
},
render() {
this.renderer.render(this.scene, this.camera);
// this.labelRenderer.render(this.scene, this.camera);
},
onWindowResize() {
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix();
this.render();
this.renderer.setSize(window.innerWidth, window.innerHeight);
this.labelRenderer.setSize(window.innerWidth, window.innerHeight);
},
animate() {
this.render();
this.myReq = requestAnimationFrame(this.animate);
},
},
beforeDestroy() {
cancelAnimationFrame(this.myReq);
clearInterval(this.timer);
this.scene = null;
// this.scene.dispose()
this.camera = null;
this.renderer = null;
this.labelRenderer = null;
this.controls = null;
},
watch: {},
filters: {},
};
</script>
<style scope>
/deep/.label {
color: #FFF;
font-family: sans-serif;
padding: 2px;
background: rgba( 0, 0, 0, .6 );
}
#panel{
position:absolute;
left:0;
top:0;
background: rgba( 0, 0, 0, .6 );
padding:10px;
}
</style>
代码语言:javascript复制threejs 中加载gltf模型 循环Mesh会减少,暂时使用整体加入this.scene.add(...gltf.scene.children)
curTexture = new THREE.TextureLoader().load("/models/clickTest/Cube-export.png")
curTexture.flipY = false
curTexture.wrapS = 1000
curTexture.wrapT = 1000
上面的3个参数不加贴图不准确,有偏移
blender导出是图片和gltf分别单独导出
材质通过setValues重新设置值
material.setValues({
map:this.getMapByName("Cube-hover.png")
})