Skip to content

@plait 系列库 API 完整文档

概述

@plait 是一个强大的画图框架系列,为 Drawnix 提供了完整的绘图、思维导图和文本编辑功能。本文档详细介绍了项目中使用的所有 @plait 相关库的 API、使用方法和示例。


📦 库概览

库名称版本主要功能核心特性
@plait/core^0.86.1核心框架画板、元素管理、变换操作、插件系统
@plait/draw^0.86.1绘图功能几何图形、箭头、图像、表格、矢量线
@plait/mind^0.86.1思维导图节点管理、布局算法、分支样式
@plait/common^0.86.1通用工具分组、图片、文本、属性管理
@plait/layouts^0.86.1布局算法思维导图布局、自动排列
@plait/text-plugins^0.86.1文本插件富文本编辑、链接、格式化
@plait-board/react-board-React组件React集成、组件封装、事件处理

🎯 @plait/core - 核心框架

核心接口

PlaitBoard - 画板核心接口

typescript
interface PlaitBoard {
    // 基础属性
    viewport: Viewport;                    // 视口信息
    children: PlaitElement[];              // 子元素列表
    theme: PlaitTheme;                     // 主题配置
    operations: PlaitOperation[];          // 操作历史
    selection: Selection | null;           // 当前选择
    pointer: PlaitPointerType | string;    // 当前指针类型
    history: PlaitHistory;                 // 历史记录
    options: PlaitBoardOptions;            // 板配置选项

    // 核心方法
    undo(): void;                          // 撤销操作
    redo(): void;                          // 重做操作
    apply(operation: PlaitOperation): void; // 应用操作
    onChange(): void;                      // 变更回调
    afterChange(): void;                   // 变更后回调

    // 事件处理
    mousedown(event: MouseEvent): void;    // 鼠标按下
    mousemove(event: MouseEvent): void;    // 鼠标移动
    mouseup(event: MouseEvent): void;      // 鼠标释放
    keyDown(event: KeyboardEvent): void;   // 键盘按下

    // 元素操作
    drawElement(context: PlaitPluginElementContext): ComponentType<ElementFlavour>;
    isHit(element: PlaitElement, point: Point, isStrict?: boolean): boolean;
    getRectangle(element: PlaitElement): RectangleClient | null;
}

PlaitElement - 元素基类

typescript
interface PlaitElement {
    id: string;                            // 唯一标识
    children?: PlaitElement[];             // 子元素
    points?: Point[];                      // 坐标点
    type?: string;                         // 元素类型
    groupId?: string;                      // 所属组ID
    angle?: number;                        // 旋转角度
    [key: string]: any;                    // 扩展属性
}

PlaitPointerType - 指针类型枚举

typescript
enum PlaitPointerType {
    hand = "hand",                         // 手型工具
    selection = "selection"                // 选择工具
}

PlaitBoardOptions - 画板配置

typescript
interface PlaitBoardOptions {
    readonly?: boolean;                    // 是否只读
    hideScrollbar?: boolean;               // 隐藏滚动条
    disabledScrollOnNonFocus?: boolean;    // 非焦点时禁用滚动
    themeColors?: ThemeColor[];            // 主题颜色
}

核心工具类

PlaitBoard 工具类

typescript
const PlaitBoard = {
    // 类型检查
    isBoard(value: any): value is PlaitBoard;
    isAlive(board: PlaitBoard): boolean;

    // 路径和节点
    findPath(board: PlaitBoard, node: PlaitNode): Path;

    // DOM 获取
    getHost(board: PlaitBoard): SVGSVGElement;
    getElementHost(board: PlaitBoard): SVGSVGElement;
    getRoughSVG(board: PlaitBoard): RoughSVG;
    getBoardContainer(board: PlaitBoard): HTMLElement;

    // 状态检查
    isFocus(board: PlaitBoard): boolean;
    getPointer<T = PlaitPointerType>(board: PlaitBoard): T;
    isPointer<T = PlaitPointerType>(board: PlaitBoard, pointer: T): boolean;

    // 元素操作
    getSelectedElements(board: PlaitBoard): PlaitElement[];
    isSelectionGrip(board: PlaitBoard): boolean;
};

