首页 前端知识 TransformControls 是 Three.js 中的一个类,用于在网页中进行 3D 场景中物体的交互式操作。

TransformControls 是 Three.js 中的一个类,用于在网页中进行 3D 场景中物体的交互式操作。

2024-05-27 09:05:06 前端知识 前端哥 11 619 我要收藏

demo案例

TransformControls 是 Three.js 中的一个类,用于在网页中进行 3D 场景中物体的交互式操作。让我们来详细讲解它的输入参数、输出、属性和方法:
在这里插入图片描述

输入参数:

TransformControls 构造函数通常接受两个参数:

  1. camera(THREE.Camera):用于渲染场景的摄像机。这个参数是必需的。

  2. domElement(HTMLElement):控制器将附加到的 HTML 元素。通常是渲染器的 DOM 元素。这个参数是可选的,如果未提供,则控制器将附加到文档主体上。

输出:

TransformControls 实例:表示变换控制器的对象,初始化为指定的摄像机,并附加到指定的 DOM 元素(如果未提供元素,则附加到文档主体)。

属性:

  1. object(THREE.Object3D):由变换控制器操作的对象。

  2. enabled(布尔值):指示控制器当前是否已启用或禁用。

  3. space(字符串):指定变换空间(‘local’ 或 ‘world’),其中应用变换。

  4. size(数字):以像素为单位的变换控制器的大小。

  5. dragging(布尔值):指示用户当前是否正在拖动控制器。

  6. showX(布尔值)、showY(布尔值)、showZ(布尔值):指示是否显示沿 X、Y 和 Z 轴的控制手柄。

  7. mode(字符串):变换模式(‘translate’、‘rotate’ 或 ‘scale’)。

  8. camera(THREE.Camera):控制器使用的摄像机。

  9. domElement(HTMLElement):控制器附加到的 DOM 元素。

方法:

  1. attach(object: THREE.Object3D):将控制器附加到指定的对象以进行操作。

  2. detach():将控制器从任何对象中分离,有效地停止操作,直到附加新对象为止。

  3. dispose():移除控制器,释放资源。

  4. update():更新控制器。应该在渲染循环中的每一帧中调用。

  5. setMode(mode: String):将变换模式设置为 ‘translate’、‘rotate’ 或 ‘scale’ 中的一种。

  6. setSize(size: Number):设置变换控制器的大小(以像素为单位)。

  7. setSpace(space: String):将变换空间设置为 ‘local’ 或 ‘world’。

TransformControls 具体来说,它可以实现以下功能:

  1. 平移(Translate):您可以移动物体,使其沿着三维空间中的 X、Y 或 Z 轴移动。这对于调整物体在场景中的位置非常有用。

  2. 旋转(Rotate):您可以围绕物体的原点或者某一指定点进行旋转操作,改变物体的方向或朝向。

  3. 缩放(Scale):您可以调整物体的大小,使其放大或缩小。这在场景中创建视觉效果或者调整物体大小时非常有用。

  4. 设置变换空间(Set Transform Space):您可以选择将变换应用于物体的局部坐标系(Local Space)还是全局坐标系(World Space)。在局部坐标系中进行变换会受到物体当前旋转的影响,而在全局坐标系中进行变换则会忽略物体的旋转。

  5. 多轴控制(Multiple Axis Control):您可以单独控制每个轴上的变换,以便更精确地调整物体的位置、旋转或缩放。

  6. 实时交互(Real-time Interaction):变换控制器提供实时的交互式体验,您可以通过拖动控制器上的手柄来直接调整物体的变换参数。

  7. 自定义设置(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://www.qianduange.cn//article/9619.html
标签
评论
发布的文章

html5怎么实现语音搜索

2024-06-01 10:06:32

HTML5

2024-02-27 11:02:15

HTML - 头部元素

2024-06-01 10:06:06

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!