VUE使用轮播图画3D模型图

使用vue的组件和three.js画出3d模型图

直接上代码,有问题评论区联系吧,经常在线。qq:2277655147

<template>
  <div class="card text-center m-b-20">
    <div class="card-body text-muted" >
      <h4 class="mt-0 header-title" style="font-weight: bold;font-size: 20px; height: 40px;">{
    
    {
    
    equipmentTitle}}</h4>
      <div class="paramPanel" v-show="sensorModel.sphereModel">
        <el-row>
          <label>{
    
    {
    
    sensorModel.sensorName}}{
    
    {
    
    sensorModel.sensorValue}}</label>
        </el-row>
      </div>
      <el-carousel
              trigger="click"
              :autoplay="false"
              :height="modelHeight"
              arrow="always"
              @change="equipmentChange"
      >
        <el-carousel-item v-for="(item,index) in equipmentData" :key="index"  >
          <div ref="panel3d"  :style="'height: '+modelHeight"></div>
        </el-carousel-item>
      </el-carousel>
    </div>
  </div>
  <!--<div ref="panel3d"  style="height: 31vh;"></div>-->
</template>
<script>
    import * as THREE from 'three'
    import {
    
     OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
    import {
    
     STLLoader } from 'three/examples/jsm/loaders/STLLoader'
    import * as TWEEN from '../../../Tween.js';
    export default {
    
    
        // props:['pointsInfo','sensorModel','equipmentTitle','parentActiveName','parentMethod','styleHeight'],
        /*
         *equipmentData:3d模型所需要的标题和监测点数据
         * equipmentChangeParent:设备变化之后的方法
         * sensorChangeParent:传感器变化之后的方法
         * styleHeight:3d模型的高度
         * initHighLight:是否初始化高亮
         */
        props:['equipmentData','equipmentChangeParent','sensorChangeParent','styleHeight','initHighLight'],
        data() {
    
    
            let temp_height=this.styleHeight;
            if(!this.styleHeight){
    
    
                temp_height='35vh';
            }
            return{
    
    
                //3d图
                scene: null,
                camera: null,
                raycaster: null,
                renderer: null,
                controls: null,
                material: null,
                mesh: null,
                INTERSECTED: null,
                INTERSECTEDForcus: null,
                pointsInfo: [],
                points: null,
                pointShells: null,
                width: 0,
                height: 0,
                //固定模型
                modelInfo:{
    
    
                    path:'/big.STL',
                    position:{
    
    
                        x:108,
                        y:0,
                        z:-137,
                    },
                    rotation:'-90',
                    scale:'0.052',
                },
                //模型的高度
                modelHeight:temp_height,
                //轮播图第一个
                sensorModel:{
    
    
                    sphereModel:false,
                    sensorName:'',
                    sensorValue:'',
                },
                //变压器标题
                equipmentTitle:'',
                //所有监测点
                parentActiveName:'',
                //展示的第几个
                index:0,
                //所有的模型
                indexs:[]
            }
        },
        watch:{
    
    
            'equipmentTitle'(value){
    
    
                if(value==this.parentActiveName){
    
    
                    if(this.points){
    
    
                        if(!this.INTERSECTED){
    
    
                            this.sensorModel.sphereModel=false;
                            return false;
                        }
                        for(let i = 0; i < this.points.children.length; i++){
    
    
                            if(this.points.children[i] == this.INTERSECTED){
    
    
                                this.sensorModel.sphereModel=true;
                                this.sensorModel.sensorName=this.pointsInfo[i].sensorName;
                                this.sensorModel.sensorValue=this.pointsInfo[i].sensorValue;
                            }
                        }
                    }
                }
            },
        },
        created() {
    
    
            this.getData();
        },
        methods: {
    
    
            getData(){
    
    
                this.$nextTick(function() {
    
    
                    if(this.equipmentData[this.index]){
    
    
                        this.equipmentTitle=this.equipmentData[this.index].equipmentName;
                        this.init3DModel(this.index);
                        this.pointsInfo=this.equipmentData[this.index].sensor;
                    }
                    // this.equipmentData.forEach((value, index)=> {
    
    
                    // });


                    this.sphere();
                    if(this.initHighLight){
    
    
                        this.initMouseDown();
                    }

                });
            },
            initMouseDown(){
    
    
                if(this.points.children[this.index]){
    
    
                    let point= this.points.children[this.index];
                    this.INTERSECTED = point;
                    this.INTERSECTEDForcus = false;
                    this.highLight();
                }
            },
            init3DModel(index){
    
    
                this.width = this.$refs.panel3d[index].clientWidth;
                this.height = this.$refs.panel3d[index].clientHeight;
                //初始化场景
                this.scene = new THREE.Scene();
                this.scene.background = new THREE.Color( 0x1B4B9D );//0x006699
                this.scene.fog = new THREE.FogExp2( 0x006699, 0.0007 );
                //初始化相机配置
                this.camera = new THREE.PerspectiveCamera(70, this.width / this.height, 1, 10000);
                this.camera.position.set(600, 300, 0);
                let tempLookAt = this.scene.position;
                tempLookAt.y = -160;
                this.camera.lookAt(tempLookAt);
                this.raycaster = new THREE.Raycaster();
                //初始化渲染器
                this.renderer = new THREE.WebGLRenderer( {
    
     alpha: true } );
                this.renderer.setClearColor( 0x0000FF, 0 );
                this.renderer.setPixelRatio(window.devicePixelRatio);
                this.renderer.setSize(this.width, this.height);
                this.$refs.panel3d[index].appendChild(this.renderer.domElement);
                //光源
                let light = new THREE.AmbientLight(0x888888, 0.6);
                this.scene.add(light);
                let directionalLight = new THREE.DirectionalLight(0x888888, 1.1);
                directionalLight.position.set(300, 1000, 500);
                directionalLight.target.position.set(0, 0, 0);
                directionalLight.castShadow = true;
                let d = 300;
                directionalLight.shadow.camera = new THREE.OrthographicCamera(-d, d, d, -d, 500, 1600);
                directionalLight.shadow.bias = 0.0001;
                directionalLight.shadow.mapSize.width = directionalLight.shadow.mapSize.height = 1024;
                this.scene.add(directionalLight);

                directionalLight = new THREE.DirectionalLight(0x888888, 1.1);
                directionalLight.position.set(-300, -1000, -500);
                directionalLight.target.position.set(0, 0, 0);
                directionalLight.castShadow = true;
                d = 300;
                directionalLight.shadow.camera = new THREE.OrthographicCamera(-d, d, d, -d, 500, 1600);
                directionalLight.shadow.bias = 0.0001;
                directionalLight.shadow.mapSize.width = directionalLight.shadow.mapSize.height = 1024;
                this.scene.add(directionalLight);
                //网格
                var gridHelper = new THREE.GridHelper(600, 60);
                this.scene.add(gridHelper);
                //控制器
                this.controls = new OrbitControls(this.camera, this.renderer.domElement);
                this.controls.enableDamping = true;
                this.controls.dampingFactor = 0.25;
                this.controls.rotateSpeed = 0.35;
                //添加事件
                window.addEventListener('resize', this.onWindowResize, false);
                this.loop();
                //模型材质
                this.material = new THREE.MeshPhysicalMaterial({
    
    
                    color: 0xB0C4DE,
                    metalness: 0,
                    roughness: 0.5,
                    reflectivity: 0.5,
                    envMap: null
                });

                this.points = new THREE.Object3D();
                this.pointShells = new THREE.Object3D();
                let loader = new STLLoader();
                let _this = this;
                loader.load(_this.modelInfo.path, function(geometry) {
    
    
                    _this.mesh = new THREE.Mesh(geometry, _this.material);
                    _this.mesh.position.set(_this.modelInfo.position.x, _this.modelInfo.position.y, _this.modelInfo.position.z);
                    _this.mesh.scale.set(_this.modelInfo.scale, _this.modelInfo.scale, _this.modelInfo.scale);
                    _this.mesh.rotation.set(0, (_this.modelInfo.rotation / 180) * Math.PI, 0);
                    _this.mesh.castShadow = true;
                    _this.mesh.receiveShadow = true;
                    _this.mesh.name = 'model';
                    _this.scene.add(_this.mesh);
                    _this.renderer.domElement.addEventListener('mousedown', _this.onDocumentMouseDown, false);
                });
            },
            sphere(){
    
    
                if(this.scene && this.pointsInfo){
    
    
                    this.pointsInfo.forEach(info=>{
    
    
                        if(info.position){
    
    
                            var sphereGeo = new THREE.SphereGeometry(4, 8, 8);//创建球体
                            var sphereMat = new THREE.MeshLambertMaterial({
    
    //创建材料
                                color:0x00FF00,
                                wireframe:false
                            });
                            var sphereMesh = new THREE.Mesh(sphereGeo, sphereMat);//创建球体网格模型
                            sphereMesh.position.set(info.position.x,info.position.y,info.position.z);//设置球的坐标
                            sphereMesh.name = info.id;
                            this.points.add(sphereMesh);

                            var sphereMat = new THREE.MeshLambertMaterial({
    
    //创建材料
                                color:0x00FF00,
                                opacity: 0, transparent: true
                            });
                            var sphereGeo = new THREE.SphereGeometry(20, 20, 20);//创建球体
                            var sphereMesh = new THREE.Mesh(sphereGeo, sphereMat);//创建球体网格模型
                            sphereMesh.position.set(info.position.x,info.position.y,info.position.z);//设置球的坐标
                            sphereMesh.name = info.id;
                            this.pointShells.add(sphereMesh);
                        }
                    });
                    this.scene.add(this.points);
                    this.scene.add(this.pointShells);
                }
            },
            loop() {
    
    
                requestAnimationFrame(this.loop);
                TWEEN.update();
                this.render();
            },
            render(){
    
    
                if(this.renderer){
    
    
                    this.renderer.render(this.scene, this.camera);
                }
            },
            startTween(pointPosition, cameraPosition){
    
    
                var x = pointPosition.x;
                var newX = cameraPosition.x;
                var y = pointPosition.y;
                var newY = cameraPosition.y;
                var z = pointPosition.z;
                var newZ = cameraPosition.z;
                var _this = this;
                new TWEEN.Tween( this.camera.position )
                    .to( {
    
    
                        x: newX,
                        y: newY,
                        z: newZ
                    } )
                    .easing( TWEEN.Easing.Linear.None ).onUpdate( function () {
    
    
                    _this.camera.lookAt(pointPosition.x, pointPosition.y-160, pointPosition.z);
                    _this.controls.target.set(x, y-160, z);
                } )
                    .onComplete( function () {
    
    
                        _this.camera.lookAt(pointPosition.x, pointPosition.y-160, pointPosition.z);
                        _this.controls.update();
                    } )
                    .start();
            },
            highLight(){
    
    
                if(this.points){
    
    
                    for(let i = 0; i < this.points.children.length; i++){
    
    
                        this.points.children[i].material.emissive.setHex(0x000000);
                        if(this.points.children[i] == this.INTERSECTED){
    
    
                            this.points.children[i].material.emissive.setHex(0xff0000);//原来位绿色,加上红色为黄色
                            if(this.INTERSECTEDForcus == false){
    
    
                                this.startTween(this.points.children[i].position, this.pointsInfo[i].camera);
                                this.INTERSECTEDForcus = true;
                                this.sensorModel.sphereModel=true;
                                this.sensorModel.sensorName=this.pointsInfo[i].sensorName;
                                this.sensorModel.sensorValue=this.pointsInfo[i].sensorValue;
                                if(this.sensorChangeParent){
    
    
                                    this.sensorChangeParent(this.pointsInfo[i].code,this.equipmentData[this.index].code,this.pointsInfo[i].sensorAllValue);
                                }
                            }
                        }
                    }
                }
            },
            onDocumentMouseDown(event){
    
    
                let mouse = new THREE.Vector2();
                event.preventDefault();
                let tempRect = this.renderer.domElement.getBoundingClientRect();
                mouse.x = ((event.clientX-tempRect.left)/this.width) * 2 - 1;
                mouse.y = -((event.clientY-tempRect.top)/this.height) * 2 + 1;
                this.raycaster.setFromCamera(mouse, this.camera);
                let intersects = this.raycaster.intersectObjects(this.pointShells.children);
                if (intersects.length > 0) {
    
    
                    let point;
                    for(let i = 0; i < this.points.children.length; i++){
    
    
                        if(this.points.children[i].name == intersects[ 0 ].object.name){
    
    
                            point = this.points.children[i];
                        }
                    }
                    if(intersects.length > 0 && this.INTERSECTED != point) {
    
    
                        this.INTERSECTED = point;
                        this.INTERSECTEDForcus = false;
                        this.highLight();
                    }
                    //失去焦点的时候
                    else if(intersects.length > 0 && this.INTERSECTED == point){
    
    
                        //取消焦点和位置数据
                        this.INTERSECTED = null;
                        this.INTERSECTEDForcus = false;
                        //改变颜色
                        this.highLight();
                        // //设置摄像头的位置
                        this.camera.position.set(400, 300, 0);
                        // //设置查看的位置
                        let tempLookAt = this.scene.position;
                        tempLookAt.y = -160;
                        this.camera.lookAt(tempLookAt);
                        //取消注释
                        this.sensorModel.sphereModel=false;

                    }
                }

            },
            onWindowResize(){
    
    
                if(!this.$refs.panel3d[this.index]){
    
    
                    return false;
                }
                this.width = this.$refs.panel3d[this.index].clientWidth;
                this.height = this.$refs.panel3d[this.index].clientHeight;
                this.camera.aspect = this.width / this.height;
                this.camera.updateProjectionMatrix();
                this.renderer.setSize(this.width, this.height);
            },
            equipmentChange(newIndex,oldIndex){
    
    
                this.index=newIndex;
                //延时清除一下旧的canvas,
                setTimeout(function (){
    
    
                    document.getElementsByTagName('canvas')[oldIndex].remove();
                },600);
                //标题
                this.equipmentTitle=this.equipmentData[newIndex].equipmentName;
                //监测点信息
                this.pointsInfo=this.equipmentData[newIndex].sensor;
                //场景
                this.init3DModel(newIndex);
                //球
                this.sphere();
                //对应当前选中的值清除一下
                this.sensorModel.sphereModel=false;
                //父类方法调用
                if(this.equipmentChangeParent){
    
    
                    this.equipmentChangeParent(this.equipmentData[newIndex].code,this.equipmentData[newIndex]);
                }
            },
        }
    };
</script>

猜你喜欢

转载自blog.csdn.net/baby_dewo/article/details/111316961