上节实现了基本的全景浏览功能:


这节我们来优化一下。
首先,酷家乐这个预览,窗外是有风景的:

其实就是一个全景图。
我们现在窗外是黑乎乎的一片。
找个全景图:

下载下来放到 public 目录:

代码里加载下:

const rgbeloader = new RGBELoader();
rgbeloader.load('./pic.hdr', function ( texture ) {
texture.mapping = THREE.EquirectangularReflectionMapping;
scene.background = texture;
});

这样,窗外就有风景了。
现在转的有点慢:

调一下速度:


这样角度转的就快了。
然后我们实现下家具的删除。
store 加一个方法:


deleteFurniture(id: string): void;
deleteFurniture(id) {
set(state => {
return {
...state,
data: {
...state.data,
furnitures: state.data.furnitures.filter(item => {
return item.id !== id
})
}
}
})
}
然后我们要知道当前选中的家具是哪个,所以还要加一个 curSelectedFurniture 的属性:

curSelectedFurniture: Furniture | null
setCurSelectedFurniture(furnitureId: string): void;

curSelectedFurniture: null,
setCurSelectedFurniture(furnitureId) {
set(state => {
const found = state.data.furnitures.filter((item)=> {
return item.id === furnitureId;
});
return {
...state,
curSelectedFurniture: found.length ? found[0] : null
}
})
}
传入家具 id,找到对应的家具,设置到 curSelectedFurniture
然后点击选中物体的时候,如果是家具,就调用这个方法:
我们把 furniture.id 设置到了 name:

所以点击的时候就取 name 来设置:


setCurSelectedFurniture: Action['setCurSelectedFurniture']
点击的时候调用下:

setCurSelectedFurniture(obj.target.name);
setCurSelectedFurniture('');
我们在 Properties 组件里把它可视化展示一下:

JSON.stringify(curSelectedFurniture, null, 4)
试下效果:

可以看到,点击不同家具,确实选中的家具信息变了。
同样的方式来加一下 2D 场景的选中逻辑:


setCurSelectedFurniture: Action['setCurSelectedFurniture']

setCurSelectedFurniture(obj.target.name);
setCurSelectedFurniture('');
试一下:

也没问题。
接下来实现下删除:

useEffect(() => {
const scene = scene3DRef.current!;
function handleKeydown(e: KeyboardEvent) {
if(e.key === 'Backspace') {
if(curSelectedFurniture) {
const furniture = scene.getObjectByName(curSelectedFurniture.id);
if(furniture) {
furniture.parent?.remove(furniture);
deleteFurniture(furniture.name);
setCurSelectedFurniture('');
}
}
}
}
window.addEventListener('keydown', handleKeydown);
return () => {
window.removeEventListener('keydown', handleKeydown);
}
}, [curSelectedFurniture]);
监听键盘事件,当按下删除键的时候,找到 curSelectedFurniture 对应的对象删除,并且在 store 里删除。
试一下:

可以看到,家具确实删除了。
但是 TransformControls 没有 detach。
我们导出一个 detach 方法:

function detachTransformControls() {
transformControls.detach();
}
然后组件里接收下:


const detachTransformControls3DRef = useRef<() => void>(null);
detachTransformControls3DRef.current = detachTransformControls;
删除的时候调用下:

detachTransformControls3DRef.current?.();
再试试:

现在删除之后就 detach 了。
案例代码上传了小册仓库
总结
这节我们给预览的场景里加上了全景图,窗外就有风景了。
然后实现了选中后按 delete 键删除家具。
现在删除家具还有一些问题,下节我们继续完善。