小地图 API
MinimapPlugin从@skynote/plugins-basic根入口导入,负责概览数据与导航,不自带DOM、Canvas绘制或面板。接入示例与产品表现见小地图指南。
构造与启用
new MinimapPlugin()没有配置参数,安装后默认关闭。将实例传入Editor的plugins,完成安装和宿主挂载,再调用setEnabled(true)。不要重复调用install;由引擎完成装配与卸载。
import { SkyNoteEditor } from '@skynote/editor';
import { LeaferAdapter } from '@skynote/renderer-leafer';
import { MinimapPlugin, type MinimapSnapshot } from '@skynote/plugins-basic';
export function mountMinimapExample(
container: HTMLElement,
draw: (snapshot: MinimapSnapshot | null) => void
): { editor: SkyNoteEditor<HTMLElement>; minimap: MinimapPlugin; destroy: () => void } {
const minimap = new MinimapPlugin();
const editor = new SkyNoteEditor<HTMLElement>({ renderer: new LeaferAdapter(), plugins: [minimap] });
let frame: number | undefined;
const unsubscribe = minimap.subscribe(() => {
if (frame !== undefined) return;
frame = requestAnimationFrame(() => {
frame = undefined;
draw(minimap.getSnapshot({ width: 224, height: 144 }));
});
});
function destroy(): void {
unsubscribe();
if (frame !== undefined) cancelAnimationFrame(frame);
editor.destroy();
}
try {
editor.mount(container);
editor.createNode({ nodeType: 'sticky', x: 0, y: 0, options: { text: '从这里开始' } });
editor.fitContent();
minimap.setEnabled(true);
return { editor, minimap, destroy };
} catch (error) {
destroy();
throw error;
}
}示例使用224×144 CSS像素的绘制区域。修改区域尺寸时,绘制、读取快照和指针导航必须传入同一组实际尺寸。宿主可按设备像素比放大绘图缓冲区,但API仍使用CSS像素。
状态、订阅与快照
| 成员 / 签名 | 参数、返回与行为 |
|---|---|
isNavigating: boolean | 是否存在当前导航会话,不等于面板是否打开 |
setEnabled(enabled: boolean): void | 启闭概览;改变状态时清除内容缓存、焦点和导航状态并发送通知;关闭后停止场景收集 |
setFocused(focused: boolean): void | 同步小地图表面的键盘焦点;失焦会结束导航;未启用或未安装时不会进入获焦状态 |
subscribe(listener: () => void): () => void | 无参数的失效通知,返回解绑函数;注册时不立即调用;宿主收到通知后重新读取快照 |
getSnapshot(size: MinimapSize): MinimapSnapshot | null | 未安装、未启用或宽高不为正时为null;维护期间仍可返回快照,但disabled为true |
通知可能来自文档、布局、选区、主题或视口变化;用requestAnimationFrame合并绘制,不在每次通知中创建另一套完整渲染器。宿主需要初次绘制时主动读取,或在订阅后启用。快照和集合按只读数据消费,不修改其内容。
类型与坐标约定
| 类型 | 字段 |
|---|---|
MinimapSize | 只读width/height: number,小地图绘制区域CSS像素尺寸 |
MinimapProjection | 只读scale/x/y: number,世界坐标到小地图像素的缩放与平移 |
MinimapNode | id: string、bounds: RectBounds(世界坐标)、container: boolean |
MinimapConnector | id: string、points: readonly Point[]、bounds: RectBounds,均为世界几何 |
MinimapContent | nodes、connectors只读数组;bounds: RectBounds | null为空内容时可为null |
MinimapSnapshot还包含:
| 字段 | 类型与说明 |
|---|---|
content | MinimapContent,可见节点与连线路由的几何示意 |
projection | MinimapProjection,内容和视口共用的投影;导航中使用会话开始时的投影 |
viewport | RectBounds,主画布当前可视区域的世界矩形 |
theme | CanvasTheme,绘制时使用的主题 |
selectedNodes/selectedConnectors | ReadonlySet<string>,当前选区ID |
navigating | boolean,是否存在导航会话 |
disabled | boolean,当前维护冻结状态;不是文档只读标记 |
世界点映射公式为mapX = worldX * scale + x、mapY = worldY * scale + y;逆变换先减平移再除scale。所有传入导航的point都是相对小地图绘制区域的CSS像素坐标,不能直接使用页面clientX/clientY或世界坐标。
指针导航
| 方法 / 签名 | 说明 |
|---|---|
beginNavigation(pointerId: number, point: Point, size: MinimapSize): boolean | 快照不可用、维护冻结或已有导航时返回false;成功时记录投影并立即导航,返回true |
moveNavigation(pointerId: number, point: Point): void | 仅移动匹配pointerId的会话,其他指针被忽略 |
endNavigation(pointerId: number): void | 结束匹配指针的导航;不是该指针则不执行 |
cancelNavigation(): void | 结束当前导航并通知重绘;不会把视口恢复到拖动前的位置 |
zoomAt(point: Point, size: MinimapSize, factor: number): void | 以对应世界点为锚缩放;factor须为有限正数;快照不可用、冻结或导航中不执行 |
panBy(x: number, y: number): void | 按主画布屏幕像素增量导航,视口平移量分别减去x/y;未启用、未安装、冻结或导航中不执行 |
点在视口框内时保留抓取偏移,拖动不会突然跳到框中心;点击框外时以点击点为中心导航。导航只更新会话视口,不产生文档或撤销历史。只读文档仍允许导航,维护冻结则不允许。
宿主只在beginNavigation返回true后捕获对应指针,PointerUp结束并释放捕获,PointerCancel、失焦和卸载时取消。主画布工具、缩放、尺寸或文档替换等变化可能提前结束会话;宿主不能仅凭“之前返回过true”继续显示抓取态,应读取isNavigating或最新快照。
键盘接入
小地图表面获焦时调用setFocused(true),失焦调用false,并将键盘按下、抬起和失焦通过宿主InputScope桥接分发。
| 按键 | 行为 |
|---|---|
| 方向键 | 每次40像素导航;按住Shift时160像素 |
+ / = / - | 按1.2倍或其倒数缩放,导航手势中不缩放 |
Esc | 结束当前导航,不回滚此前视口变化 |
不要额外绑定一套绕过输入作用域的全局document快捷键。键盘接入协议见InputScope。
投影函数与常量
| 导出 | 说明 |
|---|---|
MINIMAP_PLUGIN_ID | @skynote/plugins-basic/minimap,用于识别实例,不是额外的包导入子路径 |
MINIMAP_MIN_VIEWPORT_WIDTH | 50 CSS像素,最小视口映射宽度 |
fitMinimap(content: RectBounds | null, viewport: RectBounds, size: MinimapSize): MinimapProjection | 纯投影计算,先容纳内容与视口,再用最小视口宽度约束整体映射 |
纯函数调用方提供有效、有限的边界和正尺寸,不将其当作不可信数据的校验器。正常绘制优先使用getSnapshot返回的projection,尤其导航中不能自行换算另一套投影。最小视口约束作用于内容与视口的整体映射,高度保持主视口比例;触及约束时可能裁切远处内容。
关闭与销毁
关闭面板时调用setFocused(false)、setEnabled(false),释放宿主指针捕获并取消待执行绘制帧;不再需要通知时调用subscribe返回的解绑函数。销毁整张画布由Editor.destroy完成,不手动调用插件unmount。
引擎卸载插件时会清空内容、导航和监听器并关闭插件;宿主仍负责自己的DOM监听、绘图资源与异步任务。示例不代表完整小地图UI或大场景帧率已经验收。