Pular para o conteúdo
Pivotick
Main Navigation Início
Primeiros passos
Configuração
Referência da API
GaleriaProjetosExperimente!

Português

English
简体中文
Français
Deutsch

Português

English
简体中文
Français
Deutsch

Aparência

Sidebar Navigation

Primeiros passos

Projetos que usam o Pivotick

Configuração

Funções de retorno

Camadas de arestas

Simplificar

Layout

Renderização

Simulação

Personalizar a interface

Barra lateral

Dica

Menu de contexto

Filtros

Legenda

Tabela de dados

Estilo da interface

Traduzir a interface

Plugins

API Pivotick

Pivôs e enriquecimento

Salvar resultados dos pivôs

Desfazer e histórico

Segurança

Documentação da API

Galeria

Fundamentos

Estilo dos nós

Estilo das arestas

Layouts

Eventos e funções de retorno

Personalização da interface

Edição e criação

Notas e anotações

Filtros, pesquisa e hierarquia

Controle por programação

Temas e desempenho

Pivôs e enriquecimento

Demonstrações completas

Estenda com um plugin ​

Um plugin é um pacote independente de elementos de UI, atalhos de teclado e ganchos de ciclo de vida que se instalam em um gráfico — o núcleo nunca precisa saber que ele existe. Registre plugins declarativamente através da opção plugins, ou imperativamente a qualquer momento com graph.use(plugin).

Na instalação, um plugin recebe um PluginContext com tudo o que precisa: addElement() para colocar um elemento UI em um slot de layout (seu ciclo de vida é então gerenciado para você), onPhase() para conectar afterMount / graphReady / destroy, addKeybinding() para atalhos que são limpos automaticamente, além de acesso direto a graph, ui e layout.

O exemplo abaixo instala um plug-in de um elemento: uma stats overlay fixada na tela que lê contagens de nós/bordas ativas quando o gráfico estiver pronto. Ele estende UIComponent, então seu ciclo de vida mount → afterMount → graphReady → destroy (e quaisquer ouvintes que ele rastreia) é conduzido pelo mesmo mecanismo da barra lateral, barra de ferramentas e dica de ferramenta integradas - adicionar uma nova interface é apenas um addElement.

Clique no gráfico e pressione B para alternar a sobreposição.

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
Próxima páginaPrimeiros passos