跳转到内容
Pivotick
Main Navigation 首页
快速入门
配置
API 参考
示例库项目在线体验

简体中文

English
Français
Deutsch
Português

简体中文

English
Français
Deutsch
Português

外观

Sidebar Navigation

快速入门

使用 Pivotick 的项目

配置

回调

边图层

简化

布局

渲染

模拟

自定义界面

侧栏

提示框

上下文菜单

筛选

图例

数据表格

界面样式

翻译界面

插件

Pivotick API

拓展与数据增强

保存拓展结果

撤销与历史记录

安全

API 文档

示例库

基础

节点样式

边样式

布局

事件与回调

界面自定义

编辑与创建

备注与注释

筛选、搜索与层级

编程控制

主题与性能

拓展与数据增强

综合示例

使用插件扩展 ​

插件是一个独立的 UI 元素、键绑定和生命周期挂钩捆绑包,可将自身安装到图表中 - 核心永远不需要知道它的存在。通过 plugins 选项以声明方式注册插件,或者随时使用 graph.use(plugin) 强制注册插件。

安装时,插件会获得一个 PluginContext 及其所需的一切:addElement() 将 UI 元素放入布局槽中(然后为您管理其生命周期),onPhase() 挂钩 afterMount / graphReady / destroy,addKeybinding() 用于自动清理的快捷方式,以及直接访问 graph, ui 和 layout。

下面的示例安装了一个单元素插件:固定到画布的 stats 覆盖,一旦图表准备好,它就会读取实时节点/边计数。它扩展了 UIComponent,因此它的 mount → afterMount → graphReady → destroy 生命周期(以及它跟踪的任何侦听器)由与内置侧边栏、工具栏和工具提示相同的机制驱动 - 添加新界面只是一个 addElement。

单击图表,然后按 B 切换叠加。

js
// import { UIComponent } from 'pivotick'

// A plugin bundles UI elements, keybindings and lifecycle hooks and installs
// itself through the PluginContext it is handed — the core never needs to know
// it exists.
//
// Our plugin contributes one custom UI element: a small stats overlay pinned to
// the canvas. Because it extends UIComponent, its lifecycle (mount → afterMount
// → graphReady → destroy) and any tracked listeners are driven for free — the
// same machinery the built-in sidebar/toolbar/tooltip use.
class StatsOverlay extends UIComponent {
    // Build the DOM and drop it into the slot we were mounted into.
    onMount(slot) {
        this.el = document.createElement('div')
        // Bottom-right corner: the top-left / top / left edges are taken by the
        // B3 chrome (top bar, mode rail), so pin the overlay clear of them.
        this.el.style.cssText = [
            'position:absolute', 'bottom:12px', 'right:12px', 'z-index:5',
            'padding:8px 12px', 'border-radius:8px', 'font:12px/1.6 sans-serif',
            'background:rgba(20,24,32,0.85)', 'color:#fff',
            'box-shadow:0 2px 8px rgba(0,0,0,0.25)', 'pointer-events:none'
        ].join(';')
        slot?.appendChild(this.el)
    }

    // Runs once the graph data is ready — read live counts off the graph.
    onGraphReady() {
        this.render()
        const graph = this.uiManager.graph
        const cb = () => this.render()
        graph.on('dataBatchChanged', cb)
        // graph.on lives on the Graph, which outlives the UI — so track the
        // unsubscribe and destroy() tears it down with everything else.
        this.track(() => graph.off('dataBatchChanged', cb))
    }

    render() {
        const graph = this.uiManager.graph
        this.el.innerHTML =
            '<strong>Graph stats</strong><br>' +
            `${graph.getNodes().length} nodes · ${graph.getEdges().length} edges`
    }

    toggle() {
        this.el.style.display = this.el.style.display === 'none' ? '' : 'none'
    }

    // Only DOM cleanup needed here; children and everything registered via
    // track() (including the dataBatchChanged unsubscribe above) are torn down
    // by UIComponent.
    onDestroy() {
        this.el?.remove()
    }
}

const statsPlugin = {
    name: 'stats-overlay',
    install(ctx) {
        const overlay = new StatsOverlay(ctx.ui)
        // Mount the element into the canvas slot; its lifecycle is then managed.
        ctx.addElement(overlay, ctx.layout?.canvas)
        // Bonus: click the graph, then press "B" to toggle the overlay.
        ctx.addKeybinding({ key: 'b', callback: () => overlay.toggle() })
    }
}

// Register plugins declaratively with `plugins`, or imperatively at any time
// with `graph.use(statsPlugin)` (late installs are caught up to the current
// lifecycle phase automatically).
const options = {
    // Off: `full` mode brings a minimap and the data dock, and this card is about
    // neither (see the Minimap and Data table cards for those).
    UI: { mode: 'full', minimap: false, table: false, sidebar: { collapsed: true } },
    plugins: [statsPlugin]
}
js
const data = {
    nodes: [
        { id: 'web', data: { label: 'Web' } },
        { id: 'api', data: { label: 'API' } },
        { id: 'db', data: { label: 'Database' } },
        { id: 'cache', data: { label: 'Cache' } },
        { id: 'worker', data: { label: 'Worker' } }
    ],
    edges: [
        { from: 'web', to: 'api', data: { label: 'calls' } },
        { from: 'api', to: 'db', data: { label: 'reads' } },
        { from: 'api', to: 'cache', data: { label: 'reads' } },
        { from: 'worker', to: 'db', data: { label: 'writes' } }
    ]
}
Pager
下一页快速入门