从第一张画布开始
SkyNote 是一组可组合的画布 SDK。先使用 Editor 和 Leafer 渲染器创建编辑器,再按需要扩展节点、插件和产品界面。
Beta 文档预览
文档面向 0.1.0-beta.1 目标版本。当前 npm 包尚未确认公开可安装,下方安装命令为发布后的接入方式;发布前请在源码工作区体验。页面中的基础画布直接运行当前源码,不代表 npm 产物已完成验收。
安装与容器
发布后安装:
sh
npm install @skynote/editor @skynote/renderer-leafer容器必须有确定的宽高。页面退出时调用 destroy(),释放输入监听、渲染器和插件资源。
html
<div id="canvas" style="height: 480px; position: relative;"></div>
<script type="module" src="./main.ts"></script>一个完整示例
创建 basic.ts。下面是完整文件,只依赖已安装的两个包,不依赖本站主题或首页场景;它也用于下方真实演示。
ts
import { SkyNoteEditor } from '@skynote/editor';
import { LeaferAdapter } from '@skynote/renderer-leafer';
/** 运行示例与页面源码共用此文件;所有文档实体通过公开语义命令创建。 */
export function mountExample(
container: HTMLElement,
populate?: (editor: SkyNoteEditor<HTMLElement>) => void
): SkyNoteEditor<HTMLElement> {
const editor = new SkyNoteEditor<HTMLElement>({ renderer: new LeaferAdapter(), initialView: 'preserve' });
try {
editor.mount(container);
editor.engine.documentStore.batch(() => {
if (populate) {
populate(editor);
return;
}
const note = editor.createNode({
nodeType: 'sticky',
x: 0,
y: 0,
width: 190,
height: 150,
options: { text: '一个新想法\n双击,写下你的灵感。' }
});
const shape = editor.createNode({
nodeType: 'shape',
x: 300,
y: 35,
width: 180,
height: 70,
options: { label: '连接,让思路更清晰' }
});
if (!note || !shape) throw new Error('无法创建示例节点');
editor.updateNodeStyle([shape], { fill: '$teal', radius: 16 });
editor.engine.documentStore.createConnector({
connectorType: 'curved',
from: { nodeId: note },
to: { nodeId: shape }
});
editor.createNode({
nodeType: 'free-text',
x: 70,
y: 210,
width: 390,
options: { text: '拖动节点 · 双击编辑 · 空格拖动画布' }
});
}, '创建演示内容');
editor.engine.documentStore.clearHistory();
editor.fitContent();
return editor;
} catch (error) {
editor.destroy();
throw error;
}
}再创建同目录的 vanilla.ts:
ts
import { mountExample } from './basic';
/** 将basic.ts和本文件放在同一目录,在容器进入DOM后调用。 */
export function mountCanvasPage(container: HTMLElement): () => void {
const editor = mountExample(container);
return () => editor.destroy();
}最后在同目录创建main.ts,HTML中的模块脚本会执行该入口:
ts
import { mountCanvasPage } from './vanilla';
const container = document.getElementById('canvas');
if (!container) throw new Error('请先在页面中提供id为canvas的容器');
/** 独立页面加载即挂载;SPA路由离开时调用此清理函数。 */
export const destroyCanvasPage = mountCanvasPage(container);在自己的SPA路由退出时调用导出的destroyCanvasPage()。纯TypeScript接入需要项目自己的构建工具,以上HTML与三个TS文件可放入现有的Vite等工程中;它们不是直接双击HTML就能运行的无构建脚本。
免费体验,点击后加载;修改只保留在当前页面。
在 Vue 中使用
在 onMounted 中挂载,在 onBeforeUnmount 中销毁。编辑器实例保存在普通变量,或使用 markRaw / shallowRef;不要放入深度响应式代理。
完整单文件组件、SSR与异步卸载处理见Vue接入。
渲染器依赖浏览器环境。SSR / 静态生成站点应在客户端动态导入,不能在服务端初始化画布。
从源码工作区运行
维护者已检出四个基础包与本站时,在工作区根目录执行:
sh
pnpm install
pnpm --filter @skynote/docs-site dev本站使用端口 5174。高级插件演示的宿主配置见示例与体验。
常见问题
| 现象 | 检查方法 |
|---|---|
| 画布空白 | 确认容器已经挂载,宽高不为零;在隐藏面板中初始化后需等待布局就绪 |
window / document 未定义 | 把运行时导入与挂载放到客户端生命周期,不在SSR阶段创建Leafer实例 |
| 快捷键没有响应 | 先点击画布,让输入作用域获得焦点;宿主工具栏按下时应保留画布焦点 |
| 重复挂载后监听越来越多 | 页面卸载时调用destroy();暂时卸载渲染器才使用unmount() |
| 安装命令找不到包 | 当前仍是Beta目标文档,先按上方源码工作区方式运行;不将目标版本视为已发包 |