Skip to content

121. 实战:酷家乐装修编辑器(二十五)

Published:

上节实现了拖拽家具列表中的家具到房子的任意位置:

2025-07-25 19.42.20.gif

有两个问题:

我们先来解决第一个问题。

如何让相机的焦点在房子中间呢?

其实有两种方案:

第一种就是用 Box3 包围盒拿到房子大小,然后修改房子位置到 0,0,0 就好了,相机焦点默认在 0,0,0

另一方方案是房子位置不变,修改相机的焦点为房子的中心位置。

第一种方式之前用过,现在我们用修改相机焦点的方式再来实现这个功能。

要注意的是,相机的焦点 camera.lookAt 要和 OrbitControls 的 target 同时修改才行。

所以我们这里导出 OrbitControls:

image.png

组件里接收下:

image.png

image.png

const controls3DRef = useRef<OrbitControls>(null);
controls3DRef.current = controls;

然后在之前修改房子位置的地方改成修改相机焦点位置:

image.png

camera3DRef.current?.lookAt(center.x, 0, center.z);
controls3DRef.current?.target.set(center.x, 0, center.z);

试一下:

之前是这样:

2025-07-25 19.54.24.gif

现在是这样:

2025-07-25 19.54.55.gif

现在相机焦点又移到房子中央了,但这次不是在 0,0,0 的位置。

添加家具的功能正常:

2025-07-25 19.56.05.gif

然后来解决拖拽不同家具的对应处理。

这个其实就是在 useDrag 里加一个上下文数据就行:

image.png

const [, drag]= useDrag({
    type: '家具',
    item: {
        modelUrl: props.title === '床' ? './bed.glb' : './dining-table.glb'
    },
});

item 就是这个上下文数据。

然后在 useDrop 的时候,就直接用这个 url 来加载模型:

image.png

item: { modelUrl: string }
modelUrl: item.modelUrl

还要处理下 scale 的问题:

image.png

modelScale: item.modelUrl.includes('bed.glb') ? 800 : 1,

试一下:

清空两个户型的默认家具:

image.png

然后切换户型:

2025-07-25 21.20.22.gif

2025-07-25 21.20.48.gif

这样,拖拽家具到 3D 场景中就完成了。

不过 2D 视图没有同步更新。

和之前同样的问题:

image.png

加上 else 的处理,注意 2D 视图位置是反的。

else {
    const gltfLoader = new GLTFLoader();
    const furnitures = houseObj.getObjectByName('furnitures')!;

    gltfLoader.load(furniture.modelUrl, (gltf) => {
        furnitures.add(gltf.scene);

        gltf.scene.scale.setScalar(furniture.modelScale || 1);

        gltf.scene.position.set(
            -furniture.position.x,
            -furniture.position.y,
            -furniture.position.z
        );

        gltf.scene.rotation.x = furniture.rotation.x;
        gltf.scene.rotation.y = furniture.rotation.y;
        gltf.scene.rotation.z = furniture.rotation.z;

        gltf.scene.traverse(obj => {
            (obj as any).target = gltf.scene;
        });
        gltf.scene.name = furniture.id
    });
}

顺便把坐标轴都去一下:

image.png

image.png

image.png

看下效果:

2025-07-25 21.42.13.gif

2025-07-25 21.44.17.gif

这样,拖拽家具到 3D 场景的功能就完成了。

案例代码上传了小册仓库

总结

这节我们修复了两个问题。

第一个是相机焦点设置到房子中心的问题,这个可以移动房子位置,也可以移动相机焦点,我们用的第二种方案,设置 camera.lookAt 和 controls.target

第二个是拖拽不同家具的时候,添加对应家具的功能,这个是在 useDrag 的时候通过 item 传递数据,然后 useDrop 的时候取出 item 加载对应模型就好了。

当然,目前我们只实现了拖拽家具到 3D 视图,2D 视图也是可以实现拖拽的,原理一样。

评论