BoardTransforms - 画板变换操作

typescript
const BoardTransforms = {
    // 指针类型更新
    updatePointerType(board: PlaitBoard, pointer: string): void;

    // 视口操作
    updateViewport(board: PlaitBoard, viewport: Partial<Viewport>): void;

    // 主题操作
    updateTheme(board: PlaitBoard, theme: Partial<PlaitTheme>): void;

    // 选择操作
    updateSelection(board: PlaitBoard, selection: Selection | null): void;
};

核心插件

withBoard - 核心画板插件

typescript
const withBoard: (board: PlaitBoard) => PlaitBoard;

功能: 提供基础的画板功能,包括元素管理、事件处理、渲染等。

withHistory - 历史记录插件

typescript
const withHistory: (board: PlaitBoard) => PlaitBoard;

功能: 提供撤销/重做功能,管理操作历史。

withSelection - 选择插件

typescript
const withSelection: (board: PlaitBoard) => PlaitBoard;

功能: 提供元素选择、多选、选择框等功能。

使用示例

typescript
import { PlaitBoard, PlaitElement, PlaitPointerType, withBoard, withHistory, withSelection } from '@plait/core';

// 创建画板
const board = createBoard();
const enhancedBoard = withSelection(withHistory(withBoard(board)));

// 操作画板
BoardTransforms.updatePointerType(enhancedBoard, PlaitPointerType.selection);

// 获取选中元素
const selectedElements = PlaitBoard.getSelectedElements(enhancedBoard);

// 检查指针类型
if (PlaitBoard.isPointer(enhancedBoard, PlaitPointerType.hand)) {
    console.log('当前是手型工具');
}

🎨 @plait/draw - 绘图功能库

主要类型

PlaitDrawElement - 绘图元素联合类型

typescript
type PlaitDrawElement =
    | PlaitGeometry           // 几何图形
    | PlaitArrowLine         // 箭头线
    | PlaitVectorLine        // 矢量线
    | PlaitImage             // 图像
    | PlaitBaseTable         // 表格
    | PlaitSwimlane          // 泳道图;

DrawPointerType - 绘图指针类型

typescript
type DrawPointerType =
    | BasicShapes           // 基础形状
    | ArrowLineShape        // 箭头形状
    | FlowchartSymbols      // 流程图符号
    | SwimlaneDrawSymbols   // 泳道符号
    | TableSymbols          // 表格符号
    | UMLSymbols            // UML符号
    | VectorLinePointerType // 矢量线类型;

BasicShapes - 基础形状枚举

typescript
enum BasicShapes {
    rectangle = "rectangle",
    ellipse = "ellipse",
    diamond = "diamond",
    roundRectangle = "roundRectangle",
    parallelogram = "parallelogram",
    text = "text",
    triangle = "triangle",
    leftArrow = "leftArrow",
    trapezoid = "trapezoid",
    rightArrow = "rightArrow",
    cross = "cross",
    star = "star",
    pentagon = "pentagon",
    hexagon = "hexagon",
    octagon = "octagon",
    // ... 更多形状
}

PlaitGeometry - 几何图形接口

typescript
interface PlaitGeometry extends PlaitElement {
    type: 'geometry';
    shape: GeometryShapes;              // 形状类型
    text?: Element;                     // 文本元素
    width: number;                      // 宽度
    height: number;                     // 高度
    strokeWidth: number;                // 描边宽度
    strokeColor: string;                // 描边颜色
    fill?: string;                      // 填充颜色
    strokeStyle?: StrokeStyle;          // 描边样式
    angle?: number;                     // 旋转角度
    opacity?: number;                   // 透明度
}

PlaitArrowLine - 箭头线接口

typescript
interface PlaitArrowLine extends PlaitElement {
    type: 'arrow';
    points: Point[];                    // 路径点
    strokeWidth: number;                // 描边宽度
    strokeColor: string;                // 描边颜色
    startHandle: ArrowLineHandle;       // 起始手柄
    endHandle: ArrowLineHandle;         // 结束手柄
    texts?: ArrowLineText[];            // 文本标签
    strokeStyle?: StrokeStyle;          // 描边样式
    angle?: number;                     // 旋转角度
    opacity?: number;                   // 透明度
}

