前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >threejs记录选中变化纹理

threejs记录选中变化纹理

作者头像
tianyawhl
发布2023-12-11 09:45:20
1760
发布2023-12-11 09:45:20
举报
文章被收录于专栏:前端之攻略
代码语言: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")
})
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-12-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档