这节我们来写最后一块功能:

物体属性的编辑,比如 geometry、material。
创建一个新组件:
Properties/Info.jsx
import { useThreeStore } from "../../store";
function Info() {
const { selectedObj } = useThreeStore();
return <div className='Info'>
{ selectedObj?.isMesh ?
<div>
<div>几何体: {selectedObj.geometry.type}</div>
<div>材质: {selectedObj.material.type}</div>
</div>
: null
}
</div>
}
export default Info;
从 store 取出 selectedObj,如果它是 mesh,就分别展示下几何体、材质。
在 Properties/index.jsx 引入下:

看下效果:

这样,切换选中对象的时候,就会在 Info 组件里展示详细信息。
我们来做属性的展示和编辑:
我们只实现部分属性,其他属性的编辑也是一样,可以自己扩展
首先,我们要在 store 里添加一个修改 material 的方法:

和之前修改 position 差不多,只不过这次修改的是 material
updateMaterial(name, info) {
set(state => {
return {
data: {
...state.data,
meshArr: state.data.meshArr.map(mesh => {
if(mesh.name === name) {
mesh.props.material = {
...mesh.props.material,
...info
}
}
return mesh;
})
}
}
})
},
然后改下 Properties/Info.jsx
用 Form 来展示属性,编辑之后调用 updateMaterial 来更新。

这里我们用 Form 来展示属性,设置初始数据,编辑后用 updateMaterial 更新 store 里的数据。
import { ColorPicker, Form, Input } from "antd";
import { useThreeStore } from "../../store";
function Info() {
const { selectedObj, updateMaterial } = useThreeStore();
function handleValuesChange(changeValues) {
const colorStr = changeValues.color.toHexString();
updateMaterial(selectedObj.name, {
color: colorStr
});
}
return <div className='Info' style={{margin: 20}}>
{ selectedObj?.isMesh ?
<Form
initialValues={{
color: selectedObj.material.color.getHexString()
}}
onValuesChange={handleValuesChange}
>
<Form.Item label="材质颜色" name="color">
<ColorPicker/>
</Form.Item>
</Form>
: null
}
</div>
}
export default Info;
先把之前的 json 注释去掉:

看下效果:

可以看到,store 里已经改了。
但是渲染的时候没有设置,我们改一下:

mesh.material.color = new THREE.Color(color);
渲染的时候设置材质颜色为最新的颜色。
试一下:

这样,属性修改就完成了。
其余的属性也是一样的,大家可以自己扩展。
现在有个问题:

切换选中的对象的时候,表单颜色没有跟着变。
这个同步下就好了:

const [form] = useForm();
useEffect(() => {
if(selectedObj?.isMesh) {
form.setFieldValue('color', selectedObj.material.color.getHexString())
}
}, [selectedObj]);
用 useForm 的 api 来操作表单。
在 selectedObj 变化的时候,设置 color 的值为选中的物体的材质颜色。

案例代码上传了小册仓库
总结
这节我们实现了属性编辑。
其实就是选中对象的时候,把它的信息展示出来。
然后可以通过表单修改属性的值,把它同步更改到 json。
这样再次渲染的时候,修改的属性就生效了。
各种属性的编辑原理都一样。