vue2引入threejs

添加threejs

npm install three --save-dev

如果你需要three.js的其他版本,使用

npm show three versions

来确认哪些是可用的。要让npm使用正确的版本,执行如:

npm install three@0.84.0 --save

npm 安装模块
【npm install xxx】安装但不写入package.json;
【npm install -g xxx】利用npm安装全局模块xxx;
【npm install xxx --save】 安装并写入package.json的"dependencies"中;
【npm install xxx --save-dev】安装并写入package.json的"devDependencies"中。

npm 删除模块
【npm uninstall xxx】删除xxx模块;
【npm uninstall -g xxx】删除全局模块xxx;

FPS指示器

npm install stats.js --save

引用

<template>
    <div>
   <div id="container" style=" width: 100%; " :style="{ height: (h + 'px') }"></div>
    </div>
</template>

<script>
//引入three包  最新版
import * as THREE from "three";
const windowHeight = window.innerHeight || document.body.clientHeight
export default {
  data() {
    return {
      //一般的全景图分为两种,一种是由六张正方形的图组成,一种是由一张宽2高1的图
      bigImg: require("../assets/img/earth.jpeg"), //全景图图片路径 这个是长与高2:1的图

      satellites: [], //卫星(数组)
      container: null, // dom节点
   
  
    
    };
  },
  mounted() {
    this.scene = null; // 场景
    this.renderer = null; // 渲染器
    this.camera = null; // 相机
    this.mesh = null; //网格模型对象Mesh
    this.init(); //初始的方法都放在init
    this.animate();
  },
  //销毁页面
  destroyed: function () {
    this.scene = null; // 场景
    this.renderer = null; // 渲染器
    this.camera = null; // 相机
    this.mesh = null; //网格模型对象Mesh
  },
computed:{
		
			h(){
				return windowHeight - 64 - 44 - 20
			},
		
		},
  methods: {
   
   

    //初始化
    init: function () {
      this.container = document.getElementById("container"); //获取dom元素
      //创建场景对象Scene
      this.scene = new THREE.Scene();

      let geometry = new THREE.SphereGeometry(20, 30, 30); ///创建一个立方体几何对象Geometry
      //对球形几何网格进行x轴反转,使所有的面点向内,否则就是朝外
      //geometry.scale(-1, 1, 1);
      //纹理贴图  首先,把图片加载进来
      var texture = new THREE.TextureLoader().load(this.bigImg); //加载纹理贴图
      //创建材质,加入map
      let sphereMaterial = new THREE.MeshBasicMaterial({ map: texture });
      this.mesh = new THREE.Mesh(geometry, sphereMaterial); //网格模型对象Mesh
      //给物体取个名称 后面好控制物体的动画
      this.mesh.name = "box";
      this.mesh.position.set(0, 0, 20); //设置偏移  地球偏移
      this.scene.add(this.mesh); //网格模型添加到场景中

      //添加光源
      var satellite = new THREE.Sprite(
        new THREE.SpriteMaterial({
          map: new THREE.CanvasTexture(this.generateSprite("70,134,216")),
          blending: THREE.AdditiveBlending,
        })
      );
      satellite.scale.x = satellite.scale.y = satellite.scale.z = 80; //发光的范围
      satellite.position.set(0, 0, 20); //设置发光位置
      this.scene.add(satellite); //添加发光,让地球有发光的样式

      //创建相机对象
      //20摄像机看到的角度 1 相机看到的最近距离  1000相机看到的最远距离  剩下的就是长宽比
      this.camera = new THREE.PerspectiveCamera(
        20,
        this.container.clientWidth / this.container.clientHeight,
        1,
        1000
      );
      this.camera.position.set(0, 0, 400); //设置相机位置
      this.camera.lookAt(this.scene.position); //设置相机方向(指向的场景对象)
      //取消锯齿antialias:true
      this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
      this.renderer.setSize(
        this.container.clientWidth,
        this.container.clientHeight
      ); //设置渲染区域尺寸
      this.renderer.setClearColor(0xffffff, 0.5); //设置渲染器的初始颜色 背景颜色
      this.container.appendChild(this.renderer.domElement); //body元素中插入canvas对象

      //添加卫星
      this.satellites.push(  this.initSatellite( 10, 48, { x: -Math.PI * 0.35, y: Math.PI * 0.25, z: 0 }, 0.021, this.scene,'180,0,216' )  );
	  this.satellites.push( this.initSatellite( 60, 145,  { x: -Math.PI * 0.35, y: -Math.PI * 0.2, z: 0 }, 0.012, this.scene,'31,0,191' ) );
      this.satellites.push( this.initSatellite( 45, 125,  { x: -Math.PI * 0.35, y: -Math.PI * 0.1, z: 0 }, 0.022, this.scene,'28,21,57' ) );
      this.satellites.push( this.initSatellite( 15, 49, { x: -Math.PI * 0.35, y: Math.PI * 0.05, z: 0 }, 0.023, this.scene ,'0,144,198')  );
      this.satellites.push( this.initSatellite( 25,  69, { x: -Math.PI * 0.35, y: Math.PI * 0.3, z: 0 }, 0.026, this.scene ,'167,80,0') );
      this.satellites.push( this.initSatellite( 50, 130, { x: -Math.PI * 0.35, y: Math.PI * 0.15, z: 0 }, 0.016, this.scene  ,'201,0,5') );

      //监听窗口的变化
      window.addEventListener("resize", () => this.onWindowResize());
    },
    //动画
    animate() {
      let box = this.scene.getObjectByName("box"); //获取物体的名字 就可以控制不同的物体动画了

      this.renderer.render(this.scene, this.camera); //执行渲染操作
      box.rotateY(0.01); //每次绕y轴旋转0.01弧度

      for (var i = 0; i < this.satellites.length; i++) {
        this.satellites[i].satellite.rotation.z -= this.satellites[i].speed;
      }

      requestAnimationFrame(this.animate); //动画效果
    },
    //监听窗口的大小变化  还有相机的比例
    onWindowResize() {
      this.camera.aspect =
        this.container.clientWidth / this.container.clientHeight;
      this.camera.updateProjectionMatrix();
      this.renderer.setSize(
        this.container.clientWidth,
        this.container.clientHeight
      );
    },
    /**
     * 返回一个卫星和轨道的组合体
     * satelliteSize 卫星的大小
     * satelliteRadius 卫星的旋转半径
     *  rotation 组合体的x,y,z三个方向的旋转角度
     *  speed 卫星运动速度
     *  scene 场景
     *  {{satellite: THREE.Mesh, speed: *}} 卫星组合对象;速度
     */

    initSatellite(satelliteSize, satelliteRadius, rotation, speed, scene,color="234,0,5") {
      //轨道的大小颜色  轨道的颜色
      var track = new THREE.Mesh(
        new THREE.RingGeometry(satelliteRadius, satelliteRadius + 0.05, 50, 1),
        new THREE.MeshBasicMaterial({ color: "#d38518" })
      );
      var centerMesh = new THREE.Mesh(
        new THREE.SphereGeometry(1, 1, 1),
        new THREE.MeshLambertMaterial({
          color: 0xffff00,
          side: THREE.DoubleSide,
        })
      ); //材质设定
      var satellite = new THREE.Sprite(
        new THREE.SpriteMaterial({
          map: new THREE.CanvasTexture(this.generateSprite(color)), //发光的颜色
          blending: THREE.AdditiveBlending,
        })
      );
      satellite.scale.x = satellite.scale.y = satellite.scale.z = satelliteSize;
      satellite.position.set(satelliteRadius, 0, 0);

      var pivotPoint = new THREE.Object3D();
      pivotPoint.add(satellite);
      pivotPoint.add(track);
      centerMesh.add(pivotPoint);
      centerMesh.position.set(0, 0, 20); //设置旋转中心
      centerMesh.rotation.set(rotation.x, rotation.y, rotation.z);
      scene.add(centerMesh);
      return { satellite: centerMesh, speed: speed };
    },

    /**
     * 实现发光星星
     *color 颜色的r,g和b值,比如:“123,123,123”;
     *  {Element} 返回canvas对象
     */
    generateSprite(color) {
      var canvas = document.createElement("canvas");
      canvas.width = 16; //发光的范围
      canvas.height = 16;
      var context = canvas.getContext("2d");
      var gradient = context.createRadialGradient(
        canvas.width / 2,
        canvas.height / 2,
        0,
        canvas.width / 2,
        canvas.height / 2,
        canvas.width / 2
      );
      gradient.addColorStop(0, "rgba(" + color + ",1)"); //发光的颜色和透明度
      gradient.addColorStop(0.2, "rgba(" + color + ",1)");
      gradient.addColorStop(0.4, "rgba(" + color + ",.6)");  //.6
      gradient.addColorStop(1, "rgba(0,0,0,0)");
      context.fillStyle = gradient;
      context.fillRect(0, 0, canvas.width, canvas.height);
      return canvas;
    },
  },
};
</script>