核心工具类

PlaitDrawElement 工具类

typescript
const PlaitDrawElement = {
    // 类型检查方法
    isGeometry(value: any): value is PlaitGeometry;
    isArrowLine(value: any): value is PlaitArrowLine;
    isVectorLine(value: any): value is PlaitVectorLine;
    isImage(value: any): value is PlaitImage;
    isTable(value: any): value is PlaitTable;
    isDrawElement(value: any): value is PlaitDrawElement;

    // 分类检查
    isBasicShape(value: any): boolean;
    isFlowchart(value: any): boolean;
    isUML(value: any): boolean;
};

DrawTransforms - 绘图变换操作

typescript
const DrawTransforms = {
    // 几何图形操作
    insertGeometry(
        board: PlaitBoard,
        points: Point[],
        shape: GeometryShapes
    ): PlaitGeometry;

    resizeGeometry(
        board: PlaitBoard,
        points: Point[],
        textHeight: number,
        path: Path
    ): void;

    setText(
        board: PlaitBoard,
        element: PlaitGeometry,
        text: Element,
        width: number,
        textHeight: number
    ): void;

    insertText(
        board: PlaitBoard,
        point: Point,
        text: string
    ): void;

    // 箭头线操作
    resizeArrowLine(
        board: PlaitBoard,
        options: ArrowLineResizeOptions,
        path: Path
    ): void;

    setArrowLineTexts(
        board: PlaitBoard,
        element: PlaitArrowLine,
        texts: ArrowLineText[]
    ): void;

    connectArrowLineToDraw(
        board: PlaitBoard,
        lineElement: PlaitArrowLine,
        handle: ArrowLineHandle,
        geometryElement: PlaitGeometry
    ): void;

    // 形状切换
    switchGeometryShape(board: PlaitBoard, shape: GeometryShapes): void;

    // 图像操作
    insertImage(
        board: PlaitBoard,
        imageItem: CommonImageItem,
        startPoint?: Point
    ): void;
};

插件配置

WithDrawOptions - 绘图插件选项

typescript
interface WithDrawOptions extends WithPluginOptions {
    customGeometryTypes: string[];    // 自定义几何形状类型
}

withDraw - 绘图插件

typescript
const withDraw: (options?: WithDrawOptions) => PlaitPlugin;

功能: 提供完整的绘图功能,包括几何图形、箭头、图像等。

使用示例

typescript
import {
    withDraw,
    DrawTransforms,
    PlaitDrawElement,
    BasicShapes,
    FlowchartSymbols
} from '@plait/draw';
import { PlaitBoard } from '@plait/core';

// 启用绘图功能
const drawPlugin = withDraw({
    customGeometryTypes: ['customHeart', 'customStar']
});

// 插入矩形
const rectangle = DrawTransforms.insertGeometry(
    board,
    [{x: 100, y: 100}, {x: 200, y: 200}],
    BasicShapes.rectangle
);

// 插入流程图符号
const processSymbol = DrawTransforms.insertGeometry(
    board,
    [{x: 300, y: 100}, {x: 400, y: 200}],
    FlowchartSymbols.process
);

// 检查元素类型
if (PlaitDrawElement.isGeometry(rectangle)) {
    console.log('这是一个几何图形');
}

// 调整图形大小
DrawTransforms.resizeGeometry(
    board,
    [{x: 100, y: 100}, {x: 250, y: 250}],
    20,
    PlaitBoard.findPath(board, rectangle)
);

🧠 @plait/mind - 思维导图库

主要类型

PlaitMind - 思维导图元素

typescript
interface PlaitMind<T = BaseData> extends MindElement<T> {
    type: 'mind' | 'mindmap';
    points: Point[];                    // 位置点
}

MindElement - 思维导图节点

