Zum Inhalt springen
Pivotick
Main Navigation Startseite
Erste Schritte
Konfiguration
API-Referenz
GalerieProjekteAusprobieren!

Deutsch

English
简体中文
Français
Português

Deutsch

English
简体中文
Français
Português

Darstellung

Sidebar Navigation

Erste Schritte

Projekte mit Pivotick

Konfiguration

Callbacks

Kantenebenen

Vereinfachen

Layout

Darstellung

Simulation

Oberfläche anpassen

Seitenleiste

Tooltip

Kontextmenü

Filter

Legende

Datentabelle

Oberflächengestaltung

Oberfläche übersetzen

Plugins

Pivotick-API

Pivots und Anreicherung

Pivot-Ergebnisse speichern

Rückgängig und Verlauf

Sicherheit

API-Dokumentation

Galerie

Grundlagen

Knotengestaltung

Kantengestaltung

Layouts

Ereignisse und Callbacks

Oberflächenanpassung

Bearbeiten und Erstellen

Notizen und Anmerkungen

Filter, Suche und Hierarchie

Programmatische Steuerung

Themes und Leistung

Pivots und Anreicherung

Anwendungsbeispiele

Vereinfachen Sie das Diagramm ​

Der größte Teil dieser Grafik besteht aus Wiederholungen: acht IPs bei beiden Ereignissen, sechs Domänen bei einer, neun Dateien auf einem Host, zehn Sichtungen. UI.simplify.rules faltet Knoten, die dieselbe Rolle spielen, zu einer Gruppe, die an ihrer Stelle gezeichnet wird. Die Daten bleiben unberührt: graph.getNodes() gibt weiterhin jeden Knoten zurück.

Hier gelten der Reihe nach zwei Regeln. Nach Sensor ist die eigene App: Sie gibt jeder Sichtung ihren Sensor als Schlüssel und Knoten, die einen Schlüssel teilen, werden zu einer Gruppe. Die eingebaute Nachbarregel faltet dann Knoten eines Typs, die mit genau denselben Knoten verknüpft sind.

  • Öffnen Sie den Modus Vereinfachen auf der Schiene, um eine Regel auszuschalten oder ihre kleinste Gruppe zu ändern.
  • Doppelklicken Sie auf eine Gruppe, um ihre Mitglieder wieder auf die Arbeitsfläche zu setzen. Ziehen Sie den Chip darüber, um sie zusammenzubewegen. Sein × faltet sie zurück.
  • Wählen eine Gruppe: Die Seitenleiste listet ihre Mitglieder auf, jeweils mit Herausziehen.

Die Seite Vereinfachen behandelt die Regeln, benutzerdefinierten Regeln und das Erscheinungsbild der Gruppe.

js
const plural = { ip: 'IPs', domain: 'domains', file: 'files', sighting: 'sightings' }

const simplify = {
    rules: [
        // An app rule: a key per node, and nodes sharing a key become one group.
        // It runs first, so the sightings split by sensor before the neighbour
        // rule would fold all ten of them together.
        {
            kind: 'custom',
            id: 'bySensor',
            label: 'By sensor',
            description: 'Sightings reported by the same sensor.',
            partition: (view) => new Map(view.nodes
                .filter(node => view.typeOf(node) === 'sighting')
                .map(node => [node.id, node.getData().sensor])),
        },
        // The built-in rule: one type, exactly the same neighbours, five or more.
        { kind: 'neighbours', minSize: 5 },
    ],
    typeLabel: (type, count) => `${count} ${plural[type] ?? type}`,
}
js
const options = {
    UI: {
        mode: 'full',
        // Off: this card is about neither the minimap nor the data dock.
        minimap: false,
        table: false,
        simplify,
    },
    // Longer links, so the labels under the groups have room.
    simulation: { physics: 'manual', d3LinkDistance: 70 },
    render: {
        nodeTypeAccessor: (node) => node.getData().type,
        nodeStyleMap: {
            event: { color: '#7c3aed', size: 16 },
            host: { color: '#475569', size: 14 },
            ip: { color: '#0ea5e9' },
            domain: { color: '#10b981' },
            file: { color: '#e11d48' },
            sighting: { color: '#f59e0b' },
        },
        // A group made by the app's rule names its sensor.
        groupStyle: (group) => group.rule === 'bySensor'
            ? { text: () => `${group.members.length} from ${group.members[0].getData().sensor}` }
            : undefined,
    },
}
js
// Two events share eight IPs, the first alone has six domains, a host has nine
// files, and the second event has ten sightings from two sensors.
const ips = Array.from({ length: 8 }, (_, i) => ({ id: `ip-${i}`, data: { type: 'ip', label: `198.51.100.${10 + i}` } }))
const domains = Array.from({ length: 6 }, (_, i) => ({ id: `dom-${i}`, data: { type: 'domain', label: `site-${i}.example` } }))
const files = Array.from({ length: 9 }, (_, i) => ({ id: `file-${i}`, data: { type: 'file', label: `sample-${i}.bin` } }))
const sightings = Array.from({ length: 10 }, (_, i) => ({
    id: `seen-${i}`,
    data: { type: 'sighting', label: `Sighting ${i + 1}`, sensor: i < 6 ? 'north' : 'south' },
}))

const data = {
    nodes: [
        { id: 'ev-1', data: { type: 'event', label: 'Event 1' } },
        { id: 'ev-2', data: { type: 'event', label: 'Event 2' } },
        { id: 'host', data: { type: 'host', label: 'Build host' } },
        ...ips, ...domains, ...files, ...sightings,
    ],
    edges: [
        ...ips.flatMap(ip => [{ from: 'ev-1', to: ip.id }, { from: 'ev-2', to: ip.id }]),
        ...domains.map(domain => ({ from: 'ev-1', to: domain.id })),
        ...files.map(file => ({ from: 'host', to: file.id })),
        ...sightings.map(sighting => ({ from: 'ev-2', to: sighting.id })),
        { from: 'ev-2', to: 'host' },
    ],
}
Pager
Nächste SeiteErste Schritte