引入外部3D模型 格式gltf

npm install gsap
npm install vue-count-to -D
npm install vue-seamless-scroll --save
<template>
	<div>
		<div style="display: flex;justify-content: space-between;">
			<div style="z-index: 13;width: 240px;height: 100px;background-color: #49944c;display: flex;align-items: center;padding: 10px;border-radius: 4px;">
				<span style="color: #FFFFFF;">总数:</span>
				 <countTo :startVal='startVal' :endVal='endVal' :duration='3000' separator=',' style="color: #fff;font-size: 36px;"></countTo>
			</div>
			<div style="z-index: 13;width: 400px;height: 120px;background-color: #49944c;overflow: hidden;padding: 0 10px;border-radius: 4px;">
			
			           <table cellspacing="0" cellpadding="0" width="100%" style="table-layout: fixed;word-wrap:break-word;">
			                  <tr
			                    style="border: 1px dashed #ffffff;color: #fff;"
			                 >
			                    <td width="90"  class="tab_title">时间</td>
			                    <td width="80"  class="tab_title">用户</td>
			                    <td width="50"  class="tab_title">姓名</td>
			                    
			                    <td  class="tab_title">操作</td>
			                  </tr>
			                </table>
			            <vue-seamless-scroll :data="listData" class="seamless-warp" :class-option="defaultOption" >
			                <table cellspacing="0" cellpadding="0" width="100%" style="table-layout: fixed;word-wrap:break-word;">
			                  <tr
			                    v-for="(item, index) in listData"
			                    :key="index"
			                    style="border: 1px dashed #ffffff;color: #fff;"
			                  >
			                    <td width="90"  class="tab_title">{{ item.time }}</td>
			                    <td width="80"  class="tab_title">{{ item.number }}</td>
			                    <td width="50"  class="tab_title">{{ item.name }}</td>
			                    <td   class="tab_title" :title="item.kind">{{ item.kind }}</td>
			                  </tr>
			                </table>
			            </vue-seamless-scroll>
			     
			     </div>
			<div id="main" style="width: 300px;height: 120px;z-index: 13;background-color: #49944c;border-radius: 4px;"></div>
		</div>
		
		<div id="container" style="width:100%;height:100%;z-index: 11;position: absolute;right: 0;bottom: 0;top: 0;left: 0;"></div>
		<div v-if="loadedData!=100" style="position: absolute;z-index: 14;top: 0;left: 0;right: 0;bottom: 0;background-color: #00243d;display: flex;align-items: center;justify-content: center;" >
			<div style="width: 300px;">
				<el-progress :format="format(loadedData)" :percentage="loadedData" status="warning"  :text-inside="true" :stroke-width="22"></el-progress>
			</div>
		</div>
	</div>

 