typescript
interface MindElement<T = BaseData> extends BaseMindElement {
    type: 'mind_child' | 'mind' | 'mindmap';
    children: MindElement[];            // 子节点
    data: T;                            // 节点数据
}

BaseData - 基础数据结构

typescript
interface BaseData {
    topic: string;                      // 节点文本
    created?: number;                   // 创建时间
    updated?: number;                   // 更新时间
    expanded?: boolean;                 // 是否展开
    color?: string;                     // 节点颜色
    fontColor?: string;                 // 字体颜色
    fontSize?: number;                  // 字体大小
    fontWeight?: string;                // 字体粗细
    fontStyle?: string;                 // 字体样式
    textDecoration?: string;            // 文本装饰
}

MindElementShape - 节点形状枚举

typescript
enum MindElementShape {
    roundRectangle = "round-rectangle", // 圆角矩形
    underline = "underline"             // 下划线形状
}

BranchShape - 分支形状枚举

typescript
enum BranchShape {
    bight = "bight",                    // 曲线
    polyline = "polyline"              // 折线
}

MindLayoutType - 布局类型枚举

typescript
enum MindLayoutType {
    right = "right",                    // 右侧布局
    left = "left",                      // 左侧布局
    standard = "standard",              // 标准布局
    upward = "upward",                  // 向上布局
    downward = "downward",              // 向下布局
    rightBottomIndented = "right-bottom-indented",    // 右下缩进
    rightTopIndented = "right-top-indented",          // 右上缩进
    leftTopIndented = "left-top-indented",            // 左上缩进
    leftBottomIndented = "left-bottom-indented"       // 左下缩进
}

核心工具类

PlaitMind 工具类

typescript
const PlaitMind = {
    isMind(value: any): value is PlaitMind;
};

MindElement 工具类

typescript
const MindElement = {
    // 布局检查
    hasLayout(value: MindElement, layout: MindLayoutType): boolean;
    isIndentedLayout(value: MindElement): boolean;
    isMindElement(board: PlaitBoard | null, element: PlaitElement): element is MindElement;

    // 节点关系
    getParent(node: MindElement): MindElement<BaseData>;
    getRoot(board: PlaitBoard, element: MindElement): PlaitMind;
    getAncestors(board: PlaitBoard, element: MindElement): PlaitElement[];
    getDepth(element: MindElement): number;

    // 特性检查
    hasEmojis(element: MindElement): element is MindElement<EmojiData>;
    hasImage(element: MindElement): element is MindElement<ImageData>;

    // 节点操作
    isFirstChild(node: MindElement): boolean;
    isLastChild(node: MindElement): boolean;
    getSiblings(board: PlaitBoard, node: MindElement): MindElement[];
};

MindTransforms - 思维导图变换操作

typescript
const MindTransforms = {
    // 布局设置
    setLayout(board: PlaitBoard, type: MindLayoutType): void;
    setShape(board: PlaitBoard, shape: MindElementShape): void;
    setBranchShape(board: PlaitBoard, branchShape: BranchShape): void;
    setBranchWidth(board: PlaitBoard, branchWidth: number): void;
    setBranchColor(board: PlaitBoard, branchColor: string): void;

    // 节点内容
    setTopic(board: PlaitBoard, element: MindElement, topic?: string): void;

    // 表情符号
    addEmoji(board: PlaitBoard, element: MindElement, emojiItem: EmojiItem): void;
    removeEmoji(board: PlaitBoard, element: MindElement, emojiItem: EmojiItem): void;

    // 节点结构
    insertChildNode(board: PlaitBoard, element: MindElement): void;
    insertSiblingNode(board: PlaitBoard, element: MindElement): void;
    insertMind(board: PlaitBoard, mind: PlaitMind): void;
    removeNode(board: PlaitBoard, element: MindElement): void;

    // 节点样式
    setColor(board: PlaitBoard, element: MindElement, color: string): void;
    setFontColor(board: PlaitBoard, element: MindElement, color: string): void;
    setFontSize(board: PlaitBoard, element: MindElement, size: number): void;
};

插件

withMind - 思维导图插件

