Oberflächenoptionen
Pivotick bietet eine flexible UI-Ebene über Ihrem Diagramm, mit der Sie steuern können, wie Benutzer mit Knoten, Kanten und der Arbeitsfläche interagieren. Mit den Optionen UI können Sie:
- Konfigurieren Sie den gesamten Modus der Benutzeroberfläche (vollständig, Viewer, statisch usw.).
- Passen Sie Seitenleiste und Bedienfelder an, um Eigenschaften oder zusätzliche Informationen anzuzeigen.
- Definieren Sie Tooltips für Knoten und Kanten, mit optionalen benutzerdefinierten Renderern.
- Konfigurieren Sie Kontextmenüs für Knoten, Kanten und die Arbeitsfläche.
- Deklarieren Sie die Facetten des Filter-Panels oder lassen Sie sie aus Ihren Daten ableiten.
- Docken Sie eine Legende auf der Arbeitsfläche an – einen Schlüssel für Ihre Farben, der gleichzeitig als Filter dient und von selbst erscheint, wenn Ihre Farben durch einen deklarierten Knotentyp erklärt werden.
- Füllen Sie jede dieser Oberflächen asynchron aus Daten, die Sie bei Bedarf abrufen.
- Deaktivieren alle Funktionen, die Ihre Integration nicht benötigt.
- Fügen Sie den eigenen Text der Bibliothek in die Sprache Ihrer Benutzer ein: siehe Übersetzen der Benutzeroberfläche.
UI-Modus
Die Option mode steuert das Gesamtverhalten und die Interaktionsebene der Diagramm-Benutzeroberfläche.
fullStandard: Vollständige Benutzeroberfläche mit allen aktivierten Bedienfeldern, Menüs und Interaktionen.light: Minimale Benutzeroberfläche mit aktivierten wesentlichen Interaktionen.viewer: Ermöglicht nur das Navigieren im Diagramm (Schwenken, Zoomen, Ziehen), ohne dass UI-Panels angezeigt werden.static: Statisches Diagramm, keine UI-Panels oder Interaktionen; Das Diagramm ist schreibgeschützt.
Für die Verwendung von Pivotick im Bildstil verwenden Sie Folgendes:
const container = document.getElementById('graph-container')
const options = {
UI: {
mode: 'viewer'
},
}
const graph = Pivotick(container, options)Andere UI-Komponenten können über ihren jeweiligen Namespace konfiguriert werden
const options = {
UI: {
sidebar: {},
mainHeader: {},
propertiesPanel: {},
extraPanels: [],
tooltip: {},
contextMenu: {},
filter: {},
}
}Die Bedienoberfläche im full-Modus
Im full-Modus ist das Chrome ein modusgesteuertes Layout: eine linke Modusschiene (Auswählen / Erstellen / Anzeigen / Physik), ein kontextuelles Werkzeugfeld für den aktiven Zeigermodus, zwei Einstellungs-Flyouts – Ansicht (Arbeitsflächehintergrund und Schalter) und Physik (Layout + Simulation) – die obere Leiste (Suche, Filter, Notizen, Rückgängig/Wiederherstellen), die Auswahl Seitenleiste (Eigenschaften, Facetten, Nachbarn und eine Massenaktionszeile) und ein Ansichtsfenster auf der rechten Seite Schiene (Einpassen und Zentrieren, Zoom, Einstellungen, Vollbild) und eine Minikarte in der freien unteren rechten Ecke, die sich zusammenfaltet, wenn die Arbeitsfläche zu klein ist, um den Raum zu schonen (UI.minimap: false, um sie fallen zu lassen). Im light-Modus werden die Seitenleiste und die Minikarte gelöscht. viewer behält nur die Ansichtsfensterschiene; static ist eine nackte Arbeitsfläche.
Migration aus dem Eckchrom
Die schwebenden Überlagerungen GraphControls und GraphToolbar wurden entfernt. Layout und Physik wurden in das Flyout „Physik“ (UIManager.physicsFlyout) verschoben – sie wurden in 1.5.0 im Flyout „Ansicht“ (UIManager.viewFlyout) ausgeliefert, das jetzt den Arbeitsflächehintergrund und die Rasterschalter enthält. Wählen/erstellen Sie Werkzeuge live im Werkzeugfenster (UIManager.toolPanel) und in der Modusleiste (UIManager.modeRail). Die Option UI.selectionMenu ist weg – verwenden Sie contextMenu für Aktionen pro Knoten und die Massenaktionszeile in der Seitenleiste für Mehrfachauswahlaktionen. UIManager.graphNaviation wurde in graphNavigation umbenannt. Die Option UI.modeRail und ihre deaktivierten Explore / Enrich-Slots wurden entfernt – registrieren Sie stattdessen einen echten Modus mit addRailMode. Siehe CHANGELOG.
Die vier Modi der Schiene sind integriert, aber nicht die einzigen, die sie aufnehmen kann: Ein Plugin fügt seinen eigenen mit addRailMode hinzu. Auf diese Weise wird ein Erkundungs- oder Anreicherungsmodus erstellt, der weiß, was Ihre Daten bedeuten.
Funktionen ausschalten
Der UI-Modus entscheidet, wie viel Chrom ein Diagramm erhält. Jede Funktion in diesem Chrome kann auch einzeln ausgeschaltet werden, sodass eine Integration Dinge fallen lässt, für die ihr Backend oder ihre Benutzer keine Verwendung haben.
Eine ausgeschaltete Funktion nimmt alles auf, was sie erreicht: die Schaltfläche, das Bedienfeld, der Kontextmenüeintrag und die Tastenkombination gehören alle zusammen, sodass nichts zurückbleibt, was man anklicken oder drücken und stillschweigend verweigern könnte.
const options = {
UI: {
mode: 'full',
notes: { enabled: false },
history: { enabled: false },
inspector: { enabled: false },
editors: { deletion: { enabled: false } },
},
}Die Schalter
| Option | Was dazugehört |
|---|---|
UI.topBar.enabled | Der obere Streifen, die von ihm reservierte Höhe, die Tastenkombinationen, die seine Steuerelemente besitzen (Shift+J, Shift+K, Shift+N, Mod+Z) und alle Host-Aktionen. Benutzen Sie die Schalter unten, um eine Pille fallen zu lassen und den Rest zu behalten. |
UI.search.enabled | Das Suchpille, seine Knotenauswahl und Shift+J. |
UI.filter.enabled | Die Pille „Filterdiagramm“, ihr Panel und Shift+K. graph.queryEngine filtert immer noch aus Code. |
UI.notes.enabled | Das Pillen- und Bedienfeld „Notizen“, Shift+N, das Werkzeug „Notiz hinzufügen“, die Option „Notiz hinzufügen“ im Arbeitsflächemenü, N, das Notizkontextmenü und noteManager.addNote, das ablehnt. |
UI.history.enabled | Die Rückgängig-/Wiederholen-Schaltflächen, ihr Verlaufs-Dropdown und Mod+Z / Mod+Shift+Z. graph.history setzt die Aufnahme fort. |
UI.inspector.enabled | Der Eintrag Eigenschaften prüfen im Knotenmenü und I. |
UI.notifications.enabled | Toasts. graph.notifier.* wird zu einem No-Op, der undefined zurückgibt. |
UI.sidebar.enabled | Die gesamte Seitensäule und die Breite, die sie benötigte. |
UI.propertiesPanel.enabled | Das Eigenschaftenfenster der Seitenleiste und ihr Trennzeichen. |
UI.neighborsPanel.enabled | Das Nachbarfeld der Seitenleiste und sein Trennzeichen. |
UI.viewFlyout.enabled | Die Schaltfläche „Schiene anzeigen“ und ihr Bedienfeld. |
UI.physicsFlyout.enabled | Die Leistenschaltfläche „Physik“ und ihr Bedienfeld. |
UI.tooltip.enabled | Hover-Tooltips, auch angeheftete. Akzeptiert auch { nodes, edges, groups } oder (element, kind) => boolean, siehe Tooltips. |
UI.contextMenu.enabled | Jedes Kontextmenü. |
UI.navigation.enabled | Die Viewport-Schiene: Anpassen, Zoomen und Vollbild. |
UI.legend: false | Die Canvas-Legende, einschließlich derjenigen, die sie selbst ableiten würde. |
UI.minimap: false | Die Minikarte. |
UI.emptyState: false | Die Karte zeigt eine leere Arbeitsfläche. |
UI.table: false | Das Datendock und seine Shift+T. |
UI.pivotMode: false | Der Pivot-Rail-Modus, was auch immer registriert ist. |
Schreibpfadfunktionen haben den gleichen Schalter unter UI.editors, sodass eine schreibgeschützte Integration die Affordance entfernt, anstatt jeden Klick zu blockieren: nodeCreator, edgeCreator, nodeEditor, edgeEditor und deletion.
Das Renderer-Verhalten ist unter render ausgeschaltet: zoomEnabled (wobei auch die Zoom-Schaltflächen der Schiene übernommen werden, sodass sie in der Mitte bleiben), dragEnabled, selectionBox.enabled (das Auswahlrechteck ** und** das Werkzeug „Auswählen“ ▸ Lasso), enableNodeExpansion (der Chevron, seine Enter und die (gestrichelter, minimierter Umriss), enableFocusMode und interactionEnabled für alles auf einmal. simulation.enabled stoppt die Ausführung des Layouts.
Der Erstellungsmodus folgt seinen Werkzeugen
Der Modus „Schiene erstellen“ enthält genau vier Werkzeuge: Knoten hinzufügen, Kante hinzufügen, Notiz hinzufügen und Knoten bearbeiten. Schalten Sie alle vier aus und der Modus verlässt die Schiene zusammen mit der Verknüpfung C, anstatt sich auf ein leeres Feld zu öffnen. Auswählen bleibt immer bestehen.
Ihre eigenen Aktionen in der oberen Leiste
Eine Aktion auf der gesamten Arbeitsfläche, beispielsweise das Speichern, gehört in die obere Leiste neben der Gruppe „Rückgängig/Wiederherstellen“. UI.topBar.actions deklariert Pillen, die im gleichen Stil wie Suche, Filter und Notizen gezeichnet sind, sodass ein Design, das diese neu gestaltet, auch diese neu gestaltet.
const options = {
UI: {
topBar: {
actions: [{
id: 'save-graph',
text: () => storedId ? 'Update graph' : 'Save as graph',
async onclick(_event, ctx) {
if (storedId) return updateGraph(storedId, ctx.graph)
const values = await ctx.promptData({
fields: [{ key: 'name', label: 'Name', type: 'text' }],
})
if (values) storedId = await createGraph(values.name, ctx.graph)
},
menu: () => storedId
? [{ text: 'Save as new graph…', onclick: saveAsNew }]
: [],
}],
},
},
}- Wo.
placement: 'end'(Standardeinstellung) platziert die Pille direkt vor der Undo-Redo-Gruppe;'start'setzt es nach den eingebauten Pillen auf der linken Seite. Pillen behalten die Reihenfolge bei, in der sie deklariert wurden. - Was es sagt.
text,title,visibleundenablednehmen einen Wert oder eine Funktion des Diagramms an. Die Funktionen werden nach jeder Datenänderung amgraph.UIManager.refreshTopBar()erneut gelesen und sobald ein vononclickzurückgegebenes Versprechen erfüllt ist. Während dieses Versprechen gilt, ist die Pille deaktiviert, sodass ein langsamer Speichervorgang nicht zweimal gestartet werden kann. - Was es bekommt.
onclick(event, ctx)empfängt das Diagramm und zwei Helfer, die das Modal der Bibliothek öffnen:ctx.promptData({ fields })löst die Werte auf odernullbei Abbrechen, undctx.confirm({ body })lösttruenur auf der Bestätigungsschaltfläche auf.ctx.refresh()liest jede Aktion erneut. - Ein Caret. Mit
menuwird die Pille zu einer geteilten Schaltfläche: Die Beschriftung lautetonclick, und ein Caret öffnet die Zeilen im gleichen Zeilenformat wie die Kontextmenüs (ohne Untermenüs). Einer Funktionsform wird das gleiche übergebenctxund sie wird bei jeder Aktualisierung und jedem Öffnen aufgerufen; Während keine Zeilen zurückgegeben werden, verfügt die Pille über kein Caretzeichen. Escape oder ein Klick auf eine andere Stelle schließt die Zeilen. - Eine Abkürzung.
shortcutzeichnet ein Abzeichen auf die Pille. Es handelt sich lediglich um ein Etikett: Registrieren Sie die Bindung selbst.
Ein Plugin fügt eine Pille mit ctx.addTopBarAction(action) hinzu, die einen Entsorger zurückgibt (siehe Plugins). Die Pillen folgen dem Streifen: keine im viewer- oder static-Modus und keine im UI.topBar.enabled: false-Modus.
Eine leere Arbeitsfläche
Ein Diagramm ohne Knoten und ohne Notiz zeigt eine Karte in der Mitte der Arbeitsfläche, sodass eine Quelle, in der es nichts zu zeichnen gibt, nicht als Diagramm gelesen wird, das nicht geladen werden konnte. Es heißt „Noch nichts auf der Arbeitsfläche“, es sei denn, Sie geben ihm etwas anderes zu sagen:
const options = {
UI: {
emptyState: {
render: ({ initial, graph }) => {
const box = document.createElement('div')
box.textContent = initial ? 'Nothing is related to this record.' : 'The canvas is empty.'
const button = document.createElement('button')
button.textContent = 'Find related'
button.onclick = () => graph.UIManager.openPivotMode()
box.append(button)
return box
},
},
},
}Die Karte folgt den Daten. Durch das Hinzufügen eines Knotens oder einer Notiz wird dieser entfernt, und wenn der letzte Knoten manuell oder durch Rückgängigmachen der Aufnahme, die ihn verursacht hat, entfernt wird, wird er wieder zurückgebracht. Knoten, die von den Filtern ausgeblendet werden, zählen weiterhin: Das Diagramm ist eingeengt und nicht leer.
render wird jedes Mal ausgeführt, wenn die Karte angezeigt wird, nicht bei jeder Änderung, während sie aktiv ist. initial ist true, bis das Diagramm einen Knoten enthält, sodass einem Analysten, der eine vollständige Arbeitsfläche geleert hat, etwas anderes gesagt werden kann als einer leeren Quelle. Eine zurückgegebene Zeichenfolge wird als einfacher Text gerendert und render kann async sein, wie die Hooks unten.
Die Karte nutzt die Oberfläche und den Rand des Chroms und folgt so dem Thema. Es lässt die Gesten der Arbeitsfläche durch, sodass Schwenken, Zoomen und das Arbeitsflächemenü überall funktionieren, außer bei interaktiven Inhalten: Eine Schaltfläche, ein Link, ein Formularsteuerelement oder alles mit einer tabindex erhält seine eigenen Klicks. UI.emptyState: false zeigt überhaupt nichts an.
Asynchroner Inhalt
Jeder vom Verbraucher bereitgestellte Inhalts-Hook kann anstelle des Inhalts selbst einen Promise zurückgeben. Dies umfasst die Seitenleisten mainHeader.render, propertiesPanel.render / nodePropertiesMap / edgePropertiesMap, neighborsPanel.render, ein zusätzliches Panel title und render, die Tooltips render, renderNodeExtra, renderEdgeExtra und Eigenschaftskarten und die leeren Canvas render.
Dies gilt für den Fall, dass die Daten eines Knotens eine Referenz auf einen Datensatz und nicht auf den Datensatz selbst sind und der interessante Inhalt hinter einem HTTP-Aufruf steht:
const options = {
UI: {
tooltip: {
renderNodeExtra: async (node, { signal }) => {
const res = await fetch(`/enrich/${node.getData().uuid}`, { signal })
return renderChips(await res.json()) // an HTMLElement
},
},
},
}Fügen Sie async hinzu, leiten Sie signal weiter und die Bibliothek kümmert sich um den Rest:
| Platzhalter | Während das Versprechen aussteht, nimmt ein thematisches Skelett den Platz ein. |
| Tauschen | Beim Auflösen ersetzt der Inhalt den vorhandenen Platzhalter. |
| Veraltung | Ein Ergebnis, das eintrifft, nachdem sein Steckplatz verschwunden ist – Sie haben den Mauszeiger über einen anderen Knoten bewegt, die Auswahl geändert oder das Panel aktualisiert – wird mit verworfen gelöscht. Nur das aktuellste Rendering einer Oberfläche kann übernommen werden, unabhängig von der Reihenfolge, in der sie aufgelöst werden. |
| Stornierung | ctx.signal wird abgebrochen, wenn ein Rendering ersetzt oder das Diagramm abgerissen wird, sodass eine weitergeleitete fetch abgebrochen und nicht durchgesickert ist. |
| Fehler | Ein abgelehntes Versprechen stellt eine kompakte Fehlerzeile dar, anstatt für immer einen Spinner zu hinterlassen. Ein abgebrochener Rendervorgang ist kein Fehler und zeigt nichts an. |
Der Renderkontext
Jeder Content-Hook erhält ein RenderContext als last-Argument. Vorhandene synchrone Hooks ignorieren es einfach.
render: async (element, { signal, isStale }) => {
const rows = await fetchRows(element, signal)
if (isStale()) return '' // cheap guard for non-abortable work
return renderRows(rows)
}Anpassen des Platzhalters
UI.asyncContent überschreibt die Anzeige im ausstehenden Zustand und bei einem Fehler. Beide akzeptieren eine Zeichenfolge, eine HTMLElement oder eine Funktion der Oberfläche:
const options = {
UI: {
asyncContent: {
placeholder: (surface) => surface === 'tooltip' ? 'Loading…' : mySkeleton(),
error: 'Could not load',
},
},
}surface ist eines von 'tooltip', 'properties', 'neighbors', 'mainHeader', 'extraPanel' oder 'emptyState'.
Synchrone Haken bleiben unberührt
Die direkte Rückgabe von Inhalten verhält sich genauso wie immer – gleicher Aufruf, gleicher Frame, kein Platzhalter und kein Wrapper-Element. An einer bestehenden Integration ändert sich nichts.
Was nicht asynchron sein kann
Zwei Gruppen bleiben absichtlich synchron:
HeaderMapEntry.title/subtitlefüttern den automatisch angepassten Titelslot und Knotensuche (resolveNodeByName), die beide jetzt den Text benötigen. Verwenden Sie ein asynchronesmainHeader.render, wenn Sie abgerufene Details im Header benötigen.PropertyEntry.name/value– Rufen Sie stattdessen die Zeilen ab: Ein asynchronesnodePropertiesMapwird einmal aufgelöst und gibt dann einfache Einträge zurück, anstatt in jede Zelle einen Spinner einzufügen.
Die Renderer-Hooks pro Frame (render.renderNode, renderLabel, renderCluster und NodeStyle.html) sind ebenfalls nur synchron: Sie werden innerhalb des Zeichenpfads pro Knoten und pro Tick ausgeführt. Wenn Sie eine asynchrone Node-Dekoration benötigen, rufen Sie die Daten des Nodes ab und lassen Sie sie vom synchronen Renderer lesen.