demo案例
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>
本内容来源于小豆包,想要更多内容请跳转小豆包 》