typescript
const withMind: (baseBoard: PlaitBoard) => PlaitBoard & PlaitMindEmojiBoard;

功能: 提供完整的思维导图功能,包括节点管理、布局算法、样式设置等。

使用示例

typescript
import {
    withMind,
    MindTransforms,
    MindElement,
    MindLayoutType,
    MindElementShape,
    PlaitMind
} from '@plait/mind';
import { PlaitBoard } from '@plait/core';

// 启用思维导图功能
const mindBoard = withMind(board);

// 创建思维导图
const mindData: PlaitMind = {
    type: 'mind',
    id: 'mind-1',
    points: [{x: 400, y: 300}],
    data: { topic: '中心主题' },
    children: [
        {
            type: 'mind_child',
            id: 'child-1',
            data: { topic: '子主题1' },
            children: []
        }
    ]
};

MindTransforms.insertMind(mindBoard, mindData);

// 设置布局
MindTransforms.setLayout(mindBoard, MindLayoutType.standard);

// 设置节点形状
MindTransforms.setShape(mindBoard, MindElementShape.roundRectangle);

// 添加子节点
const rootNode = MindElement.getRoot(mindBoard, mindData);
MindTransforms.insertChildNode(mindBoard, rootNode);

// 检查节点类型
if (MindElement.isMindElement(mindBoard, selectedElement)) {
    const depth = MindElement.getDepth(selectedElement);
    console.log(`节点深度: ${depth}`);
}

🛠️ @plait/common - 通用工具库

主要功能

PropertyTransforms - 属性变换操作

typescript
const PropertyTransforms = {
    // 设置元素属性
    setProperty(board: PlaitBoard, element: PlaitElement, key: string, value: any): void;
    setProperties(board: PlaitBoard, element: PlaitElement, properties: Record<string, any>): void;

    // 删除属性
    unsetProperty(board: PlaitBoard, element: PlaitElement, key: string): void;

    // 获取属性
    getProperty(board: PlaitBoard, element: PlaitElement, key: string): any;
};

BoardCreationMode - 创建模式枚举

typescript
enum BoardCreationMode {
    dnd = "dnd",                        // 拖拽创建
    drawing = "drawing"                 // 绘制创建
}

setCreationMode - 设置创建模式

typescript
const setCreationMode = (board: PlaitBoard, mode: BoardCreationMode): void;

核心插件

withGroup - 分组插件

typescript
const withGroup: (board: PlaitBoard) => PlaitBoard;

功能: 提供元素分组功能,支持多元素组合、取消组合、嵌套分组等。

withImage - 图片插件

typescript
const withImage: (board: PlaitBoard) => PlaitBoard;

功能: 提供图片插入、编辑、变换等功能。

withText - 文本插件

typescript
const withText: (board: PlaitBoard) => PlaitBoard;

功能: 提供文本编辑、格式化等功能。

核心接口

LinkElement - 链接元素

typescript
interface LinkElement extends CustomElement {
    url: string;                        // 链接地址
    title?: string;                     // 链接标题
    target?: string;                    // 打开方式
}

CommonImageItem - 通用图片项

typescript
interface CommonImageItem {
    url: string;                        // 图片地址
    file?: File;                        // 文件对象
    width?: number;                     // 图片宽度
    height?: number;                    // 图片高度
    name?: string;                      // 图片名称
}

StrokeStyle - 描边样式

typescript
enum StrokeStyle {
    solid = "solid",                    // 实线
    dashed = "dashed",                  // 虚线
    dotted = "dotted"                   // 点线
}

常量

typescript
const DEFAULT_COLOR = '#37352f';        // 默认颜色

使用示例

typescript
import {
    withGroup,
    withImage,
    PropertyTransforms,
    BoardCreationMode,
    setCreationMode,
    StrokeStyle
} from '@plait/common';
import { PlaitBoard } from '@plait/core';

// 启用通用功能
const enhancedBoard = withGroup(withImage(withText(board)));

// 设置创建模式
setCreationMode(enhancedBoard, BoardCreationMode.dnd);

