ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Open Pencil `usePosition()` 组合式 API 详解:读写选中节点的位置、尺寸、旋转、对齐与翻转

Open Pencil `usePosition()` 组合式 API 详解:读写选中节点的位置、尺寸、旋转、对齐与翻转 前端桌面应用AI 应用MCP 服务【免费下载链接】open-pencilAI-native design editor. Open-source Figma alternative.项目地址https://gitcode.com/gh_mirrors/op/open-pencil点击查看免费下载usePosition()是 Open Pencil开源 Figma 替代品Vue SDKopen-pencil/vue中面向属性面板Property Panel的控制型组合式函数control composable为当前选中节点提供位置、尺寸、旋转、对齐、翻转等派生值与操作动作。本文基于官方文档 use-position.md 展开并结合仓库源码 use.ts 及其底层调用链说明如何在自定义编辑器外壳中快速搭建可运行的位置控制 UI以及多选场景下“混合值mixed value”的处理机制。usePosition()是什么usePosition()是open-pencil/vue包中用于位置类属性面板的核心组合式函数。文档西班牙语版与英文版描述它提供“计算值valores calculados与动作acciones”英文版则直接称之为“a control composable for position-related UI”。它面向以下能力英文原文档读取与修改x、y位置读取与修改width、height尺寸读取与修改rotation旋转角度对齐到容器align水平/垂直方向上的 min / center / max翻转flip水平/垂直镜像旋转动作rotate数值属性的 scrub/update拖动微调与提交。从源码看usePosition() 只做了两件事一是通过useNodeProps()拿到当前选中节点集合与混合值检测能力二是把这些状态包装成对编辑器命令alignNodes/flipNodes/rotateNodes和属性预览usePropScrub的调用。因此它不维护任何独立状态所有数据都来自编辑器 store 的当前选区。快速上手安装与引入import { usePosition } from open-pencil/vueopen-pencil/vue是 Open Pencil 的 Vue 集成包封装了编辑器上下文、选区状态与各类控制组合式函数。调用usePosition()前必须处于provideEditor提供的编辑器上下文之内可参考组合式函数总览 index.md 中的provideEditor/useEditor。基本用法const { x, y, width, height, rotation, updateProp, commitProp } usePosition()解构出的x、y、width、height、rotation均为 Vuecomputed引用会随当前选区变化自动更新。源码中的具体计算方式如下use.tsconst x computed(() node.value?.x ?? 0) const y computed(() node.value?.y ?? 0) const width computed(() node.value?.width ?? 0) const height computed(() node.value?.height ?? 0) const rotation computed(() Math.round(node.value?.rotation ?? 0))注意两点实现细节当没有任何选中节点时node为空四个数值回退为0rotation会经过Math.round取整避免浮点角度带来 UI 抖动适合直接渲染到输入框。返回的全部成员usePosition()的返回对象完整列表use.ts成员类型说明editorEditor编辑器实例来自useEditor()nodesRefSceneNode[]当前选中的所有节点nodeRefSceneNode \| undefined当前活动节点单选/主节点activeRefboolean选区是否处于活动状态isMultiRefboolean是否多选prop(key)函数读取某数值属性多选且不一致时返回MIXED哨兵值idsComputedstring[]当前选中节点 id 列表x/y/width/height/rotationComputednumber派生数值updateProp(key, value)函数实时更新数值属性scrub 阶段预览模式commitProp(key, value, previous)函数提交一次属性修改进入撤销栈cancelProp(key)函数取消未提交的预览修改align(axis, pos)函数对齐axis为horizontal \| verticalpos为min \| center \| maxflip(axis)函数翻转axis为horizontal \| verticalrotate(degrees)函数旋转单位为度数值属性键的类型约束updateProp/commitProp/cancelProp的第一个参数类型为NumericNodeProperty其定义位于 scene-graph/src/types.ts/** Scalar numeric node fields accepted by numeric property controls. */ export type NumericNodeProperty { [K in keyof SceneNode]-?: SceneNode[K] extends number ? K : never }[keyof SceneNode]这是一个映射类型从SceneNode中自动筛出所有数值类型的键。也就是说凡是SceneNode上为number的字段如x、y、width、height、rotation、opacity等都可以作为键传入类型系统会在编译期保证你不会传错键名。这也意味着该组合式函数并不仅限于几何属性任何标量数值属性都能走同一条 scrub/commit 通路。多选与混合值Mixed Value文档西语版明确指出“Los valores mixtos se conservan cuando los objetos seleccionados no coinciden.”当选中对象不一致时混合值会被保留。这是位置面板在多选场景下的关键行为单选时x/y/width/height/rotation直接取活动节点的值多选且各节点属性不一致时属性读取函数prop(key)返回MIXED哨兵值UI 层据此显示“混合”占位如输入框显示为空或–避免误导用户以为所有节点共享同一数值。MIXED哨兵值由 node-props/use.ts 导出/** Sentinel value returned when a property differs across multiple selected nodes. */ export { MIXED }PositionControlsRoot组件正是这样使用它的PositionControlsRoot.vueconst xValue computed(() isMulti.value ? multiProp(x).value : Math.round(node.value?.x ?? 0) )即多选时走prop(key)的混合值检测单选时直接读活动节点并取整。当用户在多选状态下输入一个新数值updateProp会通过updateAllWithUndo等机制把该值一致地应用到所有选中节点底层见useNodeProps的批量更新逻辑。实战示例1. 对齐选中节点position.align(horizontal, center) // 水平方向居中对齐 position.align(vertical, min) // 垂直方向按最小值顶部对齐align(axis, pos)的三个取值含义axispos行为horizontalmin左对齐horizontalcenter水平居中对齐horizontalmax右对齐verticalmin顶对齐verticalcenter垂直居中对齐verticalmax底对齐其底层实现use.tsfunction align(axis: horizontal | vertical, pos: min | center | max) { editor.alignNodes(ids.value, axis, pos) }alignNodes是编辑器层命令作用于ids.value当前选中节点 id 列表对齐基准是这些节点所在容器的边界。2. 翻转选中节点position.flip(horizontal) // 水平镜像 position.flip(vertical) // 垂直镜像实现同样直通编辑器命令use.tsfunction flip(axis: horizontal | vertical) { editor.flipNodes(ids.value, axis) }在应用层翻转命令也被注册为菜单/快捷键动作见 editor/commands/selection.tsflipNodes([...selection.selectedIds.value], horizontal)与flipNodes(..., vertical)这说明usePosition().flip与应用内建命令走的是同一条编辑器管线行为完全一致。3. 旋转选中节点position.rotate(90) // 顺时针旋转 90 度实现use.tsfunction rotate(degrees: number) { editor.rotateNodes(ids.value, degrees) }注意rotate(degrees)是增量旋转在当前角度基础上加degrees而非设置绝对角度绝对角度仍需通过updateProp(rotation, value)设置。rotation派生值做了取整因此 UI 显示为整数度而底层场景图仍保留精确浮点值。4. 数值微调scrub / update / commitusePosition()内部复用了usePropScrub(editor)提供的三件套use.tsconst { updateProp: _updateProp, commitProp: _commitProp, cancelProp: _cancelProp } usePropScrub(editor) function updateProp(key: NumericNodeProperty, value: number) { _updateProp(nodes.value, key, value) } function commitProp(key: NumericNodeProperty, value: number, previous: number) { _commitProp(nodes.value, key, value, previous) } function cancelProp(key: NumericNodeProperty) { _cancelProp(nodes.value, key) }而 usePropScrub 的本质是**属性预览preview**机制function updateProp(nodes: SceneNode[], key: NumericNodeProperty, value: number) { preview.update(nodes.map((node) node.id), { [key]: value }, Change ${key}) } function commitProp() { preview.commit() } function cancelProp() { preview.cancel() }这套模式对应输入框的典型交互流程用户拖动滑杆或在输入框连续输入 → 高频调用updateProp(key, value)节点在画布上实时预览变化但尚未写入撤销历史用户松开/回车确认 → 调用commitProp(key, value, previous)将本次修改提交进撤销栈用户按 Esc 取消 → 调用cancelProp(key)回滚到修改前状态。这保证了数值微调scrub操作既流畅预览不触发撤销记录又不污染历史记录只在提交时写入一次。在 Vue 属性面板中的典型用法usePosition()是属性面板最常用的控制组合式函数之一。property-panels.md 给出了完整的位置面板示例script setup langts import { usePosition } from open-pencil/vue const { x, y, width, height, updateProp, commitProp } usePosition() /script template div classgrid grid-cols-2 gap-2 input :valuex inputupdateProp(x, Number(($event.target as HTMLInputElement).value)) / input :valuey inputupdateProp(y, Number(($event.target as HTMLInputElement).value)) / input :valuewidth inputupdateProp(width, Number(($event.target as HTMLInputElement).value)) / input :valueheight inputupdateProp(height, Number(($event.target as HTMLInputElement).value)) / /div /template要点x/y/width/height是computed可直接绑定到input :valueinput中通过updateProp实时更新若需要撤销支持在change或 blur 时补一次commitProp(key, value, previous)多选混合值场景下建议改用prop(key)判断MIXED以渲染占位符。文档给出的选型原则Rule of thumb直接的控制逻辑用组合式函数composables当难点在于重复的列表/树/slot 结构协调时用结构性 headless 原语如PropertyListRoot。因此位置面板这种“选区派生值 更新动作”的场景usePosition()是首选而 fills/strokes/effects 这类需要数组增删的结构才应搭配useFillControls/useStrokeControls/useEffectsControls与列表原语。与无头组件的配合PositionControlsRoot如果不想逐一手写插槽绑定open-pencil/vue还提供了无头原语组件PositionControlsRoot西语文档“Véase también”中关联。其文档描述为为当前选区暴露位置、尺寸、旋转、对齐、翻转处理器的“headless root primitive”适用于“想要自定义位置控件但又不想重新实现编辑器接线”的场景。该组件内部同样调用usePosition()然后通过单个默认插槽把状态与动作全部暴露出去PositionControlsRoot.vuetemplate slot :activeactive :is-multiisMulti :idsids :x-valuexValue :y-valueyValue :w-valuewValue :h-valuehValue :rotation-valuerotationValue :mixedMIXED :actionsactions / /template使用模式PositionControlsRoot v-slot{ xValue, yValue, wValue, hValue, rotationValue, actions, mixed } !-- 自定义位置控件actions 中已包含 updateProp/commitProp/cancelProp/align/flip/rotate -- /PositionControlsRoot其中actions聚合了updateProp、commitProp、cancelProp、align、flip、rotate六个动作mixed即MIXED哨兵值方便多选时渲染混合占位。源码调用链一览从组合式函数到编辑器命令的完整调用链usePosition() ├── useNodeProps() // 选区状态nodes / node / isMulti / prop(MIXED) │ └── createNodePropSelectionState(store) ├── usePropScrub(editor) // 预览模式update / commit / cancel │ └── useNodePreview(editor) ├── align(axis, pos) → editor.alignNodes(ids, axis, pos) ├── flip(axis) → editor.flipNodes(ids, axis) └── rotate(degrees) → editor.rotateNodes(ids, degrees)相关文件组合式函数实现packages/vue/src/controls/position/use.ts选区与混合值packages/vue/src/controls/node-props/use.ts数值属性预览packages/vue/src/controls/prop-scrub/use.ts无头原语组件packages/vue/src/primitives/PositionControls/PositionControlsRoot.vue数值属性键类型packages/scene-graph/src/types.ts应用内对齐/翻转命令参考packages/vue/src/editor/commands/selection.ts相关 API 与文档索引西语原文档packages/docs/es/programmable/sdk/api/composables/use-position.md英文原文档packages/docs/programmable/sdk/api/composables/use-position.md属性面板指南property-panels.md无头位置控件position-controls-root.md相关组合式函数useLayoutuse-layout.md、useAppearance、usePropScrub高级用法见西语文档关联的 use-prop-scrub全部组合式函数索引index.mdusePosition()把选区状态、混合值检测、预览式微调与编辑器命令封装成一个薄层是自定义 Open Pencil 编辑器外壳时搭建位置/变换面板的最直接入口配合无头组件PositionControlsRoot可以在不重新实现任何编辑器接线的前提下完全掌控位置控件的展示形态。赞分享前端桌面应用AI 应用MCP 服务【免费下载链接】open-pencilAI-native design editor. Open-source Figma alternative.项目地址https://gitcode.com/gh_mirrors/op/open-pencil点击查看免费下载相关推荐open-pencil 位置控制组合式函数 usePosition 完全指南读取与修改选中节点的位置、尺寸与旋转open pencil 位置控制组合式函数 usePosition 完全指南读取与修改选中节点的位置、尺寸与旋转 usePosition 是 open pen前端桌面应用AI 应用MCP 服务Open Pencil useLayout 详解自动布局、尺寸模式、内边距、对齐与网格轨道的统一控制Open Pencil useLayout 详解自动布局、尺寸模式、内边距、对齐与网格轨道的统一控制 useLayout 是 Open Pencil 官方 V前端桌面应用AI 应用MCP 服务Open-Pencil 响应式选区状态深入解析 useSelectionState() 组合式 APIOpen Pencil 响应式选区状态深入解析 useSelectionState 组合式 API 导读 useSelectionState 是 Open P前端桌面应用AI 应用MCP 服务上一篇BioGPT代码解析深入理解openmind框架下的生物医学模型实现下一篇WaveTerm内存泄漏排查提升稳定性的性能分析工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表