</template>
<script>
	
	import gsap from "gsap";
	import vueSeamlessScroll from 'vue-seamless-scroll'
	 //引入three包  最新版
	import * as THREE from 'three'
	//鼠标控制器  需要threejs高版本
	import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
	//引入模型加载器
	import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
	//解压
	import { DRACOLoader  } from 'three/examples/jsm/loaders/DRACOLoader.js'
	import { CSS2DObject, CSS2DRenderer } from "three/examples/jsm/renderers/CSS2DRenderer.js";
	const echarts = require('echarts');
  import countTo from 'vue-count-to';
  export default {
    components: { countTo ,vueSeamlessScroll},
    data () {
      return {
		time:null,
        startVal: 0,
        endVal: 2020,
		loadedData:0,
		labelRenderer:null,//标签标题
		container : null, // dom节点
		clock:new THREE.Clock(),//时间
		listData: [
		                  {
		                    number:'1212',
		                    name:'xiaoming',
		                     kind:'12213',
		                  
		                    time:'2022-01-03',
		                  },
		                {
		                    number:'4545',
		                    name:'xiaohuan',
		                     kind:'432423',
		                 
		                    time:'2022-01-04',
		                  },
				 ]
      }
    },
	  // 监听属性 类似于data概念
	        computed: {
	            defaultOption () {
	                return {
	                    step: 0.2, // 数值越大速度滚动越快
	                    limitMoveNum: 2, // 开始无缝滚动的数据量 this.dataList.length
	                    hoverStop: true, // 是否开启鼠标悬停stop
	                    direction: 1, // 0向下 1向上 2向左 3向右
	                    openWatch: true, // 开启数据实时监控刷新dom
	                    singleHeight: 0, // 单步运动停止的高度(默认值0是无缝不停止的滚动) direction => 0/1
	                    singleWidth: 0, // 单步运动停止的宽度(默认值0是无缝不停止的滚动) direction => 2/3
	                    waitTime: 1000 // 单步运动停止的时间(默认值1000ms)
	                }
	            }
	 
	        },
	mounted () {
		this.scene = null  // 场景
		this.renderer = null // 渲染器
		this.camera = null // 相机
		this.model = null  // 场景
		this.light = null // 渲染器
		
		this.controls= null // 控制器
		
		this.init() //初始的方法都放在init
		this.loadGltf()
		this.animate()	
		this.drawLine();	
	},
	created(){
	    this.setout()
	},

	destroyed: function () {
	            this.scene = null  // 场景
	            this.renderer = null // 渲染器
	            this.camera = null // 相机
	            this.model = null  // 场景
	            this.light = null // 渲染器
	         
				this.controls= null // 控制器
				clearInterval(this.time); //清除计时器
				this.time = null; //设置为null
	        },
	methods: {
		
		format(percentage) {
				return () => {
				             return percentage!=100 ? '正在加载...'+percentage+'%' : percentage+'%'
				    	}
		      },
		setout(){
			// 计时器正在进行中,退出函数
			if (this.time != null) {
			  return;
			}
			// 计时器为空,操作
			//需要加定时器 DOM没有那么快加载出来
			this.time=setInterval(()=>{								
					let myChart = echarts.init(document.getElementById('main'));
					myChart.clear()//清除画布
					this.drawLine()																	
			},6000)
		},
		 drawLine () {
		     
		     let myChart = echarts.init(document.getElementById('main'));
		     myChart.setOption({
		      
		       title: {
		           text: '',
		           left: 'center',
		           top: '0%',
		           textStyle: {
		               fontSize: 12,
		               color: '#d5bb24',
		               fontWeight: 'normal'
		           }
		       },
		       // legend:{
		       // 	left:'center',
		       // 	icon:'pin',
		       // 	top:'10%',
		       // 	textStyle:{
		       // 		color:'#eaeaea'
		       // 	}
		       // },
		       tooltip: {
		     				trigger:'axis',
		     				axisPointer:{
		     					type:'line'
		     				}
		     			},
		     			
		     			grid: {
		     				top:'20%',
		     			    left: '20%',
		     				right: '6%',
		     				bottom:'24%'
		     			},
		     			
		       xAxis: {
		         data: ['1/1','1/2','1/3','1/4','1/5 ','1/6','1/7 '],
		     			  axisLine: {
		     			             lineStyle: {
		     			                 color: 'rgba(255,255,255,0.12)'
		     			             }
		     			         },
		     			         axisLabel: {
		     			             margin: 10,
		     			             color: '#d6d6d6',
		     						  interval: 0,
		     						 //  rotate:90,
		     			             textStyle: {
		     			                 fontSize: 10
		     			             },
		     			         },
		       },
		       yAxis:[  {
		     				  		type:'value',
		     						
		     				  		//name:'次数',
		     				  		splitLine: {
		     				  		    show: true,
		     				  		    lineStyle: {
		     				  		        color: '#00BFF3',
		     				  		        opacity:0.23
		     				  		    }
		     				  		},
		     						scale: true, //只显示有数据的那段
		     						 nameTextStyle:{
		     							color:'#ffffff' ,
		     							
		     						 },
		     				  		axisLabel:{
		     				  			formatter:'{value}',
		     				  			show: true,
		     				  			margin: 20,
		     				  			textStyle: {
		     				  			    color: '#ebebeb',
		     				  								   
		     				  			},
		     				  		}
		     				  	}],
		       series: [{
		           name: '次数',
		           type: 'line',
		     		smooth: true,
		           data: [0,20,34,60,120,180,200,200,200,200,200,200],
		     				itemStyle: {
		     				            normal: {
		     				                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
		     				                    offset: 0,
		     				                    color: 'rgba(91, 221, 217, 1.0)' // 0% 处的颜色
		     				                }, {
		     				                    offset: 1,
		     				                    color: 'rgba(165, 103, 218, 1.0)' // 100% 处的颜色
		     				                }], false),
		     				                barBorderRadius: [30, 30, 30, 30],
		     				                shadowColor: 'rgba(0,160,221,1)',
		     				                shadowBlur: 0,
		     				            }
		     				        },
		     				label:{
		     					normal:{
		     						show:true,
		     						formatter:function(params){
		     							return params.value
		     						},
		     						position:'top',
		     						fontSize:10,
		     						color:'#f1f1f1'
		     					}
		     				}
		       }]
		     });
		    },
			// 声明一个方法传入参数可以在不同的地方调用相机
			cameraReset(position, lookAt, time = 1){
				gsap.to(this.camera.position, {
				        x: position.x,
				        y: position.y,
				        z: position.z,
				        duration: time,
				        ease: "power4.out",
				       // onComplete: function () {
				         // 这是相机运动完成的回调,可以执行其他的方法.
				       // }
				    });
				    gsap.to(this.camera.lookAt, {
				        x: lookAt.x,
				        y: lookAt.y,
				        z: lookAt.z,
				        duration: time,
				        ease: "power4.out",
				    });
					//控制器
				    gsap.to(this.controls.target, {
				        x: lookAt.x,
				        y: lookAt.y,
				        z: lookAt.z,
				        duration: time,
				        ease: "power4.out",
				    });
			},
			// 声明一个方法传入参数可以在不同的地方位移
			objReset(obj,x,y,z, time = 1){
			
				//时间线可以用来排列动画的播放顺序
				let tl = gsap.timeline({repeat:-1});
				tl.to(obj.position, {
				        x:0,
				        y: -34,
				        z: 0,
				        duration: time
				    },">-0.1")
					.to(obj.rotation, {
					   
					    z: -Math.PI/2,
					   
					    duration: 0.1
					},">-0.1")
					.to(obj.position, {
				        x: -15.5,
				        y: -34,
				        z: 0,
				        duration: 3
				    },">-0.1")
					.to(obj.rotation, {
					   
					    z: -Math.PI,
					   
					    duration: 0.1
					},">-0.1")
					.to(obj.position, {
				        x: -15.5,
				        y: 0,
				        z: 0,
				        duration: time
				    },">-0.1")
					.to(obj.rotation, {
					   
					    z: Math.PI/2,
					   
					    duration: 0.1
					},">-0.1")
					.to(obj.position, {
				        x: 0,
				        y: 0,
				        z: 0,
				        duration: 3
				    },">-0.1")
				
			},
		 //初始化
		   init() {
						this.container = document.getElementById('container');//获取dom元素
		              this.scene = new THREE.Scene();
		              //this.scene.background = new THREE.Color(0xcccccc);
		              this.camera = new THREE.PerspectiveCamera(60,this.container.clientWidth/this.container.clientHeight,1,5000);
		              this.camera.position.set(30,30,30);  //定位相机
					  this.camera.lookAt(0,0,0);  //看向哪里
						//消除锯齿{antialias: true} 透明背景alpha: true
		              this.renderer = new THREE.WebGLRenderer({antialias: true,alpha: true});
		              this.renderer.setSize(this.container.clientWidth,this.container.clientHeight);
		               //半球光  光源直接放置于场景之上,光照颜色从天空光线颜色颜色渐变到地面光线颜色。
					 //参数: 天空中发出光线的颜色  地面发出光线的颜色  光照强度
					  let  hemiLight = new THREE.HemisphereLight(0xffffff, 0xdddddd, 1);
					 this.scene.add(hemiLight);
					   //聚光灯
						 this.light = new THREE.SpotLight(0xdddddd,2);
						   this.light.position.set(20,20,20);
						   this.light.castShadow = true;//此属性设置为 true 聚光灯将投射阴影
						   this.light.shadow.bias = -0.0001;
						   //设置阴影分辨率  调整阴影的分辨率来消除马赛克样式的阴影
						   this.light.shadow.mapSize.width = 1024*4;
						   this.light.shadow.mapSize.height = 1024*4;
						   this.scene.add( this.light );
		              this.container.appendChild(this.renderer.domElement);
					  
					  //标签渲染器
						this.labelRenderer=new CSS2DRenderer();
						this.labelRenderer.setSize(this.container.clientWidth,this.container.clientHeight)
						this.labelRenderer.domElement.style.position='absolute';
						this.labelRenderer.domElement.style.top='0px';
						//添加此属性会使标签上的交互无法点击  如果不添加会屏蔽点击事件
						this.labelRenderer.domElement.style.pointerEvents = 'none';
						this.container.appendChild(this.labelRenderer.domElement)
		              //创建controls对象 控制器  摄像机 渲染到那个元素上
		            this.controls=new OrbitControls(this.camera,this.renderer.domElement)
					
					     this.controls.target = new THREE.Vector3(0, 0, 0);
					      // 使动画循环使用时阻尼或自转 意思是否有惯性
					     this.controls.enableDamping = false;
					      // 动态阻尼系数 就是鼠标拖拽旋转灵敏度
					      this.controls.dampingFactor = 0.04;
					      // 是否可以旋转
					     this.controls.enableRotate = false;
					      // 是否可以缩放与速度
					      this.controls.enableZoom = false;
					      // 设置相机距离原点的最进距离
					     this.controls.minDistance = 1;
					      // 设置相机距离原点的最远距离
					     this.controls.maxDistance = 2000;
					      // 是否开启右键拖拽
					     this.controls.enablePan = true;
					//监听控制器的鼠标事件,执行渲染内容
					this.controls.addEventListener('change',()=>{
					  this.renderer.render(this.scene,this.camera);
					})
			   //监听窗口的变化
				  window.addEventListener('resize',()=>this.onWindowResize());
				  
				   //监听鼠标的点击事件
				   this.renderer.domElement.addEventListener('click',event=>{
					 const { offsetX,offsetY} =event
					 // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
					
					const x = ( offsetX / this.container.clientWidth ) * 2 - 1;
					const y = - ( offsetY / this.container.clientHeight ) * 2 + 1;
					//创建2D的坐标
					 const mousePoint=new THREE.Vector2(x,y)
					//这个类用于进行raycasting(光线投射)光线投射用于进行鼠标拾取(在三维空间中计算出鼠标移过了什么物体)
					 const raycaster =new THREE.Raycaster()
					 // 通过摄像机和鼠标位置更新射线
					 raycaster.setFromCamera(mousePoint,this.camera)
					 // 计算物体和射线的焦点
					 const intersects= raycaster.intersectObjects(this.scene.children,true)
					
					
					 //筛选 不点击网格  [0] 只取离鼠标最近的那个 instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
					 const  intersect=intersects.filter(intersect=>!(intersect.object instanceof THREE.GridHelper) && intersect.object.name !== 'plane' && !(intersect.object instanceof THREE.AxesHelper))[0]
					//判断是否有点击的东西
					if(intersect && this.isClickSoldier(intersect.object,'node_Lo-_01_-22946')){
					   
						//this.objReset(intersect.object,0,0,0 ,6)
						console.log(intersect.object)
					}
				   
				   })	  
			 },
			   //递归点击模型  使用递归判断
			         isClickSoldier(object,name){
			             if(object.name===name){
			               return object;
			             }else if(object.parent){
			               return this.isClickSoldier(object.parent)
			             }else{
			               return null;
			             }
			         },
				  //监听窗口的大小变化  还有相机的比例
				 onWindowResize(){
					  this.camera.aspect=this.container.clientWidth/this.container.clientHeight;
					 this.camera.updateProjectionMatrix();
					 this.renderer.setSize(this.container.clientWidth,this.container.clientHeight)  
					 this.labelRenderer.setSize(this.container.clientWidth,this.container.clientHeight)  
				 },
				   //递归实现
				   //@leafName  查找的name,
				   //@nodes   原始Json数据
				   //@path    供递归使用
				  findPathByLeafId(leafName, nodes,path){
				     if(path === undefined) {
				             path = {};
				           }
				        for(let i = 0; i < nodes.length; i++) {
				            let tmpPath= path;
				          //   tmpPath.push(nodes[i].id);
				            if(leafName == nodes[i].name) {
				              tmpPath=nodes[i];
				              return tmpPath;
				            }
				            if(nodes[i].children) {
				              let findResult = this.findPathByLeafId(leafName, nodes[i].children,tmpPath);
				              if(findResult) {
				                return findResult;
				              }
				            }
				        }
				  },
		          // 外部模型加载函数
		            loadGltf(){
			
		                //加载模型
		               let loader =new GLTFLoader();
					   let dracoLoader = new DRACOLoader();  //解压
					   dracoLoader.setDecoderPath( 'draco/gltf/' );//设置解压库文件路径
					   dracoLoader.setDecoderConfig({type: 'js'})  //使用js方式解压
					   dracoLoader.preload()  //初始化_initDecoder 解码器
					   loader.setDRACOLoader(dracoLoader)   //gltfloader使用dracoLoader
		              //这里一点要注意目录结构  这里的只能加载静态文件里的
		                loader.load('test/model.glb',(gltf)=>{  //放入压缩的文件glb
						//写一个递归找到对象
						let chend=this.findPathByLeafId('node_Lo-_01_-22946',gltf.scene.children)
						if(chend!==undefined){
							this.objReset(chend,0,0,0 ,6)
							//创建地球标签
							let earthDiv=document.createElement('div');
							earthDiv.className='label';
							earthDiv.textContent='扫地车:发货看得开范德萨夸大事实';
						
							let earthLable=new CSS2DObject(earthDiv)
							//设置位置
							earthLable.position.set(0,0,-6)
							chend.add(earthLable)
						}
						
						
		               // console.log(gltf.scene)  //打印这个找到动画的属性 名称 name 命名
		                this.model=gltf.scene //获取模型对象
						//设置模型位置
					   this.model.position.set(0,0,10);
		                if(this.scene)     this.scene.add(this.model)
						// 首页进入相机的视角,这个视角可以在三维模型中建立一个摄像机获取摄像机的坐标,如C4D,非常准确.
						    const cameraPosition = {
						      x: 20,
						      y: 20,
						      z: 20,
						    };
						    const cameraLookat = {
						      x: 10,
						      y: 0,
						      z: 0,
						    };
						// 模型加载完,进行相机的初始化,传入设置的参数,模型加载为异步
						   if(this.scene)  this.cameraReset(cameraPosition, cameraLookat,10);
		                },( xhr )=> {
							this.loadedData=0
							//console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
							//进度条 进度		
							this.loadedData = Math.floor(xhr.loaded/xhr.total*100)
						}, ( error )=> {
							console.log( 'An error happened' );
						})
		            },
		        //动画
		          animate() {
					  const delta = this.clock.getDelta();
					  //模型旋转动画
				   // if ( this.model ) this.model.rotation.y -= 0.04 * delta;
					if(this.renderer){
						 this.renderer.render( this.scene, this.camera);
						 this.labelRenderer.render(this.scene,this.camera)
					}      
		            requestAnimationFrame( this.animate);
		         },
	}
  }
</script>
<style>
 .seamless-warp {
             overflow: hidden;
          }
	/*  //溢出内容隐藏 //强制文本在一行内显示 //当对象内文本溢出时显示省略标*/
  .tab_title{
	overflow: hidden;  
	white-space: nowrap;  
	text-overflow: ellipsis; 
	font-size: 10px;
  }
   .label{
             color:#ffffff;
             font-size:10px;
			 padding: 2px;
			 opacity: 0.8;
			 width: 80px;
			 overflow: hidden;
			 text-overflow: ellipsis; 
			 border-radius: 2px;
			 background-color: #0187E6;
         }
</style>
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

时光浅止

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值