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>

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
对整threeJS体系进行全面剖析。整理出全面的教学大纲,涵盖内容面非常广。此教学版本为threeJS107版本。关于版本不建议大家使用低于90的版本学习。以下是课程目录1-ThreeJS概览(基本图形简介,什么是点线面如何绘制点线面,什么是材质,什么是几何体,什么是相机,什么是渲染器,什么是场景)2-相机和渲染器(详解相机类型,渲染器如何使用,针对不同场景怎么用,怎么调效果,怎么渲染,怎么输出画布,如何解决透明问题等等)3-创建平面几何(常见的几何体如何使用,如何使用简单的几何体绘制出自定义自己想要的几何体,关于几何体的性能剖析,如何解决性能,几何体的渲染原理)4-高级图形算法常见库(求直线的斜率  计算线段与圆的交点 计算线段的长度 判断折线是否在多边形内 等等)5-sprite精灵(怎么让一个图标永远朝向屏幕,精灵的属性,精灵材质原理等,广告提示框必用)6-骨骼游戏动画(什么是模型动画,常见游戏案例,如何让人头进行各种攻击动作)7-3d模型加载(常见模型格式,如何渲染不同格式,不同格式的特点,什么格式性能优越,模型渲染异常,贴图不显示等问题详解)8-高阶动态纹理(你所不知道的纹理用法,我说你不知道,你肯定不知道)9-漫游轨迹以及其动画路径(怎么绘制贝塞尔曲线,如何使用曲线上的路径,跟随路径移动的原理,相机如何运动,物体如何运动)10-着色器(什么是着色器。初识着色器基础,着色器材质怎么用,怎么使用着色器库)11-常见渲染以及透明度问题12-对象拾取以及拖拽(3d世界里面如何拖拽物体,拖拽的原理,mousemove mouseon等的事件效果)13-世界坐标以及组的问题(什么是相对坐标,什么是世界坐标,什么是当前坐标,怎么转化父子坐标系,组的优化,为什么用组,组的优势)14-指定对象旋转中心(什么是物体的几何体中心,如何改变中心,如何绕轴转动)15-层级对象渲染(多个场景一键切换,切换的优势,针对大项目的用法)16-拓展了解系列(不定期不断更新案例,各种酷炫效果bloom,halo等,以及各种3d图表,粒子案例等,不断构建你的3d实践能力)

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

圣京都

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

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

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

打赏作者

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

抵扣说明:

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

余额充值