// 设置元素属性
PropertyTransforms.setProperty(enhancedBoard, element, 'strokeColor', '#ff0000');
PropertyTransforms.setProperty(enhancedBoard, element, 'strokeStyle', StrokeStyle.dashed);
PropertyTransforms.setProperties(enhancedBoard, element, {
    fill: '#ffff00',
    opacity: 0.8
});

// 获取属性
const strokeColor = PropertyTransforms.getProperty(enhancedBoard, element, 'strokeColor');

📐 @plait/layouts - 布局算法库

主要类型

MindLayoutType - 布局类型(已在 mind 库中介绍)

LayoutType - 布局大类

typescript
enum LayoutType {
    logic = "logic",                    // 逻辑布局
    indented = "indented",              // 缩进布局
    fishBone = "fish-bone"             // 鱼骨图布局
}

LayoutOptions - 布局选项

typescript
interface LayoutOptions {
    getHeight: (node: OriginNode) => number;                    // 获取节点高度
    getWidth: (node: OriginNode) => number;                     // 获取节点宽度
    getHorizontalGap: (node: OriginNode, parent?: LayoutNode) => number;  // 水平间距
    getVerticalGap: (node: OriginNode, parent?: LayoutNode) => number;     // 垂直间距
    getVerticalConnectingPosition: (node: OriginNode, parent?: LayoutNode) => ConnectingPosition;  // 连接位置
    getExtendWidth?: (node: OriginNode) => number;              // 扩展宽度
    getExtendHeight: (node: OriginNode) => number;              // 扩展高度
    getIndentedCrossLevelGap: () => number;                     // 缩进跨级间距
}

LayoutNode - 布局节点

typescript
interface LayoutNode extends OriginNode {
    x: number;                         // X坐标
    y: number;                         // Y坐标
    width: number;                     // 宽度
    height: number;                    // 高度
    children: LayoutNode[];            // 子节点
    parent?: LayoutNode;               // 父节点
    layout: LayoutData;                // 布局数据
}

核心功能

布局算法

typescript
// 逻辑布局算法
const logicLayout: (root: OriginNode, options: LayoutOptions) => LayoutNode;

// 缩进布局算法
const indentedLayout: (root: OriginNode, options: LayoutOptions) => LayoutNode;

// 鱼骨图布局算法
const fishBoneLayout: (root: OriginNode, options: LayoutOptions) => LayoutNode;

使用示例

typescript
import { MindLayoutType, LayoutType } from '@plait/layouts';

// 在思维导图中使用布局
MindTransforms.setLayout(mindBoard, MindLayoutType.standard);

// 检查布局类型
const currentLayout = MindElement.getLayout(rootNode);
if (currentLayout === MindLayoutType.right) {
    console.log('当前是右侧布局');
}

✍️ @plait/text-plugins - 文本插件库

主要功能

LinkEditor - 链接编辑器

typescript
const LinkEditor = {
    // 包装链接
    wrapLink(editor: Editor, text: string, url: string): void;

    // 取消链接
    unwrapLink(editor: Editor, at?: Location): void;

    // 检查链接状态
    isLinkActive(editor: Editor): boolean;

    // 获取链接元素
    getLinkElement(editor: Editor): NodeEntry<CustomElement>;

    // 插入链接
    insertLink(editor: Editor, url: string, text?: string): void;
};

TextTransforms - 文本变换操作

typescript
const TextTransforms = {
    // 文本格式化
    setBold(editor: Editor): void;
    setItalic(editor: Editor): void;
    setUnderline(editor: Editor): void;
    setStrikethrough(editor: Editor): void;

    // 字体设置
    setFontSize(editor: Editor, size: number): void;
    setFontColor(editor: Editor, color: string): void;

    // 对齐方式
    setAlignment(editor: Editor, alignment: 'left' | 'center' | 'right'): void;
};

工具函数

typescript
// URL检测
const isUrl = (text: string): boolean;

// 获取元素文本标记
const getTextMarksByElement = (element: Element): TextMark[];

// 检查是否为链接
const isLinkElement = (element: any): element is LinkElement;

使用示例

