Fabric.js Document Engine

搜索文档

查找页面或章节

EN

原生 JavaScript

查看 Markdown

不用框架,也可以不用构建工具,只有引擎和 DOM。

引擎的核心代码里没有任何框架相关的代码,所以 Fabric.js 原生 JavaScript 用起来和任何框架一样顺手。你创建画布、创建引擎,再根据它的状态更新工具栏。

页面

<div role="toolbar">
  <button id="undo">Undo</button>
  <button id="redo">Redo</button>
  <button id="save">Save</button>
  <span id="status" aria-live="polite"></span>
</div>
<canvas id="editor"></canvas>

脚本

import { Canvas } from "fabric";
import {
  bindKeyboardShortcuts,
  createDocumentEngine,
  createDocumentStateStore,
} from "fabricjs-document-engine";
import { createLocalStorage } from "fabricjs-document-engine/storage";
 
const canvas = new Canvas("editor", { width: 800, height: 500 });
const engine = createDocumentEngine({
  canvas,
  storage: createLocalStorage(),
  autosave: true,
});
bindKeyboardShortcuts(engine);
 
const undo = document.querySelector<HTMLButtonElement>("#undo")!;
const redo = document.querySelector<HTMLButtonElement>("#redo")!;
const save = document.querySelector<HTMLButtonElement>("#save")!;
const status = document.querySelector("#status")!;
 
undo.addEventListener("click", () => engine.undo());
redo.addEventListener("click", () => engine.redo());
save.addEventListener("click", () => engine.save());
 
const store = createDocumentStateStore(engine);
 
function render() {
  const state = store.getSnapshot();
  undo.disabled = !state.canUndo;
  redo.disabled = !state.canRedo;
  save.disabled = !state.isDirty;
  status.textContent = state.saveStatus;
}
 
store.subscribe(render);
render();

createDocumentStateStore 提供一个快照,里面有工具栏需要的全部状态。它只在有订阅者时才监听引擎。

用事件代替 store

如果你只要一个值,监听单个事件就行:

engine.on("history:change", ({ canUndo, canRedo }) => {
  undo.disabled = !canUndo;
  redo.disabled = !canRedo;
});

on 会返回一个取消订阅的函数。完整列表见事件。

不用打包工具

Fabric.js 原生 JavaScript 也可以借助 import map 直接从 CDN 加载。这个包以 ES 模块发布,不用框架也不用打包:

<script type="importmap">
  {
    "imports": {
      "fabric": "https://cdn.jsdelivr.net/npm/fabric@7/+esm",
      "fabricjs-document-engine": "https://cdn.jsdelivr.net/npm/fabricjs-document-engine@1/+esm"
    }
  }
</script>

想一步步不用框架做出编辑器,请跟着编辑器教程。