标尺与参考线
Ydesign 内置了 标尺(Ruler)+ 参考线(Guidelines) 的能力,覆盖了画布对位 / 元素对齐 / 视觉草图常见的辅助场景。整个能力由:
@ydesign/core里的RulerHandler(注册在editor.rulerHandler)@ydesign/react-editor里的<RulerButton />(画布右下角的开关按钮)
两部分组成,可以分别独立使用。
快速接入
把 <RulerButton /> 放在 <WorkspaceWrap> 里,和 <ZoomButtons /> 并列即可:
import { DesignEditorContainer, SidePanelWrap, WorkspaceWrap } from '@ydesign/react-editor';
import Workspace from '@ydesign/react-editor/canvas/workspace';
import { ZoomButtons } from '@ydesign/react-editor/toolbar/zoom-buttons';
import { RulerButton } from '@ydesign/react-editor/toolbar/ruler-button';
<DesignEditorContainer>
<SidePanelWrap>{/* ... */}</SidePanelWrap>
<WorkspaceWrap>
<Workspace store={store} />
<ZoomButtons store={store} />
<RulerButton store={store} />
</WorkspaceWrap>
</DesignEditorContainer>;
<RulerButton /> 自带:
- 开关:点按钮 → 下拉菜单 → "显示标尺和参考线"切换;状态记忆在
localStorage,刷新后保持 - 清除参考线:菜单第二项;只有当画布上至少存在一条参考线时可点
- 多语言:会读取
translate('toolbar.ruler')/toolbar.rulerShow/toolbar.rulerClear
用户交互
启用标尺后:
| 操作 | 效果 |
|---|---|
| 鼠标悬停在标尺区域 | 光标变 ns-resize / ew-resize |
| 在标尺区域按下鼠标拖入画布 | 拖出一条参考线 |
| 选中参考线(点击它) | 参考线变 蓝色,同时标尺顶部 / 左侧蓝色高亮显示当前坐标 |
| 拖动参考线 | 跟随鼠标移动;同步更新标尺数字 |
| 拖动参考线进入标尺区域 | 鼠标光标变为 🚫 禁止图标,提示"松手即删除" |
| 拖动参考线回到标尺区域松开 | 自动删除该参考线(鼠标光标自动恢复) |
| 缩放画布 | 标尺刻度密度自适应(缩放越大刻度越密) |
| 选中任意对象 | 标尺顶部 / 左侧出现 蓝色高亮区段,两端显示对象的 left / right、top / bottom |
📍 标尺坐标系的原点 (0, 0) 对应 workarea 的左上角,与"位置"工具栏里的 X / Y 显示完全一致。
核心能力 API(editor.rulerHandler)
开关 / 状态
editor.rulerHandler.enable(); // 显示标尺
editor.rulerHandler.disable(); // 隐藏标尺(参考线一并隐藏)
editor.rulerHandler.toggle(); // 切换
editor.rulerHandler.isEnabled; // boolean,当前是否启用
参考线管理
editor.rulerHandler.clearGuidelines(); // 移除所有参考线
editor.rulerHandler.showGuidelines(); // 显示所有参考线(不影响 isEnabled)
editor.rulerHandler.hideGuidelines(); // 隐藏所有参考线
editor.rulerHandler.hasGuidelines(); // boolean,画布上是否存在参考线
命中检测(高级)
editor.rulerHandler.isPointOnRuler(point); // 'horizontal' | 'vertical' | false
判断给定的 viewport 坐标(屏幕像素,相对 canvas 左上角)是否落在标尺区域。常用于自定义事件。
自定义外观
RulerHandler 支持在初始化时传入配置项:
import RulerHandler, { type RulerHandlerOptions } from '@ydesign/core/dist/handlers/RulerHandler';
const options: RulerHandlerOptions = {
ruleSize: 20, // 标尺宽高,默认 20
fontSize: 10, // 刻度字号,默认 10
backgroundColor: '#fff', // 标尺背景色
borderColor: '#ddd', // 标尺边框色
textColor: '#888', // 刻度数字颜色
highlightColor: '#007fff', // 选中对象 / 选中参考线时的高亮色
guidelineColor: '#4bec13', // 参考线默认颜色
};
如果需要替换默认配置,可以在自己的应用里创建 Editor 时手动注入。当前 <RulerButton /> 用默认配置即可,绝大多数场景无需调整。
与持久化 / 历史的关系
参考线对持久化系统是透明的:
- 不进
store.objects(不会触发自动保存) - 不进
historyHandler(撤销 / 重做时不会"撤销出"参考线,也不会消失) - 不进
excludeFromExport: true(导出 PNG / JSON 时被跳过)
也就是说,参考线只是当前编辑会话内的视觉辅助,关闭浏览器就消失。需要"保存参考线布局"的场景,建议你自己读取 editor.rulerHandler 里的对象状态做单独存储。
实现细节(可跳过)
- 标尺本身不是 fabric 对象,而是订阅
after:render之后在画布主 context 上手动绘制 —— 因此不会出现在canvas.toJSON()里 - 参考线是普通的
fabric.Line(带isGuideline: true标记),但stroke设为透明,由我们在after:render阶段自定义渲染(这样不受canvas.clipPath裁剪,可以延伸到 workarea 之外) - 命中检测覆写了
containsPoint方法,用"鼠标到参考线的垂直距离 ≤ 6 屏幕像素"判定 —— 比 fabric 默认的长跨度命中更可靠 - 每次
object:added后自动把参考线置顶,保证图片 / 文字下方的参考线仍然可被选中
FAQ
Q:为什么参考线穿过图片时也能选中?
启用标尺时会订阅 object:added,新对象一旦加入就把所有参考线置顶。所以即使图片在视觉上"覆盖"了参考线,hit-test 也会先命中参考线。
Q:参考线会被保存到模板 JSON 里吗?
不会。excludeFromExport: true 已经设置,store.objects 中也会过滤掉,因此你可以放心使用而不必担心污染数据。
Q:可以隐藏标尺但保留参考线吗?
可以。直接调 disable() 关闭标尺,参考线对象会自动设为 visible: false,再次 enable() 时恢复显示。如果需要长期"无标尺有参考线"的状态,建议自己先 enable() 再用 CSS / 业务代码盖住标尺区域。