这节我们把选中家具时的信息面板做一下:

去掉背景色:

然后用 antd 的表单来展示一下:

{
curSelectedFurniture ? <div>
<Form initialValues={
curSelectedFurniture
} style={{
margin: 10
}}>
<Form.Item label="ID" name='id'>
<Input disabled/>
</Form.Item>
<Form.Item label="位置 x" name={["position", 'x']}>
<Input/>
</Form.Item>
<Form.Item label="位置 y" name={["position", 'y']}>
<Input/>
</Form.Item>
<Form.Item label="位置 z" name={["position", 'z']}>
<Input/>
</Form.Item>
<Form.Item label="角度 x" name={["rotation", 'x']}>
<Input/>
</Form.Item>
<Form.Item label="角度 y" name={["rotation", 'y']}>
<Input/>
</Form.Item>
<Form.Item label="角度 z" name={["rotation", 'z']}>
<Input/>
</Form.Item>
</Form>
</div> : null
}

信息展示出来了,但现在在表单里按删除键会把家具删除:

我们阻止下事件冒泡就好了:

onKeyDown={(evt) => {
evt.stopPropagation();
}}

现在移动家具位置,切换选中的家具的时候,表单值都不会变化:

因为它只设置了初始值,我们要做下值的同步:

const [form] = useForm();
useEffect(() => {
form.setFieldsValue(curSelectedFurniture);
}, [curSelectedFurniture]);
form={form}
用 useForm 拿到表单实例,切换选中的家具的时候,设置下表单值。

然后是编辑时同步表单值:

data 变化的时候也同步设置下就好了。

这个旋转角度显然用滑动输入条会更好。

范围是 -2π 到 2π

<Form.Item label="位置 x" name={["position", 'x']}>
<InputNumber/>
</Form.Item>
<Form.Item label="位置 y" name={["position", 'y']}>
<InputNumber disabled/>
</Form.Item>
<Form.Item label="位置 z" name={["position", 'z']}>
<InputNumber/>
</Form.Item>
<Form.Item label="角度 x" name={["rotation", 'x']}>
<Slider min={-Math.PI * 2} max={Math.PI * 2}/>
</Form.Item>
<Form.Item label="角度 y" name={["rotation", 'y']}>
<Slider min={-Math.PI * 2} max={Math.PI * 2}/>
</Form.Item>
<Form.Item label="角度 z" name={["rotation", 'z']}>
<Slider min={-Math.PI * 2} max={Math.PI * 2}/>
</Form.Item>
用 Slider 调整角度,位置应该是用 InputNumber,然后 y 方向禁用

然后编辑表单的时候同步到 store:

onValuesChange={handleValuesChange}
function handleValuesChange() {
const values = form.getFieldsValue();
console.log(values);
}
表单变化的时候打印下表单值:

然后把它更到 store 里:

function handleValuesChange() {
const values = form.getFieldsValue();
updateFurniture(values.id, 'position', values.position);
updateFurniture(values.id, 'rotation', values.rotation);
}
试一下:

这样就能直接通过表单来修改家具位置角度了。
当然,这里角度也只支持绕 y 轴旋转:

把 x、z 方向的旋转禁用:


整体测试下:

这里还有个问题:

2D、3D 视图的家具旋转方向刚好相反。
这个也是因为我们之前 2D 视图整体旋转了 180 度的原因,家具的 rotation.y 也要旋转 180 度。
改 3 处地方:

obj.rotation.y = furniture.rotation.y + Math.PI;
这样就好了:

顺便改下 title


这个墙的选中效果,我们暂时也用不到,去掉:

案例代码上传了小册仓库
总结
这节我们加上了家具信息编辑的表单。
选中家具的时候,用 antd 的 Form 来展示 position、rotation 等信息,角度用 Slider 滑动条。
data 变化的时候,同步修改表单的值。
表单值变化的时候,同步设置到 store。
这样,家具的信息编辑表单就完成了。