typescript
import { LinkEditor, TextTransforms, isUrl } from '@plait/text-plugins';
import { Editor } from 'slate';

// 检查文本是否为URL
const text = 'https://example.com';
if (isUrl(text)) {
    // 插入链接
    LinkEditor.insertLink(editor, text, text);
}

// 设置文本格式
TextTransforms.setBold(editor);
TextTransforms.setFontSize(editor, 16);
TextTransforms.setFontColor(editor, '#ff0000');

// 检查链接状态
if (LinkEditor.isLinkActive(editor)) {
    const linkElement = LinkEditor.getLinkElement(editor);
    console.log('当前链接:', linkElement[0].url);
}

⚛️ @plait-board/react-board - React组件库

主要组件

Board - 画板组件

typescript
interface PlaitBoardProps {
    style?: React.CSSProperties;     // 样式
    className?: string;              // CSS类名
    children?: React.ReactNode;      // 子组件
    afterInit?: (board: PlaitBoard) => void;  // 初始化回调
}

const Board: React.FC<PlaitBoardProps>;

Wrapper - 包装器组件

typescript
interface WrapperProps {
    value: PlaitElement[];                    // 元素数据
    viewport?: Viewport;                      // 视口配置
    theme?: PlaitTheme;                       // 主题配置
    options: PlaitBoardOptions;               // 画板选项
    plugins: PlaitPlugin[];                   // 插件列表
    onChange?: (data: BoardChangeData) => void;           // 变更回调
    onSelectionChange?: (selection: Selection | null) => void;  // 选择变更回调
    onViewportChange?: (value: Viewport) => void;          // 视口变更回调
    onThemeChange?: (value: ThemeColorMode) => void;       // 主题变更回调
    onValueChange?: (value: PlaitElement[]) => void;       // 值变更回调
    children?: React.ReactNode;              // 子组件
}

const Wrapper: React.FC<WrapperProps>;

BoardChangeData - 画板变更数据

typescript
interface BoardChangeData {
    value: PlaitElement[];                   // 新的元素数据
    viewport?: Viewport;                     // 新的视口
    theme?: PlaitTheme;                      // 新的主题
}

React Hooks

useBoard - 获取画板实例

typescript
const useBoard: () => PlaitBoard;

usePluginEvent - 插件事件处理

typescript
const usePluginEvent: (
    board: PlaitBoard,
    viewportContainerRef: RefObject<HTMLElement>,
    hostRef: RefObject<SVGSVGElement>
) => void;

插件

withReact - React集成插件

typescript
const withReact: (board: PlaitBoard) => PlaitBoard;

功能: 提供React组件渲染支持。

withPinchZoom - 缩放插件

typescript
const withPinchZoom: (board: PlaitBoard) => PlaitBoard;

功能: 提供触控缩放支持。

使用示例

typescript
import React from 'react';
import { Board, Wrapper, useBoard, withReact } from '@plait-board/react-board';
import { PlaitElement, PlaitTheme } from '@plait/core';
import { withDraw } from '@plait/draw';

const MyBoardComponent: React.FC = () => {
    const [value, setValue] = useState<PlaitElement[]>([]);
    const [viewport, setViewport] = useState<Viewport>();
    const [theme, setTheme] = useState<PlaitTheme>();

    // 插件配置
    const plugins = [
        withReact,
        withDraw(),
        // ... 其他插件
    ];

    // 画板选项
    const options: PlaitBoardOptions = {
        readonly: false,
        hideScrollbar: false,
    };

    const handleChange = (data: BoardChangeData) => {
        setValue(data.value);
        if (data.viewport) setViewport(data.viewport);
        if (data.theme) setTheme(data.theme);
    };

    return (
        <Wrapper
            value={value}
            viewport={viewport}
            theme={theme}
            options={options}
            plugins={plugins}
            onChange={handleChange}
        >
            <Board afterInit={(board) => {
                console.log('画板初始化完成:', board);
            }} />
        </Wrapper>
    );
};

