跳转到内容

传奇 ​

UI.legend 将 legend 停靠在画布角落:每个类别一行,每行都有一个色样、一个标签及其后面的节点数。指向画布上该类别的行灯;单击其中一个会将其隐藏,因此图例兼作 UI 中最快的过滤器。

ts
const options = {
    UI: {
        legend: { key: 'type', title: 'Node type' },
    },
}

您可能根本不需要该块:如果没有 UI.legend,当图形的颜色由声明的 render.nodeTypeAccessor 解释时,图例会自行出现 **** — 请参阅默认情况下打开。 UI.legend: false 将其关闭。

一次编码多个内容的图需要多个键:传递 sections 而不是单个键 - 请参阅一次多个键。

图例是镶边的一部分,因此它仅出现在 full 和 light 模式中 — viewer 和 static 没有。

传说从来不给任何东西上色

图例是描述性。它读取渲染器已经为节点解析的颜色 (renderer.getNodeStyle(node).color) 并报告它。着色保持在原来的位置:render.defaultNodeStyle.color、render.nodeStyleMap或每个节点的样式 - 通常通过ColorPaletteMapper。更改调色板,图例就会自行变化。

默认开启 ​

图例只有在保证说真话的情况下才值得在未经询问的情况下显示,因此自动图例从您已经声明的内容开始,而不是从对数据的猜测开始:render.nodeTypeAccessor,您指向nodeStyleMap的维度。

然而,拥有候选者还不够,维度可以对数据进行分区,而与颜色无关。因此,在渲染任何内容之前,图例会检查该尺寸是否解释了颜色:

  • 每个类别都精确地解析为 one 颜色;
  • 至少有两个不同的颜色(否则颜色无法区分类别);
  • 最多有 24 个类别——类似于 id 的维度为每个节点生成一个值,每个值都有自己的颜色,否则将通过上面的检查。

如果其中任何一个失败,则不会出现图例,也不会记录任何内容:您没有要求一个。自动图例也会跳过5000个节点,其中采样每个节点的颜色不值得不请自来——有人警告说,所以这种缺席是可以解释的。声明 UI.legend (或 true)可以同时提升两者。

ts
// nothing declared → a legend appears iff `type` explains the colours
render: { nodeTypeAccessor: (node) => node.getData().type, nodeStyleMap: { … } }

UI: { legend: false }   // never
UI: { legend: true }    // derive from nodeTypeAccessor, check or no check
UI: { legend: { position: 'top-right' } }   // automatic entries, your placement

自动图例键位于访问器而不是数据键上,因此它无法与声明的构面 共享过滤器 — 为此为其提供显式 key。

条目来自哪里 ​

从数据密钥派生 ​

key 是常见情况下的整个配置:node.getData()[key] 的不同值成为行,按首次看到的顺序,用值本身进行标记。

ts
UI: { legend: { key: 'type' } }

数组值键为每个元素贡献一行,并且每个元素下都有一个节点计数(tags: ['public', 'critical']出现在两者下)。

关于派生行,有两件事值得了解:

  • 键没有值的节点(null,undefined,'')不会获得任何行,图例永远无法隐藏它们 - 它只作用于它列出的类别。开发时警告会指定密钥的名称以及未表示的节点数量。
  • 用多种颜色绘制的类别保留找到的第一个颜色,并警告:一行只能显示一个样本。如果分组实际上不是一种颜色,请自行声明条目。

申报条目 ​

当类别不是纯数据键时传递entries——计算的分组、翻译的标签、固定的色标。每个条目都有自己的predicate,这是切换过滤器的内容。

ts
UI: {
    legend: {
        title: 'Tier',
        entries: [
            { id: 'edge', label: 'Edge', color: '#0072B2',
              predicate: (node) => node.getData().type === 'web' },
            { id: 'storage', label: 'Storage', color: '#009E73',
              predicate: (node) => ['database', 'cache'].includes(node.getData().type) },
        ],
    },
}

entries也可能是图的函数,每当数据发生变化时都会重新解析 - 因此列表遵循数据而无需声明搅动:

ts
UI: {
    legend: {
        key: 'type',
        entries: (graph) => distinct(graph, 'type').map((type) => ({
            id: type,
            label: t(`type.${type}`),        // translated, used verbatim
            color: palette.getColor(type),
        })),
    },
}

声明 entries 和 key 是上面显示的有用的中间立场:条目给出标签和颜色,key 为不携带标签和颜色的条目提供默认谓词 (data[key] === id)。两者都没有的条目不会发出警告,也不匹配任何内容。

行的切换状态在重新解析后仍然存在;从数据中消失的条目会丢失它,而不是像隐藏的幽灵一样徘徊。

一次几个键 ​

一张编码三件事的图表——填充中的种类、外壳中的出处、笔划中的关系——需要三个键,而不是一个。通过 sections,每个标题块都会获得自己的标题块,在一张停靠的卡内按照声明顺序从上到下堆叠:

ts
UI: {
    legend: {
        position: 'bottom-left',        // the card docks; sections don't
        sections: [
            { key: 'type',  title: 'Element' },
            { key: 'scope', title: 'Provenance' },
            { key: 'tlp',   title: 'Sharing', filterable: false },
        ],
    },
}

