threejs 实现模型拖拽功能

9 篇文章 1 订阅

导入相关插件

import {
		DragControls
	} from "three/examples/jsm/controls/DragControls"; //拖拽控件
	import {
		TransformControls
	} from "three/examples/jsm/controls/TransformControls"; //可视化平移控件

代码

objects 为存储移动的mesh模型。

<template>
	<div id="myThree" ref="myThreeRef">

	</div>

</template>

<script>
	import * as THREE from "three"; //引入Threejs
	// import Detector from '@/utilTree/Detector.js';
	import {
		OrbitControls
	} from 'three/examples/jsm/controls/OrbitControls'; //控制器
	import {
		TrackballControls
	} from 'three/examples/jsm/controls/TrackballControls'; //轨迹球
	import {
		OBJLoader
	} from 'three/examples/jsm/loaders/OBJLoader'; //引入obj模型加载库OBJLoader.js
	import {
		MTLLoader
	} from 'three/examples/jsm/loaders/MTLLoader'; //引入mtl模型加载库MTLLoader.js
	const ThreeBSP = require('../assets/js/jthreebsp.js')(THREE)
	import Detector from '@/assets/js/Detector.js'
	import {
		DragControls
	} from "three/examples/jsm/controls/DragControls"; //拖拽控件
	import {
		TransformControls
	} from "three/examples/jsm/controls/TransformControls"; //可视化平移控件

	export default {
		data() {
			return {
				VIEW_ANGLE: 70,
				ASPECT: 0,
				NEAR: 1,
				FAR: 20000,
				SCREEN_WIDTH: 0,
				SCREEN_HEIGHT: 0,
				doorOpen: false,
				grouwalcloneOpen: false
				// Detector: Detector

			}
		},
		created() {},
		mounted() {
			this.scene = null;
			this.camera = null
			this.renderer = null;
			this.controls = null;
			this.group = null;
			this.groupWal = null;
			this.grouwalclone = null;
			this.groupStairs = null; //楼梯的数据
			this.getThreewidthOrHeigth(); //获取渲染所需的数据
			this.init(); //准备阶段
			this.animate();

		},
		beforeDestroy() {
			// 销毁
			// this.scene = null;
			// this.camera = null
			// this.renderer = null;
			// this.controls = null;
			// this.group = null;
		},
		methods: {
			getThreewidthOrHeigth() {
				this.SCREEN_WIDTH = this.$refs.myThreeRef.clientWidth;
				this.SCREEN_HEIGHT = this.$refs.myThreeRef.clientHeight;
				this.ASPECT = this.SCREEN_WIDTH / this.SCREEN_HEIGHT;
			},
			init() {
				this.initScene(); //加载场景
				this.initCamera(); //添加摄像机
				this.initRender(); //渲染器
				this.initControls(); //控制器
				// this.initTrackballControls()
				this.initLight(); //光源
				this.initObject(); //加载模型

				this.initDragControls()

				document.body.addEventListener("keydown", (e) => {
					this.onKeyDown(e)

				}, false)


			},

			// 添加拖拽控件
			initDragControls() {
				let _this = this;
				// 添加平移控件
				var transformControls = new TransformControls(this.camera, this.renderer.domElement);
				this.scene.add(transformControls);

				// 过滤不是 Mesh 的物体,例如辅助网格
				var objects = [];

				console.log(this.groupWal, 'groupWal')

				objects = this.groupWal.children;

				objects.push(this.groupStairs)




				console.log(objects, 'objects')
				// 初始化拖拽控件
				var dragControls = new DragControls(objects, this.camera, this.renderer.domElement);

				// 鼠标略过事件
				dragControls.addEventListener('hoveron', function(event) {
					// 让变换控件对象和选中的对象绑定
					transformControls.attach(event.object);
				});
				// 开始拖拽
				dragControls.addEventListener('dragstart', function(event) {
					_this.controls.enabled = false;
				});
				// 拖拽结束
				dragControls.addEventListener('dragend', function(event) {
					_this.controls.enabled = true;
					console.log(_this.groupWal, '结束')
				});
			},

			/**
			 * 鼠标按下
			 * **/
			onKeyDown(event) {
				console.log(event)
				console.log('点击')
				// switch (event.keyCode) {
				// 	case 13:
				// 		console.log('点击')
				// 		break;
				// }
			},

			/****
			    模型渲染start
			*****/
			initObject() {
				//用来存外部引入的模型
				this.group = new THREE.Group();
				// 围墙模型
				this.groupWal = new THREE.Group();
				this.groupStairs = new THREE.Group();
				this.dummyObject3D = new THREE.Object3D();
				//模型加载函数集合
				this.createFloor(); //产生墙体
				this.createFire(); //产生灭火器	
				this.createStairs(); //产生楼梯
			},
			createFloor() {
				// 对于导入外部模型,注意异步情况的产生
				let floor = require('../assets/images/floor.jpg')
				let that = this;
				var loader = new THREE.TextureLoader();
				loader.load(floor, function(texture) {
					texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
					texture.repeat.set(10, 10);
					var floorGeometry = new THREE.BoxGeometry(1600, 1100, 10);
					var floorMaterial = new THREE.MeshBasicMaterial({
						map: texture,
						side: THREE.DoubleSide
					});
					var floor = new THREE.Mesh(floorGeometry, floorMaterial);
					floor.position.y = -0.5;
					floor.rotation.x = Math.PI / 2;
					floor.name = '地板1';
					that.groupWal.add(floor); //加入墙体集合	
					that.scene.add(that.groupWal)
				});
			},
			// 灭火器
			createFire() {
				let loaderObj = new OBJLoader();
				let loaderMtl = new MTLLoader();
				let that = this;
				loaderMtl.load('static/mtl/fire.mtl', function(materials) {
					materials.preload(); //预加载材质
					loaderObj.setMaterials(materials);
					loaderObj.load('static/obj/fire.obj', function(obj) {
						// console.log(obj, '1222')
						obj.children[0].scale.set(0.4, 0.4, 0.4)
						obj.children[0].position.set(-780, 0, -500)
						// console.log(obj.children[0].material);
						obj.children[0].name = "灭火器"
						// console.log(obj, '莫获取')
						that.groupWal.add(obj.children[0])
						// that.scene.add(obj);

						that.animate()
					})
				})
			},
			// 楼梯
			createStairs() {
				let loaderObj = new OBJLoader();
				let loaderMtl = new MTLLoader();
				let that = this;
				loaderMtl.load('static/mtl/stairs.mtl', function(materials) {
					materials.preload(); //预加载材质
					loaderObj.setMaterials(materials);
					loaderObj.load('static/obj/stairs.obj', function(obj) {
						// console.log(obj, '1222')
						obj.scale.set(1.46, 1.46, 1.46)
						obj.position.set(-500, 150, 0)
						// console.log(obj.children[0].material);
						obj.rotation.x = -Math.PI / 2;
						// obj.position.set(300,0, -300)
						obj.name = "楼梯";
						console.log(obj, '楼梯')
						that.groupStairs.add(obj)

						that.scene.add(that.groupStairs);
						that.animate()
					})
				})
			},
			/****
			    模型渲染end
			*****/
			animate() {
				// 进行渲染
				requestAnimationFrame(this.animate)
				// this.controls.update()
				this.renderer.render(this.scene, this.camera)
			},
			initScene() {
				// 场景
				this.scene = new THREE.Scene();
			},
			initCamera() {
				// 摄像机
				this.camera = new THREE.PerspectiveCamera(this.VIEW_ANGLE, this.ASPECT, this.NEAR, this.FAR);
				this.camera.position.set(0, 1000, 1500);
				this.camera.lookAt(this.scene.position);
				this.camera.lookAt(0, 0, 0);
				this.scene.add(this.camera)
			},
			initRender() {
				// 渲染器
				if (Detector.webgl) {
					this.renderer = new THREE.WebGLRenderer({
						antialias: true,
						alpha: true,
						logarithmicDepthBuffer: true
					});
				} else {
					this.renderer = new THREE.CanvasRenderer();
				}
				this.renderer.setSize(this.SCREEN_WIDTH, this.SCREEN_HEIGHT);
				this.renderer.setClearColor(0xb9d3ff, 1);
				var container = document.getElementById('myThree');
				container.appendChild(this.renderer.domElement);

			},
			// 初始化轨迹球控件
			initTrackballControls() {
				this.controls = new TrackballControls(this.camera, this.renderer.domElement);
				// controls.noRotate = true;
				this.controls.noPan = true;
				// 视角最小距离
				this.controls.minDistance = 1000;
				// 视角最远距离
				this.controls.maxDistance = 5000;
			},
			// 三指操控
			initControls() {
				this.controls = new OrbitControls(this.camera, this.renderer.domElement);
			},
			// 光源
			initLight() {
				var directionalLight = new THREE.DirectionalLight(0xffffff, 1); //模拟远处类似太阳的光源
				directionalLight.position.set(0, 100, 0).normalize();
				this.scene.add(directionalLight);
				var ambient = new THREE.AmbientLight(0xffffff, 1); //AmbientLight,影响整个场景的光源
				ambient.position.set(0, 0, 0);
				this.scene.add(ambient);
			}




		}



	}
</script>

<style>
	#myThree {
		width: 1920px;
		height: 1080px;
	}
</style>

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

圣京都

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

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

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

打赏作者

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

抵扣说明:

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

余额充值