コンテンツへスキップ
Pivotick
Main Navigation ホーム
はじめに
設定
生成された API ドキュメント
ギャラリープロジェクト試してみる!

日本語

English
简体中文
Français
Deutsch
Português
Nederlands
العربية
Español

日本語

English
简体中文
Français
Deutsch
Português
Nederlands
العربية
Español

外観

Sidebar Navigation

はじめに

Pivotick を使ったプロジェクト

設定

コールバック

エッジレイヤー

簡略化

レイアウト

描画

シミュレーション

UI のカスタマイズ

サイドバー

ツールチップ

コンテキストメニュー

フィルター

凡例

データ表

UI のスタイル

UI の翻訳

プラグイン

Pivotick API

ピボットとデータ拡充

ピボット結果の保存

元に戻す操作と履歴

セキュリティ

API ドキュメント

ギャラリー

基本

ノードのスタイル

エッジのスタイル

レイアウト

イベントとコールバック

UI のカスタマイズ

編集と作成

メモと注釈

フィルター・検索・階層

プログラムによる制御

テーマとパフォーマンス

ピボットとデータ拡充

注目のサンプル

グラフを簡略化する ​

このグラフの大部分は繰り返しです。両方のイベントに 8 つの IP、1 つのイベントに 6 つのドメイン、1 つのイベントに 9 つのファイルがあります。 ホスト、目撃情報は10件。 UI.simplify.rules 同じ役割を果たすノードを 1 つに折りたたむ グループが代わりに描画されます。データは変更されません: graph.getNodes() は依然として次の間隔で返されます。 ノード。

ここでは 2 つのルールが順番に実行されます。 センサーによるはアプリ独自のもので、各照準にセンサーを与えます。 をキーとして、キーを共有するノードが一つのグループとなります。組み込みの ** 近隣ルール** が折り畳まれます 1 つのタイプのノードがまったく同じノードにリンクされます。

  • レールで Simplify モードを開いて、ルールをオフにするか、その最小グループを変更します。
  • グループをダブルクリックすると、そのメンバーがキャンバスに戻ります。それらの上のチップをドラッグして、 それらを一緒に移動します。 × で折り返されます。
  • グループを選択: サイドバーにそのメンバーがリストされ、それぞれに引き出しが付いています。

Simplify ページでは、ルール、カスタム ルール、グループの外観について説明します。

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
次のページはじめに