demo案例:https://techbrood.com/threejs/examples/#misc_controls_transform
TransformControls 是 Three.js 中的一个类,用于在网页中进行 3D 场景中物体的交互式操作。让我们来详细讲解它的输入参数、输出、属性和方法:
输入参数:
TransformControls 构造函数通常接受两个参数:
camera(THREE.Camera):用于渲染场景的摄像机。这个参数是必需的。
domElement(HTMLElement):控制器将附加到的 HTML 元素。通常是渲染器的 DOM 元素。这个参数是可选的,如果未提供,则控制器将附加到文档主体上。
输出:
TransformControls 实例:表示变换控制器的对象,初始化为指定的摄像机,并附加到指定的 DOM 元素(如果未提供元素,则附加到文档主体)。
属性:
object(THREE.Object3D):由变换控制器操作的对象。
enabled(布尔值):指示控制器当前是否已启用或禁用。
space(字符串):指定变换空间(‘local’ 或 ‘world’),其中应用变换。
size(数字):以像素为单位的变换控制器的大小。
dragging(布尔值):指示用户当前是否正在拖动控制器。
showX(布尔值)、showY(布尔值)、showZ(布尔值):指示是否显示沿 X、Y 和 Z 轴的控制手柄。
mode(字符串):变换模式(‘translate’、‘rotate’ 或 ‘scale’)。
camera(THREE.Camera):控制器使用的摄像机。
domElement(HTMLElement):控制器附加到的 DOM 元素。
方法:
attach(object: THREE.Object3D):将控制器附加到指定的对象以进行操作。
detach():将控制器从任何对象中分离,有效地停止操作,直到附加新对象为止。
dispose():移除控制器,释放资源。
update():更新控制器。应该在渲染循环中的每一帧中调用。
setMode(mode: String):将变换模式设置为 ‘translate’、‘rotate’ 或 ‘scale’ 中的一种。
setSize(size: Number):设置变换控制器的大小(以像素为单位)。
setSpace(space: String):将变换空间设置为 ‘local’ 或 ‘world’。
TransformControls 具体来说,它可以实现以下功能:
平移(Translate):您可以移动物体,使其沿着三维空间中的 X、Y 或 Z 轴移动。这对于调整物体在场景中的位置非常有用。
旋转(Rotate):您可以围绕物体的原点或者某一指定点进行旋转操作,改变物体的方向或朝向。
缩放(Scale):您可以调整物体的大小,使其放大或缩小。这在场景中创建视觉效果或者调整物体大小时非常有用。
设置变换空间(Set Transform Space):您可以选择将变换应用于物体的局部坐标系(Local Space)还是全局坐标系(World Space)。在局部坐标系中进行变换会受到物体当前旋转的影响,而在全局坐标系中进行变换则会忽略物体的旋转。
多轴控制(Multiple Axis Control):您可以单独控制每个轴上的变换,以便更精确地调整物体的位置、旋转或缩放。
实时交互(Real-time Interaction):变换控制器提供实时的交互式体验,您可以通过拖动控制器上的手柄来直接调整物体的变换参数。
自定义设置(Customization):您可以通过控制器的属性来自定义其外观和行为,例如控制手柄的显示、设置控制器的大小等。
代码:
<!DOCTYPE html> <html lang="en"> <head> <title>three.js webgl - transform controls</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> <link type="text/css" rel="stylesheet" href="main.css"> </head> <body> <div id="info"> "W" translate | "E" rotate | "R" scale | "+/-" adjust size<br /> "Q" toggle world/local space | "Shift" snap to grid<br /> "X" toggle X | "Y" toggle Y | "Z" toggle Z | "Spacebar" toggle enabled<br /> "Esc" reset current transform<br /> "C" toggle camera | "V" random zoom </div> <script type="importmap"> { "imports": { "three": "../build/three.module.js", "three/addons/": "./jsm/" } } </script> <script type="module"> import * as THREE from 'three'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; import { TransformControls } from 'three/addons/controls/TransformControls.js'; let cameraPersp, cameraOrtho, currentCamera; let scene, renderer, control, orbit; init(); render(); function init() { renderer = new THREE.WebGLRenderer( { antialias: true } ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( renderer.domElement ); const aspect = window.innerWidth / window.innerHeight; cameraPersp = new THREE.PerspectiveCamera( 50, aspect, 0.01, 30000 ); cameraOrtho = new THREE.OrthographicCamera( - 600 * aspect, 600 * aspect, 600, - 600, 0.01, 30000 ); currentCamera = cameraPersp; currentCamera.position.set( 5, 2.5, 5 ); scene = new THREE.Scene(); scene.add( new THREE.GridHelper( 5, 10, 0x888888, 0x444444 ) ); const ambientLight = new THREE.AmbientLight( 0xffffff ); scene.add( ambientLight ); const light = new THREE.DirectionalLight( 0xffffff, 4 ); light.position.set( 1, 1, 1 ); scene.add( light ); const texture = new THREE.TextureLoader().load( 'textures/crate.gif', render ); texture.colorSpace = THREE.SRGBColorSpace; texture.anisotropy = renderer.capabilities.getMaxAnisotropy(); const geometry = new THREE.BoxGeometry(); const material = new THREE.MeshLambertMaterial( { map: texture } ); orbit = new OrbitControls( currentCamera, renderer.domElement ); orbit.update(); orbit.addEventListener( 'change', render ); control = new TransformControls( currentCamera, renderer.domElement ); control.addEventListener( 'change', render ); control.addEventListener( 'dragging-changed', function ( event ) { orbit.enabled = ! event.value; } ); const mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); control.attach( mesh ); scene.add( control ); window.addEventListener( 'resize', onWindowResize ); window.addEventListener( 'keydown', function ( event ) { switch ( event.keyCode ) { case 81: // Q control.setSpace( control.space === 'local' ? 'world' : 'local' ); break; case 16: // Shift control.setTranslationSnap( 100 ); control.setRotationSnap( THREE.MathUtils.degToRad( 15 ) ); control.setScaleSnap( 0.25 ); break; case 87: // W control.setMode( 'translate' ); break; case 69: // E control.setMode( 'rotate' ); break; case 82: // R control.setMode( 'scale' ); break; case 67: // C const position = currentCamera.position.clone(); currentCamera = currentCamera.isPerspectiveCamera ? cameraOrtho : cameraPersp; currentCamera.position.copy( position ); orbit.object = currentCamera; control.camera = currentCamera; currentCamera.lookAt( orbit.target.x, orbit.target.y, orbit.target.z ); onWindowResize(); break; case 86: // V const randomFoV = Math.random() + 0.1; const randomZoom = Math.random() + 0.1; cameraPersp.fov = randomFoV * 160; cameraOrtho.bottom = - randomFoV * 500; cameraOrtho.top = randomFoV * 500; cameraPersp.zoom = randomZoom * 5; cameraOrtho.zoom = randomZoom * 5; onWindowResize(); break; case 187: case 107: // +, =, num+ control.setSize( control.size + 0.1 ); break; case 189: case 109: // -, _, num- control.setSize( Math.max( control.size - 0.1, 0.1 ) ); break; case 88: // X control.showX = ! control.showX; break; case 89: // Y control.showY = ! control.showY; break; case 90: // Z control.showZ = ! control.showZ; break; case 32: // Spacebar control.enabled = ! control.enabled; break; case 27: // Esc control.reset(); break; } } ); window.addEventListener( 'keyup', function ( event ) { switch ( event.keyCode ) { case 16: // Shift control.setTranslationSnap( null ); control.setRotationSnap( null ); control.setScaleSnap( null ); break; } } ); } function onWindowResize() { const aspect = window.innerWidth / window.innerHeight; cameraPersp.aspect = aspect; cameraPersp.updateProjectionMatrix(); cameraOrtho.left = cameraOrtho.bottom * aspect; cameraOrtho.right = cameraOrtho.top * aspect; cameraOrtho.updateProjectionMatrix(); renderer.setSize( window.innerWidth, window.innerHeight ); render(); } function render() { renderer.render( scene, currentCamera ); } </script> </body> </html>
转载:https://blog.csdn.net/qq_37030315/article/details/137037850