three DragControls 拖放控制器

698 阅读3分钟

DragControls 是 Three.js 提供的一个控制器,用于在 3D 场景中通过鼠标或触控拖拽物体。它的主要作用是帮助开发者在交互式的 Three.js 项目中更轻松地实现拖动操作。

注意,这个拖放控制主要功能是将场景中的物体直接通过属标控制位置,极大的简化了 three 中对物体位置操作的使用

DragControls 有五个属性五个事件

DragControls( objects : Array, camera : Camera, domElement : HTMLDOMElement ) objects: 一组可被拖拽的3D Objects。 camera: 渲染场景的摄像机。 domElement: 用于事件监听的HTML元素。(可选) 创建一个新的 DragControls 实例。

    // 添加环境光和点光源
    const ambientLight = new THREE.AmbientLight(0x404040); // 环境光
    scene.add(ambientLight);
    const pointLight = new THREE.PointLight(0xffffff, 1);
    pointLight.position.set(5, 5, 5);
    scene.add(pointLight);
    // 创建一个可拖拽的立方体
    const geometry = new THREE.BoxGeometry();
    const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);
    // 设置拖拽对象数组(这里是单个立方体)
    const objects = [cube];
    // 初始化 OrbitControls 以便旋转视角
    const orbitControls = new OrbitControls(camera, renderer.domElement);
    // 创建 DragControls 控制器
    const dragControls = new DragControls(objects, camera, renderer.domElement);
    // 监听拖拽事件
    dragControls.addEventListener('dragstart', (event) => {
        orbitControls.enabled = false; // 禁用 OrbitControls,防止拖拽冲突
        event.object.material.color.set(0xff0000); // 开始拖拽时改变颜色
    });
    dragControls.addEventListener('drag', (event) => {
        console.log("拖拽中,位置:", event.object.position); // 输出拖拽位置
    });
    dragControls.addEventListener('dragend', (event) => {
        orbitControls.enabled = true; // 重新启用 OrbitControls
        event.object.material.color.set(0x00ff00); // 结束拖拽时恢复颜色
    });

事件

  • dragstart 当用户开始拖拽3D Objects时触发。
  • drag当用户拖拽3D Objects时触发。
  • dragend 当用户开始完成3D Objects时触发。
  • hoveron 当指针移动到一个3D Object或者其某个子级上时触发。
  • hoveroff 当指针移出一个3D Object时触发。

属性

  • objects : Array 可拖放对象的数组。
  • raycaster : Raycaster 内部用于检测拾取对象的光线投射器。
  • recursive : Boolean 可拖放对象的子对象是否可以独立于其父对象进行拖放。 默认值为 true。在 Three.js 中,DragControls 的 .recursive: Boolean 参数用于控制可拖拽对象的子对象是否可以独立拖动。这个选项的默认值是 true,意味着子对象默认情况下是可以被单独拖动的,而不依赖于父对象。dragControls.recursive = false:设置 recursive 为 false 后,即便在 objects 数组中包含了父对象 parentCube,其子对象 childCube 也不会被单独拖动。只有在拖动 parentCube 时,childCube 才会随之移动。
    // 创建父对象和子对象
    const parentGeometry = new THREE.BoxGeometry(2, 2, 2);
    const parentMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
    const parentCube = new THREE.Mesh(parentGeometry, parentMaterial);
    scene.add(parentCube);
    const childGeometry = new THREE.BoxGeometry(1, 1, 1);
    const childMaterial = new THREE.MeshBasicMaterial({ color: 0x0000ff });
    const childCube = new THREE.Mesh(childGeometry, childMaterial);
    childCube.position.set(1.5, 0, 0); // 子对象在父对象右侧
    parentCube.add(childCube);
    // 设置拖拽对象数组(包含父对象)
    const objects = [parentCube];
    // 创建 DragControls 并设置 recursive 为 false,避免拖动子对象
    const dragControls = new DragControls(objects, camera, renderer.domElement);
    dragControls.recursive = false; // 禁止单独拖动子对象
  • rotateSpeed : Float 执行 rotate 时的旋转速度。该值越大旋转速度越快。 默认值为 1。
  • transformGroup : Boolean 当 DragControls.objects 数组包含一个单个可拖拽的组对象时该选项生效。 如果设置为true,DragControls会转换整个组对象,而不对单个对象做转换。默认值为false。在 Three.js 的 DragControls 中,transformGroup: Boolean 参数用于控制是否将选中的多个对象作为一个整体来拖动。默认情况下,这个值为 false,意味着每个对象在拖动时会单独移动。如果将其设置为 true,则所有选中的对象会被视为一个整体并一起移动。
    // 创建多个对象并添加到场景中
    const objects = [];
    const colors = [0xff0000, 0x00ff00, 0x0000ff];
    for (let i = 0; i < 3; i++) {
        const geometry = new THREE.BoxGeometry(1, 1, 1);
        const material = new THREE.MeshBasicMaterial({ color: colors[i] });
        const cube = new THREE.Mesh(geometry, material);
        cube.position.set(i * 2 - 2, 0, 0); // 分散放置
        scene.add(cube);
        objects.push(cube); // 将每个对象添加到拖拽对象数组中
    }
    // 创建 DragControls 并启用 transformGroup,将多个对象视为一个整体
    const dragControls = new DragControls(objects, camera, renderer.domElement);
    dragControls.transformGroup = true; // 设置为 true,将多个对象作为一个整体拖动