- 前端
- 桌面应用
- AI 应用
- MCP 服务
【免费下载链接】open-pencil
AI-native design editor. Open-source Figma alternative.
toolCursor(tool, override?)是 open-pencil(AI-native 设计编辑器,开源 Figma 替代方案)Vue SDK 提供的一个轻量工具函数:它将编辑器当前激活的工具映射为对应的 CSS 光标值,并允许通过override参数显式替换结果。本篇围绕该 API 的签名、工具-光标映射表、覆盖机制,以及它在 open-pencil 画布组件中的真实调用链展开,帮助你在自研画布外壳或工具栏 UI 中实现与主编辑器一致的光标行为。
一、API 签名与定位
toolCursor定义于 tool-cursor/index.ts,从 SDK 包入口 index.ts 导出,并在 Vue 包 README 的 API 清单中列为顶层可用 API。其签名如下:
export function toolCursor(tool: Tool, override?: string | null): stringtool:编辑器工具标识,类型为Tool(联合类型,共 11 个成员,定义于 editor/types.ts);override:可选的字符串覆盖值,可为null;- 返回值:最终应应用的 CSS
cursor值字符串。
实现本身只有三行核心逻辑:
export function toolCursor(tool: Tool, override?: string | null): string { if (override) return override return TOOL_CURSORS[tool] ?? 'default' }从源码结构看,该函数被归类于 Vue SDK 的横切内部工具(ARCHITECTURE.md 提到toolCursor位于跨领域内部模块),但其职责非常聚焦:让自定义画布外壳(custom canvas shell)或工具栏 UI 无需自行维护「工具 → 光标」的映射,即可获得与主编辑器一致的光标体验。
二、完整的工具-光标映射表
映射关系由源文件顶部的TOOL_CURSORS常量表给出(index.ts),完整覆盖Tool联合类型的所有 11 个成员:
工具(Tool) | 光标值 | 语义说明 |
|---|---|---|
SELECT | default | 常规箭头光标,用于选择与拖拽 |
FRAME | crosshair | 十字准星,用于绘制画框 |
SECTION | crosshair | 十字准星,用于绘制分区 |
RECTANGLE | crosshair | 十字准星,用于绘制矩形 |
ELLIPSE | crosshair | 十字准星,用于绘制椭圆 |
LINE | crosshair | 十字准星,用于绘制直线 |
POLYGON | crosshair | 十字准星,用于绘制多边形 |
STAR | crosshair | 十字准星,用于绘制星形 |
TEXT | text | 文本 I 形光标,用于插入文字 |
PEN | crosshair | 十字准星,用于钢笔路径绘制 |
HAND | grab | 抓手光标,用于画布平移 |
可以看出映射规则相当直观:所有“画东西”的工具(形状、画框、钢笔)统一用crosshair,选择工具用default,文本工具用text,手型工具用grab。此外TOOL_CURSORS[tool] ?? 'default'提供了一个兜底:若传入的tool不在表中(例如未来扩展了新工具而映射表尚未更新),函数会安全地回退到default,而不是返回undefined。
三、override 机制:显式覆盖优先
第二个参数override遵循“真值优先”策略:只要传入非空字符串,就直接返回该值,完全绕过工具映射:
if (override) return override这意味着:
toolCursor('SELECT', 'nwse-resize')返回'nwse-resize';toolCursor('SELECT', null)或toolCursor('SELECT')返回'default';override传空字符串''时按 falsy 处理,仍走工具映射(从源码的if (override)真值判断可以确认)。
这个设计对应的实际场景是:工具只决定“基础光标”,而瞬时的交互状态(悬停命中可编辑区域、正在拖拽、正在绘制路径等)可以临时覆盖它。open-pencil 的画布层正是这样使用的。
四、真实调用链:EditorCanvas 如何组合 toolCursor 与交互覆盖
在主应用组件 EditorCanvas.vue 中,光标由一个响应式计算属性产生:
const cursor = computed(() => toolCursor(store.state.activeTool, cursorOverride.value))其中两个输入各有来源:
store.state.activeTool:编辑器共享状态中的当前激活工具,类型即前文提到的Tool;cursorOverride:由画布输入组合式 useCanvasInput 返回的Ref<string | null>,用于承载交互期间产生的临时光标。
cursorOverride的典型写入点包括:
- 悬停命中检测:指针移动时,
useCanvasInput在 refreshMeasurement 中调用updateHoverCursor(...),根据指针位置命中的节点类型(例如可缩放的边、可拖拽的引导线)写出对应的临时光标; - 引导线拖拽:通过
createGuideInput的setCursor回调写入(useCanvasInput.ts); - 钢笔绘制过程:pen/input.ts 在路径构建期间将
cursorOverride置为'crosshair',保证即使底层工具状态有细微变化,绘制中光标也稳定; - 交互结束清理:交互 cleanup 阶段会将其重置为
null(useCanvasInput.ts),使光标回落到toolCursor的基础映射。
由此形成的分层模型是:activeTool决定基础光标,cursorOverride在交互生命周期内做短时覆盖,toolCursor负责把二者合并为最终值。自定义画布外壳只需复制「computed(() => toolCursor(activeTool, override))」这一行组合逻辑,就能获得与主编辑器一致的三层行为。
五、在自定义画布外壳中使用
结合上文调用链,一个最小的自研工具栏/画布外壳集成示例如下:
<script setup lang="ts"> import { computed, ref } from 'vue' import { toolCursor } from '@open-pencil/vue' const activeTool = ref('SELECT') // 由你的工具状态管理写入 const override = ref<string | null>(null) // 交互期间临时写入 const cursor = computed(() => toolCursor(activeTool.value, override.value)) </script> <template> <div class="my-canvas" :style="{ cursor }"> <!-- 自定义画布内容 --> </div> </template>要点:
activeTool的取值必须来自Tool联合类型的 11 个成员,映射表与兜底逻辑见 tool-cursor/index.ts;override建议只写入瞬时的交互光标,交互结束后重置为null,与 useCanvasInput.ts 中 cleanup 时的行为保持一致;- 若需要配合画布与编辑器命令使用,可参考 SDK 组合式 API useCanvas 与
useEditorCommands的相关文档页。
六、小结与延伸阅读
toolCursor虽然只有十余行实现,却浓缩了 open-pencil 处理工具光标的完整约定:11 个工具到 CSS 光标的固定映射、default兜底,以及“工具为基础、交互为覆盖”的两层模型。核心实现与证据路径如下,便于继续深入:
- 实现:packages/vue/src/editor/tool-cursor/index.ts
Tool类型定义:packages/core/src/editor/types.ts- 应用侧调用:src/components/EditorCanvas.vue
- 覆盖值来源:packages/vue/src/canvas/useCanvasInput.ts、packages/vue/src/canvas/pen/input.ts
- API 清单:packages/vue/README.md
- 前端
- 桌面应用
- AI 应用
- MCP 服务
【免费下载链接】open-pencil
AI-native design editor. Open-source Figma alternative.
相关推荐
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考