// 使用Hook获取画板实例
const BoardTools: React.FC = () => {
    const board = useBoard();

    const handleUndo = () => {
        board.undo();
    };

    const handleRedo = () => {
        board.redo();
    };

    return (
        <div>
            <button onClick={handleUndo}>撤销</button>
            <button onClick={handleRedo}>重做</button>
        </div>
    );
};

🚀 完整集成示例

Drawnix风格的完整实现

typescript
import React, { useState } from 'react';
import {
    PlaitBoard,
    PlaitElement,
    PlaitPointerType,
    Viewport,
    PlaitTheme
} from '@plait/core';
import { withDraw } from '@plait/draw';
import { withMind } from '@plait/mind';
import { withGroup } from '@plait/common';
import { Board, Wrapper, useBoard } from '@plait-board/react-board';

const DrawnixBoard: React.FC = () => {
    const [value, setValue] = useState<PlaitElement[]>([]);
    const [viewport, setViewport] = useState<Viewport>();
    const [theme, setTheme] = useState<PlaitTheme>();

    // 插件系统配置
    const plugins = [
        withDraw({
            customGeometryTypes: ['customHeart', 'customStar']
        }),
        withGroup,
        withMind,
        // 自定义插件
        withCustomShapes(),
        withHotkeyPlugin(),
    ];

    // 画板配置
    const options: PlaitBoardOptions = {
        readonly: false,
        hideScrollbar: false,
        disabledScrollOnNonFocus: false,
        themeColors: MindThemeColors,
    };

    // 处理画板变更
    const handleChange = (data: BoardChangeData) => {
        setValue(data.value);
        setViewport(data.viewport);
        setTheme(data.theme);

        // 自动保存到本地存储
        localStorage.setItem('drawnix-data', JSON.stringify(data.value));
    };

    // 处理选择变更
    const handleSelectionChange = (selection: Selection | null) => {
        console.log('选择变更:', selection);
    };

    return (
        <div className="drawnix-container">
            <Wrapper
                value={value}
                viewport={viewport}
                theme={theme}
                options={options}
                plugins={plugins}
                onChange={handleChange}
                onSelectionChange={handleSelectionChange}
            >
                <Board
                    afterInit={(board) => {
                        console.log('Drawnix画板初始化完成');
                        // 可以在这里进行初始化配置
                    }}
                />
            </Wrapper>

            {/* 工具栏组件 */}
            <Toolbar board={useBoard()} />
        </div>
    );
};

// 自定义插件示例
const withCustomShapes = () => {
    return (board: PlaitBoard) => {
        // 注册自定义形状渲染器
        board.registerCustomShapeRenderer('customHeart', CustomHeartRenderer);
        board.registerCustomShapeRenderer('customStar', CustomStarRenderer);

        return board;
    };
};

// 自定义热键插件
const withHotkeyPlugin = () => {
    return (board: PlaitBoard) => {
        board.addKeydownHandler((event) => {
            if (event.ctrlKey && event.key === 'z') {
                event.preventDefault();
                board.undo();
            }
            if (event.ctrlKey && event.key === 'y') {
                event.preventDefault();
                board.redo();
            }
        });

        return board;
    };
};

📚 API参考总结

核心概念

  1. 插件系统: @plait采用插件化架构,所有功能都通过插件实现
  2. 变换操作: 使用Transforms进行状态变更,确保数据一致性
  3. 类型安全: 完整的TypeScript类型定义,提供良好的开发体验
  4. React集成: 通过@plait-board/react-board提供React组件支持

最佳实践

  1. 插件组合: 合理组合插件,避免功能冲突
  2. 性能优化: 使用React.memo和useCallback优化渲染性能
  3. 错误处理: 妥善处理插件加载和运行时错误
  4. 类型检查: 充分利用TypeScript类型系统确保代码质量

扩展开发

  1. 自定义插件: 实现PlaitPlugin接口添加新功能
  2. 自定义形状: 使用PlaitCustomGeometry接口添加新图形
  3. 自定义渲染: 通过board.registerCustomShapeRenderer注册渲染器
  4. 事件处理: 使用board.addEventListener添加自定义事件监听

文档版本: v1.0最后更新: 2025年11月17日基于 @plait v0.86.1