一个部分包含单个图例所包含的所有内容,除了属于该卡的position。各个部分在其他方面都是独立的:它们自己的条目、它们自己的计数、它们自己的折叠状态、它们自己的过滤器。

过滤器并在一起 ​

每个可过滤部分驱动其自己的过滤器,查询引擎对它们进行处理:在第一个部分中关闭attribute,在第二个部分中关闭self,留在画布上的是都不是的节点。每个部分的 show all 仅清除该部分。

节写入 __legend:<id>,其中 id 是节的 id,否则是 key,否则是它在堆栈中的位置 (section-0)。 单键图例——对象形式——保留了它一直使用的普通__legend。与一个单独的图例一样,其 key 命名已声明的 select / multiselect 刻面 的部分反而会驱动该刻面,并且其兄弟姐妹不受影响。

对边而不是节点进行关键帧处理 ​

声明 scope: 'edge' 的部分列出了图形的 **关系类型 ** 以及 line 样本(渲染器解析它们时的描边颜色、破折号和标记),并且其切换隐藏边缘层而不是节点。它位于同一张卡中的节点范围部分旁边,并使它们保持不变。整个功能请参见边缘层。

ts
UI: {
    legend: {
        sections: [
            { key: 'type', title: 'Element' },
            { key: 'kind', title: 'Relationship', scope: 'edge' },
        ],
    },
}

命名您设置样式所依据的尺寸 ​

既没有 key 也没有 entries 的部分是您已经声明为 render.nodeTypeAccessor 的维度 — 这是不是普通数据键的样式维度的一种拼写。它会跳过颜色检查:在您要求的sections列表中。只有一个部分可以执行此操作;第二个被丢弃并带有警告。

ts
UI: { legend: { sections: [{}, { key: 'scope', title: 'Provenance' }] } }
//                         ↑ whatever nodeTypeAccessor returns, headed "Type"

关闭颜色维度的部分

样本是从渲染器解析的颜色中采样的,这是图例可以读取的唯一通道。以颜色不编码的维度(来源,当来源被绘制为封闭体时)为关键的部分获取每个类别中第一个节点的颜色,并警告该类别呈现多个节点。在该部分声明 entries 和您自己的 color,以赋予其有意义的样本。

空间 ​

各部分单独折叠; alt-单击任意 V 形可立即折叠或展开整个堆栈。每个部分仍然将其自己的列表滚动到超过maxVisibleEntries,并且卡片作为一个整体被画布高度限制并滚动而不是超过它 - 因此六个部分保留在视口内。

解析为无条目(没有节点携带的键,空声明)的部分将被完全跳过,而不是显示为空标题框;部分全为空的卡片不会呈现任何内容。

将鼠标悬停在类别上 ​

指向一行,画布就会给出答案:类别所代表的元素保持其外观,其他所有内容都会变暗,直到指针离开。没有任何内容被过滤,也没有任何内容移动,因此这是在决定是否关闭某个类别之前找到该类别所在位置的廉价方法。

scope: 'edge'部分上的一行点亮其线,节点与其他层一起后退。折叠成闭合簇或 simplify 组的边会照亮在其位置绘制的线。

指向已经关闭的类别不会使任何内容变暗 - 画布上没有任何内容可供其点亮。

highlightOnHover: false 将其关闭一段。 filterable: false 键也会突出显示,这是一行唯一执行的操作。

同一组可以从代码中点亮,并保持直到被清除:

js
graph.emphasiseElements(graph.getMutableNodes().filter((node) => node.getData()?.type === 'md5'))
graph.clearEmphasis()

两者都采用渲染器绘制的元素,因此它们读取 getMutableNodes() / getMutableEdges() 而不是克隆 getter。

过滤 ​

切换一行会将过滤器写入 graph.queryEngine — 与 过滤器面板 驱动的引擎相同 — 因此它不是第二个并行机制:

  • 在隐藏类别中添加之后切换的节点将被隐藏。
  • 隐藏类别隐藏在扩展集群的子图中。
  • resetFilters(),或面板的重置,重新点亮每一行。
  • 显示的每一行过滤器都是 removed,因此标题的活动过滤器计数不会报告未隐藏任何内容的图例。

默认情况下,图例拥有一个自己的保留过滤键 (__legend),通过谓词匹配 — 每个部分一个,命名空间为__legend:<id>,采用堆叠形式。

与面板共享过滤器 ​

当 key 命名已声明的 select / multiselect facet 时,图例会驱动 ** 该facet 的键**。图例和面板然后成为一个过滤器的两个视图:关闭样本,面板的多选会删除该值;在面板中选择值,图例会相应地重新亮起。

ts
UI: {
    filter: { facets: [{ key: 'type', label: 'Type', type: 'multiselect', options: … }] },
    legend: { key: 'type' },   // ⇒ writes setFilter('type', …)
}

