ARTICLE DETAIL

资讯详情

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

掌握 OpenPencil Vue SDK 的 useCanvasInput:画布指针交互中枢的源码级解析

掌握 OpenPencil Vue SDK 的 useCanvasInput:画布指针交互中枢的源码级解析 前端桌面应用AI 应用MCP 服务【免费下载链接】open-pencilAI-native design editor. Open-source Figma alternative.项目地址https://gitcode.com/gh_mirrors/op/open-pencil点击查看免费下载导读useCanvasInput是 OpenPencilAI-native 设计编辑器开源项目Vue SDK 中负责把canvas元素的指针与鼠标事件接入编辑器输入系统的核心 composable。它把屏幕坐标换算成画布坐标、统一调度选中、拖拽、缩放、旋转、平移、绘图工具与文本/矢量编辑等全部画布交互是任何自建编辑器外壳editor shell接入画布时必须掌握的低层 API。读完本文你将理解useCanvasInput的完整签名、各参数的职责、内部交互状态机DragState、坐标换算原理以及它在真实编辑器外壳中的调用方式能够据此在自己构建的 Vue 组件里正确接入 OpenPencil 画布。本文基于仓库中该 API 的官方文档packages/docs/fr/programmable/sdk/api/composables/use-canvas-input.md并深入其实际源码 packages/vue/src/canvas/useCanvasInput.ts 及配套输入模块展开。一、useCanvasInput 是什么根据官方文档useCanvasInput(options)把目标元素通常是canvas的事件绑定到编辑器的输入系统上覆盖的能力清单包括指针的移动、按下与释放mouvement, pression et relâchement du pointeur选中与框选sélection et rectangle de sélection视图平移与缩放déplacement de la vue et zoom对象拖拽glissement des objets缩放与旋转redimensionnement et rotation形状工具、钢笔Plume、文本与抓手工具outils de formes, Plume, Texte et Main矢量编辑与文本编辑édition vectorielle et textuelle。文档同时强调了两个关键设计坐标换算该 composable 会把屏幕坐标转换为画布坐标并在一次交互的整个生命周期内保持指针捕获pointer capture定位这是一个低层bas niveauAPI主要面向“自己拥有画布、希望构建干净界面”的编辑器外壳组件而非高层封装。在 Vue SDK 中useCanvasInput与useCanvas负责 CanvasKit 渲染表面的创建与维护见 use-canvas.md和useTextEdit负责文本输入见 use-text-edit.md三者通常搭配使用useCanvas管渲染useCanvasInput管交互useTextEdit管画布内文本编辑。它在 SDK 公开入口 packages/vue/src/index.ts 中被导出。二、函数签名与参数说明虽然法语文档以useCanvasInput(options)概括实际源码 packages/vue/src/canvas/useCanvasInput.ts 中的签名更为精确是理解其行为的权威依据export function useCanvasInput( canvasRef: RefHTMLCanvasElement | null, editor: Editor, hitTestSectionTitle: (cx: number, cy: number) SceneNode | null, hitTestComponentLabel: (cx: number, cy: number) SceneNode | null, hitTestFrameTitle: (cx: number, cy: number) SceneNode | null, onCursorMove?: (cx: number, cy: number) void, onActivate?: () void, isEnabled: () boolean () true )各参数含义如下参数类型说明canvasRefRefHTMLCanvasElement \| null目标画布元素的引用所有事件都绑定在此元素上editorEditor来自open-pencil/core/editor的编辑器实例通常由createEditor创建、useEditor从上下文取回hitTestSectionTitle(cx, cy) SceneNode \| null命中测试给定画布坐标返回命中的 Section 标题节点hitTestComponentLabel(cx, cy) SceneNode \| null命中测试返回命中的组件标签节点hitTestFrameTitle(cx, cy) SceneNode \| null命中测试返回命中的 Frame 标题节点onCursorMove可选回调指针移动时回调参数为画布坐标(cx, cy)可用于同步外部悬浮信息onActivate可选回调每次mousedown时触发编辑器外壳用它做“激活面板”等处理isEnabled() boolean交互开关默认恒为true为false时忽略输入多面板场景下用于区分当前活动面板返回对象包含供外壳组件消费的状态与操作源码 useCanvasInput.tsdrag当前拖拽状态RefDragState | null用于驱动覆盖层 UIcursorOverrideRefstring | null画布上的光标覆盖值画布标签Frame/Section 标题编辑canvasLabelEdit、updateCanvasLabelEdit、commitCanvasLabelEdit、cancelCanvasLabelEditAuto Layout 内边距编辑autoLayoutPaddingEdit、updateAutoLayoutPaddingEdit、commitAutoLayoutPaddingEdit、cancelAutoLayoutPaddingEditcleanupInteractions()取消进行中的交互、清空临时反馈并复位修饰键状态常用于面板失活或组件卸载时。注意法语文档把参数概括为options对象德语版文档则给出位置参数形式的调用示例见 packages/docs/de/programmable/sdk/api/composables/use-canvas-input.md源码实现采用的是上面这组位置参数。三、坐标换算从屏幕坐标到画布坐标文档明确提及“composable 把屏幕坐标转换成画布坐标”。这一逻辑集中在 packages/vue/src/shared/input/geometry.ts 的getPointerCoords中export function getPointerCoords(e: MouseEvent, canvas: HTMLCanvasElement | null, editor: Editor) { if (!canvas) return { sx: 0, sy: 0, cx: 0, cy: 0 } const rect canvas.getBoundingClientRect() const sx e.clientX - rect.left const sy e.clientY - rect.top const { x: cx, y: cy } editor.screenToCanvas(sx, sy) return { sx, sy, cx, cy } }换算分两步客户端坐标 → 画布像素坐标用getBoundingClientRect()减去画布左上角得到sx/sy画布像素坐标 → 画布逻辑坐标通过editor.screenToCanvas(sx, sy)得到cx/cy。screenToCanvas内部会考虑编辑器的平移pan与缩放zoom因此useCanvasInput处理的永远是逻辑坐标缩放平移无需你手工处理。此外packages/vue/src/canvas/pointer/use.ts 的createCanvasPointer在换算基础上又封装了三类能力canvasToLocal画布坐标 → 某个节点局部坐标供进入容器内部后的命中测试使用、hitTestInScope在当前“进入的容器”或当前页范围内做命中测试支持深/浅两种模式、isInsideContainerBounds判断某点是否落在容器边界内。这三者与三个标题命中测试函数一起组成了hitFns供拖拽调度与光标更新共用。四、统一拖拽状态机DragStateuseCanvasInput的核心是一个dragref所有进行中的交互都归约为统一的拖拽状态联合类型DragState定义于 packages/vue/src/shared/input/types.tsexport type DragState | DragDraw // 绘图工具拖拽矩形、椭圆、线条…… | DragMove // 移动选中对象 | DragPan // 抓手/空格平移视图 | DragResize // 缩放 | DragMarquee // 框选 | DragRotate // 旋转 | DragPen // 钢笔路径绘制 | DragTextSelect // 文本选区 | DragEditNode // 矢量节点编辑 | DragEditHandle // 贝塞尔手柄编辑 | DragBendHandle // 弯曲手柄编辑 | DragGuide // 标尺/参考线拖拽以DragMove为例types.ts它记录起点、当前位置、已应用的位移增量appliedDx/appliedDy、是否已判定为拖拽dragStarted、所有对象的原始位置以及duplicated拖拽时按住修饰键复制、autoLayoutParentId、brokeFromAutoLayout等自动布局相关信息。DragResizetypes.ts则保存origRect、原矢量网络、填充/描边几何、派生文本字形等快照保证缩放预览可随时回滚。onMouseMoveuseCanvasInput.ts是一个集中的分发器根据drag.value.type把移动事件分别交给handlePanMove、guideInput.handleMove、handleRotateMove、handleMoveMove、applyResize、handlePenDragMove、handleNodeEditMove、handleBendHandleMove、handleDrawMove、handleMarqueeMove等实现。无拖拽时它仍会驱动钢笔悬浮updatePenHover、矢量节点悬浮updateNodeEditHover、参考线悬浮与光标更新保证“仅悬停不拖拽”的场景也有即时反馈。onMouseUpuseCanvasInput.ts按类型提交结果commitResizePreview提交缩放、editor.penCommit(true)提交钢笔路径、editor.commitRotation提交旋转、draw.commit()提交绘图、setMarquee(null)结束框选。这样所有交互都遵循“开始 → 预览 → 提交/取消”的同一生命周期。五、指针捕获与事件绑定文档强调“在交互期间保持指针捕获”。这一实现位于 useCanvasInput.tsfunction onPointerDown(e: PointerEvent) { if (e.pointerType ! mouse || e.button ! 0) return canvasRef.value?.setPointerCapture(e.pointerId) }pointerdown时若为鼠标主键立即调用setPointerCapture保证即使指针移出画布后续的mousemove/mouseup仍派发到画布拖拽不中断pointerup/pointercancel时释放捕获并分别走“提交”与“取消”路径。事件绑定通过useEventListener完成useCanvasInput.ts包括画布上的pointerdown/pointerup/pointercancel/dblclick/mousedown/mousemove/mouseup/mouseleave以及 window 级的keydown/keyup追踪 Alt/Meta/Ctrl 修饰键、blur失焦时复位测量修饰键并取消交互、捕获阶段的mouseup防止指针离开画布后拖拽卡死和捕获阶段的Escape取消绘图/旋转。另外它还订阅了编辑器的若干事件useCanvasInput.tsrotation:preview-changed、tool:changed、selection:changed、page:changed、graph:replaced。当工具切换、选区变化或页面/图被替换时进行中的绘图与旋转交互会被自动取消避免状态错乱组件卸载时onScopeDispose会统一停止监听并调用cancelPointerInteraction。六、工具联动与修饰键语义onMouseDownuseCanvasInput.ts是交互入口先触发onActivate再依据isEnabled判断是否处理随后提交可能存在的 Auto Layout 内边距编辑、聚焦画布、清空悬浮节点并在参考线拖拽标尺拖出/已有参考线之后把事件交给handleToolMouseDown统一派发。工具与节点类型的映射TOOL_TO_NODEtypes.ts说明绘图工具FRAME/SECTION/RECTANGLE/ELLIPSE/LINE/POLYGON/STAR/TEXT会创建对应类型的节点。修饰键在交互中有明确语义由updateModifier跟踪useCanvasInput.ts并在移动/释放分支中生效Shift缩放保持宽高比、旋转按角度约束、钢笔切线约束Alt测量模式开关配合画布内测量、参考线复制拖拽、节点编辑分支调整Meta/Ctrl测量模式升级为“deep”、拖拽复制、节点编辑分支的精确控制空格临时切换到抓手平移setupPanZoom与useSpaceHeld配合实现。值得留意的是测量模式measurementcanMeasureuseCanvasInput.ts要求指针在画布内、无拖拽、处于 SELECT 工具且有选中对象、且不在文本/节点/钢笔编辑状态此时按住 Alt 会以shallow/deep两种深度调用editor.setMeasurementMode驱动画布内测量反馈与光标覆盖。七、真实用法EditorCanvas 外壳组件该 API 的实际调用者正是主应用中的 src/components/EditorCanvas.vue。其调用方式EditorCanvas.vue是理解各参数实战含义的最佳示例const { cursorOverride, canvasLabelEdit, updateCanvasLabelEdit, commitCanvasLabelEdit, cancelCanvasLabelEdit, autoLayoutPaddingEdit, updateAutoLayoutPaddingEdit, commitAutoLayoutPaddingEdit, cancelAutoLayoutPaddingEdit, cleanupInteractions } useCanvasInput( canvasRef, store, hitTestSectionTitle, hitTestComponentLabel, hitTestFrameTitle, updatePaneCursor, activatePane, () isActivePane.value )要点三个命中测试函数hitTestSectionTitle等来自编辑器外壳自身的场景查询逻辑把“哪里是 Section 标题”这类自定义判定交给调用方updatePaneCursor作为onCursorMove把指针画布坐标同步给面板层activatePane作为onActivate保证点击画布时面板被激活isEnabled返回() isActivePane.value实现多面板多画布共存时只有活动面板响应输入外壳在面板失活watch(isActivePane)与组件卸载onUnmounted时调用cleanupInteractions()EditorCanvas.vue与useTextEdit(canvasRef, store, { isEnabled: () isActivePane.value })和useCanvasDrop一起构成完整画布外壳。返回的cursorOverride、autoLayoutPaddingEdit等还驱动着覆盖层例如内边距编辑器的锚点坐标由paddingEditorAnchor计算EditorCanvas.vue再通过useCanvasVirtualReference定位浮层实现拖拽内边距时实时显示数值编辑器的效果。八、相关 API 与进一步阅读useCanvasInput通常与以下 API 配套使用useCanvas负责 CanvasKit 加载、surface 创建/重建、尺寸观察、像素比调整与刷新请求是渲染侧的对偶 composableuseTextEdit负责 textarea 回退的文本输入、IME 组合、光标闪烁与样式快捷键与useCanvasInput的文本编辑入口互补useEditor/provideEditor从 Vue 注入上下文取得Editor实例导出于 packages/vue/src/index.ts。若需更完整的接入方式可参考 EditorCanvas.vue 与 SDK 文档目录 packages/docs/fr/programmable/sdk底层坐标换算与命中测试实现在 packages/vue/src/shared/input/geometry.ts 与 packages/vue/src/canvas/pointer/use.ts。官方还提供了德语、西班牙语、意大利语、波兰语等多语言版本的同主题文档如 packages/docs/de/programmable/sdk/api/composables/use-canvas-input.md供交叉参考。总结useCanvasInput是 OpenPencil Vue SDK 中画布交互的总调度器它以统一的DragState状态机覆盖移动、缩放、旋转、平移、框选、绘图、钢笔、参考线与矢量/文本编辑通过screenToCanvas完成坐标换算借助 Pointer Capture 与全局事件监听保证交互完整性并通过回调与isEnabled机制适配多面板编辑器外壳。结合 EditorCanvas.vue 的实战用法你可以快速在自己的 Vue 组件中搭建出与 OpenPencil 主应用一致的画布交互体验。赞分享前端桌面应用AI 应用MCP 服务【免费下载链接】open-pencilAI-native design editor. Open-source Figma alternative.项目地址https://gitcode.com/gh_mirrors/op/open-pencil点击查看免费下载相关推荐OpenPencil 的 useCanvasInput把指针事件接入编辑器画布的 Vue ComposableOpenPencil 的 useCanvasInput把指针事件接入编辑器画布的 Vue Composable 在 OpenPencil开源 AI 原生设计前端桌面应用AI 应用MCP 服务OpenPencil useCanvasInput 完全指南为 Vue 画布组件接入选择、拖拽、缩放与工具交互OpenPencil useCanvasInput 完全指南为 Vue 画布组件接入选择、拖拽、缩放与工具交互 useCanvasInput 是 OpenPe前端桌面应用AI 应用MCP 服务OpenPencil Vue SDK 的 useTextEdit 指南画布文本编辑、IME 组合与 SceneGraph 同步全解析OpenPencil Vue SDK 的 useTextEdit 指南画布文本编辑、IME 组合与 SceneGraph 同步全解析 useTextEdit前端桌面应用AI 应用MCP 服务上一篇Python模糊字符串匹配神器TheFuzz10分钟快速入门指南下一篇Ruby爬虫框架Wombat用优雅DSL轻松提取结构化数据创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表