THREE.JS使用TransformControls对模型拖拽的代码实例
作者:莫,imma
拖拽是前端实现中比较常用的一种效果,下面这篇文章主要给大家介绍了关于THREE.JS使用TransformControls对模型拖拽的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
一、原理:
TransformControls 是由 THREE.JS 提供的一类控制器。
该类可提供一种类似于在数字内容创建工具(例如Blender)中对模型进行交互的方式,来在3D空间中变换物体。 和其他控制器不同的是,变换控制器不倾向于对场景摄像机的变换进行改变。
详见官网。
二、步骤:
- 初始化场景
- 引入TransformControls控制器,并对其进行监听
- 添加模型和连线
- 根据控制器的改变对连线进行修改
三、代码:
<template> <div class="fa_container"> <div class="container" ref="container"></div> </div> </template> <script> import * as THREE from 'three' import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' import { TransformControls } from 'three/examples/jsm/controls/TransformControls.js' const scene = new THREE.Scene() let renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true, logarithmicDepthBuffer: true }) let camera, controls, transformControl const pointer = new THREE.Vector2() const point = new THREE.Vector3() const raycaster = new THREE.Raycaster() let splineHelperObjects = [] const ARC_SEGMENTS = 200 let splines = [] export default { name: 'model', data () { return { positionList: [ [10, 0, 0], [-10, 0, 0] ] } }, mounted () { this.init() this.addMarkModel() this.render() }, methods: { init () { this.dom = this.$refs['container'] this.initHelper() this.initLight() this.initCamera() this.initRender() this.initControls() this.dom.addEventListener('pointermove', e => { this.onPointerMove(e) }) }, initHelper () { scene.background = new THREE.Color(0xf0f0f0) // const axes = new THREE.AxesHelper(50) // scene.add(axes) const planeGeometry = new THREE.PlaneGeometry(2000, 2000) planeGeometry.rotateX(-Math.PI / 2) const planeMaterial = new THREE.ShadowMaterial({ color: 0x000000, opacity: 0.2 }) const plane = new THREE.Mesh(planeGeometry, planeMaterial) plane.position.y = -200 plane.receiveShadow = true scene.add(plane) const helper = new THREE.GridHelper(2000, 100) helper.position.y = -199 helper.material.opacity = 0.25 helper.material.transparent = true scene.add(helper) }, initCamera () { camera = new THREE.PerspectiveCamera( 45, this.dom.offsetWidth / this.dom.offsetHeight, 0.001, 10000 ) camera.position.set(35, 35, 35) }, initLight () { const directLight = new THREE.DirectionalLight('#ffffff', 0.5) const directLight1 = new THREE.DirectionalLight('#ffffff', 0.5) const directLight2 = new THREE.PointLight('#ffffff', 0.5) const ambientLight = new THREE.AmbientLight('#ffffff', 0.3) directLight.castShadow = true directLight.position.set(15, 15, 15) directLight1.position.set(-15, -15, 15) ambientLight.position.set(0, 0, -5) directLight2.position.set(-15, 15, -15) directLight2.castShadow = true scene.add(directLight, directLight1, ambientLight, directLight2) }, initRender () { renderer.setSize(1902, 935) renderer.outputEncoding = THREE.sRGBEncoding this.dom.appendChild(renderer.domElement) }, initControls () { controls = new OrbitControls(camera, renderer.domElement) transformControl = new TransformControls(camera, renderer.domElement) transformControl.addEventListener('change', () => { console.log('模型拖动') }) transformControl.addEventListener('dragging-changed', function (event) { controls.enabled = !event.value }) transformControl.addEventListener('objectChange', param => { this.updateSplineOutline() }) scene.add(transformControl) }, // 鼠标移动 onPointerMove (event) { pointer.x = (event.clientX / window.innerWidth) * 2 - 1 pointer.y = -(event.clientY / window.innerHeight) * 2 + 1 raycaster.setFromCamera(pointer, camera) const intersects = raycaster.intersectObjects(splineHelperObjects, false) if (intersects.length > 0) { const object = intersects[0].object if (object !== transformControl.object) { transformControl.attach(object) controls.enabled = false } } }, // 更新连线 updateSplineOutline () { for (let k = 0; k < splines.length; k++) { const spline = splines[k] const splineMesh = spline.mesh const position = splineMesh.geometry.attributes.position for (let i = 0; i < ARC_SEGMENTS; i++) { const t = i / (ARC_SEGMENTS - 1) spline.getPoint(t, point) position.setXYZ(i, point.x, point.y, point.z) } position.needsUpdate = true } }, render () { requestAnimationFrame(this.render.bind(this)) controls.update() renderer.render(scene, camera) }, addMarkModel () { for (let i = 0; i < this.positionList.length; i++) { let position = [] let obj1 = this.creatSpot(this.positionList[i], i) let obj2 = this.creatHtml(i) setTimeout(() => { position.push(obj1.position) position.push(obj2.position) this.creatLine(position) }, 2000) } }, creatSpot (positionArr, index) { const spherGeometry = new THREE.SphereGeometry(3, 32, 16) const spherMaterial = new THREE.MeshLambertMaterial({ color: 'red' }) const sphere = new THREE.Mesh(spherGeometry, spherMaterial) sphere.position.set(positionArr[0], positionArr[1], positionArr[2]) sphere.scale.set(0.2, 0.2, 0.2) splineHelperObjects.push(sphere) scene.add(sphere) return sphere }, creatHtml (index, spot) { const spherGeometry = new THREE.BoxBufferGeometry(15, 15, 15) const spherMaterial = new THREE.MeshPhongMaterial({ transparent: true, opacity: 1, color: 'green' }) const sphere = new THREE.Mesh(spherGeometry, spherMaterial) sphere.position.x = Math.random() * 10 sphere.position.y = Math.random() * 20 sphere.position.z = Math.random() * 15 sphere.scale.set(0.2, 0.2, 0.2) splineHelperObjects.push(sphere) scene.add(sphere) return sphere }, creatLine (position) { var curve = new THREE.CatmullRomCurve3(position) var points = curve.getPoints(ARC_SEGMENTS) var geometry = new THREE.BufferGeometry().setFromPoints(points) var material = new THREE.LineBasicMaterial({ color: 0xff0000 }) curve.mesh = new THREE.LineSegments(geometry, material) scene.add(curve.mesh) splines.push(curve) } } } </script> <style> .container { width: 1902px; height: 935px; overflow: hidden; background: black; display: inline-block; } </style>
四、最终效果:
拖拽前:
鼠标拾取模型:
模型拖动:
总结
到此这篇关于THREE.JS使用TransformControls对模型拖拽的文章就介绍到这了,更多相关THREE.JS对模型拖拽内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!