使用专家组语言的两个后果:

  • 空多重选择意味着对面板没有约束,因此图例无法表达“隐藏所有内容”:最后显示的行被禁用,而不是写入一个将使整个图形恢复的值。其自身密钥的图例没有这样的限制。
  • 键具有 **无值 ** 的节点会被任何选择隐藏,就像从面板中过滤时一样。

如果 key 命名另一种类型的切面(text、regex、numberRange、boolean),图例将保留自己的键并发出警告 - 值列表在那里没有任何意义。

读取切换开关 ​

每个切换都会在数据事件总线上公布:

ts
graph.on('legendToggle', ({ section, hidden, visible }) => {
    localStorage.setItem(`legend.hidden.${section}`, JSON.stringify(hidden))
})

section 是已切换部分的 ID,hidden / visible 是该部分的行。单键图例报告其自己的派生 ID(其 key,其他section-0)。

恢复与传说中的调用相同:

ts
graph.queryEngine.setFilter('__legend', { value: visible, matchMode: 'exact' })

在运行时更改图例 ​

graph.setLegend(config) 取代 UI.legend 上线。开始时没有图例的图表会立即构建一个图例,然后 false 删除它 - 用它清除其过滤器,因此没有任何内容隐藏在消失的图例后面。

ts
graph.setLegend({ key: 'zone', title: 'Region' })
graph.setLegend({ sections: [{ key: 'zone' }, { key: 'tier' }] })
graph.setLegend(false)        // remove it
graph.setLegend(true)         // back to the derived one

在两个表单之间交换会重命名过滤器键,因此您留下的表单的过滤器将被删除:没有任何内容隐藏在消失的部分后面。

选项 ​

UI.legend 还采用 boolean:false 抑制图例,true 从 render.nodeTypeAccessor 派生一个,而无需先审查颜色。下面的一切都是对象形式。

stacked形式为{ enabled?, position?, sections }:sections是下面的列表减去position,enabled / position描述整个卡片。

选项类型默认值它的作用
enabledbooleantruefalse 保留声明但不显示任何内容(与 legend: false 相同)。
idstringkey,否则section-<index>部分标识:其过滤键 (__legend:<id>) 和 legendToggle section 字段。
titlestring美化key,否则'Legend'标题文本,逐字使用(因此可以翻译)。
keystring—行派生自的数据键,以及声明条目的默认谓词。对于 automatic 图例,省略此值和 entries。
entriesLegendEntry[] | (graph) => LegendEntry[]—声明的行;函数在数据更改时重新解析。
position'bottom-left' | 'bottom-right' | 'top-left' | 'top-right'full模式下'bottom-right',否则'bottom-left'它停靠在哪个画布角。属于卡片,所以它是不是一个分区选项。 'top-left' 与上下文工具面板共享其锚点,该面板在打开时覆盖图例。
collapsiblebooleantrue显示将其折叠到标题的 V 形符号。
collapsedbooleanfalse开始折叠。
showCountsbooleantrue显示每个类别的节点计数(在整个图表上,因此在切换时它不会闪烁)。
filterablebooleantruefalse 呈现一个普通的、非交互式的密钥。
highlightOnHoverbooleantrue将鼠标悬停在画布上的行会点亮该类别,并使其余部分变暗。
maxVisibleEntriesnumber12列表之前显示的行在图例内滚动。

LegendEntry 是 { id, label?, color, badge?, predicate?, order? }。 id 是行的标识、写入过滤器的值以及标签的后备。

当节点通过 badge 而不是通过其填充来区分时,请给出 badge 的条目,并且该行显示标记而不是点。它是按照画布绘制的方式绘制的,并且一个名为“color”的徽章占据了该条目。过滤没有改变。

js
{ id: 'enriched', label: 'From enrichment', color: '#8b5cf6',
  badge: { svgIcon: sparkle }, predicate: (node) => node.getData().enriched }

maxVisibleEntries 是图例高度的上限;画布是另一个。

在 full 模式下,图例默认停靠在右下角,堆叠在该模式也安装的小地图上方:左列属于模式导轨及其面板,而其面板是工作区而不是设置表的导轨模式向下延伸得足够远,以使图例成为单行。当小地图共享选定的角落时,图例位于其顶部,在其折叠、调整大小或卸载时跟随它。

bottom-left 图例与模式轨共享其列,因此在短视口中,它会缩小到模式轨之间的空间,并滚动到落在其上的任何行,而不是在模式轨下生长。它永远不会自行移动角落。

互动 ​

手势效果
悬停一行点亮画布上的该类别,调暗其他所有内容
单击一行隐藏/显示该类别
Alt-单击一行只显示该类别
标题显示全部重新点亮每一行(清除图例的过滤器)
标头反转交换显示的类别
标头 V 形将该部分折叠到其标题
Alt-单击 V 形图标一次折叠或展开每个部分

行是真正的按钮:可通过 Tab 键访问,Enter / Space 切换,aria-pressed 携带状态。隐藏行是用空心样本和灰色文本绘制的,因此颜色从来都不是唯一的信号。

有关实时示例,请参阅 可过滤图例 图库卡,有关完整类型,请参阅 LegendOptions / LegendGroupOptions。