效果展示:
在这里插入图片描述

1. 导入依赖

	import * as THREE from 'three'
    import {GLTFLoader} from 'three/examples/jsm/loaders/GLTFLoader';
    import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//props: {
//    websockData: Object, //父组件传递的websocketData
//},
data() {
    return {
        camera: null, //相机
        scene: null, //场景
        renderer: null, //渲染器
        container: null, //容器
        controls: null, //控制器
        sprites : [], //精灵、几何体、材质、贴图的集合,控制实时变化
    }
},

2.创建相机、场景、光源、渲染器、控制器

//创建相机
initCamera() {
    this.camera = new THREE.PerspectiveCamera(45, this.container.clientWidth / this.container.clientHeight, 0.1, 10000)
    this.camera.position.set(43, 11, 22); //相机位置
},
//创建场景
initScene() {
    this.scene = new THREE.Scene()
    this.scene.background = new THREE.Color("#c5ccec");
    this.scene.add(this.camera)
},
//光源
initLight() {
    //平行光,沿着特定方向发射的光
    const directionalLight1 = new THREE.DirectionalLight("#ccc", 1);
    directionalLight1.position.set(1, 1, 1);
    this.scene.add(directionalLight1);
    const directionalLight2 = new THREE.DirectionalLight("#ccc", 1);
    directionalLight2.position.set(-1, 0.5, -1);
    this.scene.add(directionalLight2);
    const directionalLight3 = new THREE.DirectionalLight("#ccc", 1);
    directionalLight3.position.set(-23, 1, 27);
    this.scene.add(directionalLight3);
    const directionalLight4 = new THREE.DirectionalLight("#ccc", 1);
    directionalLight4.position.set(24, 1, -24);
    this.scene.add(directionalLight4);
},
//渲染器
initRenderer() {
    this.container = document.getElementById('container')
    this.renderer = new THREE.WebGLRenderer({antialias: true, alpha: true});
    this.renderer.setPixelRatio(this.container.devicePixelRatio);
    this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
    this.container.appendChild(this.renderer.domElement)
},
//视图控制器
initControls() {
    this.controls = new OrbitControls(this.camera, this.renderer.domElement);
    //上下翻转的最大角度
    this.controls.maxPolarAngle = 1.5;
    //上下翻转的最小角度
    this.controls.minPolarAngle = 0.3;
    //是否允许缩放
    this.controls.enableZoom = true;
    //控制是否带有惯性
    this.controls.enableDamping = true
},

3.导入GLTF模型

//加载设备模型
initGLTF(item) {
	let that = this
	function onProgress(xhr) {
	    if (xhr.lengthComputable) {
	        const percentComplete = xhr.loaded / xhr.total * 100;
	        // ${Math.round(percentComplete, 2)}%  //加载进度
	    }
	}
	function onError() {}
	//导入模型
	new GLTFLoader().setPath('static/obj/').load(item + '.gltf', function (object) {
	    object.scene.position.x = 0;
	    object.scene.position.z = 0;
	    object.scene.name = item; //模型名称
	    object.scene.scale.set(0.1, 0.1, 0.1) //设置模型比例尺寸
	    object.scene.traverse(function (child) {
	        if (child.isMesh) {
	        	//给模型下的Mesh添加材质颜色
	            child.material = new THREE.MeshPhongMaterial({
	                color: child.material.color,
	                shininess: 100,
	                reflectivity: 0.5,
	                flatShading: false
	            })
	        }
	    });
	    //给模型内的Mesh集合加到全局
	    that.sprites = []
	    object.scene.children.forEach(child => {
           that.sprites.push({
               mesh: child,
               sprite: null,
               texture: null,
               spriteMaterial: null,
           })
         });
	    that.scene.add(object.scene);
	}, onProgress, onError);
}

4.在animate中实时显示Sprite

animate() {
	this.renderer.render(this.scene, this.camera);
	this.animateId = requestAnimationFrame(this.animate);
	//先清空精灵
	this.scene.children.forEach(child =>{
	    if(child.type === "Sprite"){
	        this.scene.remove(child);
	    }
	})
	this.sprites.forEach(item => {
	    if (item.sprite) { //注意加载前要把加载过的精灵销毁掉,释放内存
	        this.scene.remove(item.sprite)
	        this.scene.remove(item.texture)
	        this.scene.remove(item.spriteMaterial)
	    }
	    //绘制矩形
	    var canvas = document.createElement("canvas");
	    var context = canvas.getContext("2d");
	    //canvas 实体
	    context.fillStyle = "rgba(0,0,0,0.5)"; //填充带透明颜色
	    context.fillRect(0,0,600,200); //x,y,width,height
	    //canvas 边框
	    context.lineJoin = "round";
	    context.lineCap = 'round';
	    context.miterLimit = 0;
	    context.lineWidth = 5;  //borderWidth
	    context.strokeStyle = "#17fe6d";
	    context.strokeRect(0,0,300,150);
	    //canvas 文字
	    context.fillStyle = "#fff";
	    context.font = "24px bold Arial";
	    context.fillText(item.mesh.name, 30, 30);
	    context.fillStyle = "#fff";
	    context.font = "20px bold Arial";
	    context.fillText("websocket值:" + this.websockData['socketKey'], 30, 60);
	    item.texture = new THREE.Texture(canvas); //就是上面的canvas,将它写在一个函数中然后返回。
	    item.texture.needsUpdate = true;
	    item.spriteMaterial = new THREE.SpriteMaterial({map: item.texture});
	    item.sprite = new THREE.Sprite(item.spriteMaterial);
	    item.sprite.scale.set(2.5, 2.5, 2.5); //大小缩放
	    item.sprite.position.set(item.mesh.position.x / 10, (item.mesh.position.y + 40) / 10 + 4, item.mesh.position.z / 10); //位置
	    item.sprite.name = "标识图"
	    this.scene.add(item.sprite); //将其放入场景中
	})
},

5.获取websocket数据

initWebSocket() {
  //初始化weosocket
  // this.websock = new WebSocket('ws://' + location.host + '/socket');
  this.websock = new WebSocket("ws://192.168.2.9:5002/socket");
  this.websock.onmessage = this.websocketonmessage;
  this.websock.onopen = this.websocketonopen;
  this.websock.onerror = this.websocketonerror;
  this.websock.onclose = this.websocketclose;
},
websocketonmessage(e) {
    this.websockVarData = JSON.parse(e.data);
},
websocketonopen() {
    console.log("socket连接成功")
},
websocketonerror(){
    console.log("连接错误")
},
websocketsend(Data) {
    this.websock.send(Data);
},
websocketclose(e) {
    console.log("websocket关闭");
},
closesocket() {
    this.websock.close();
},

也可以在父组件调用,传递websockVarData值当前组件获取,数据也是实时的,不需要用watch监听值,在animate方法中是自动更新的

6.最后初始化方法

init() {
   this.initRenderer()
   this.initCamera()
   this.initScene()
   this.initLight()
   this.initGLTF("xx模型")
   this.initControls()
},
mounted() {
	this.initWebSocket()
    this.init()
    this.animate()
},
Logo

前往低代码交流专区

更多推荐