边缘层
一张关系看起来都很相似的图,当它携带多个kind关系时,它就不再可读。 边缘层是你需要解决这个问题的三件事,它们应该一起使用:
- 命名该种类 —
render.edgeTypeAccessor。 - 将其分开 —
render.edgeStyleMap。 - 将其关闭 —
UI.filter.edgeFacets,在过滤器面板中显示为实时切换开关,并且可选地,作为图例部分。
const options = {
render: {
edgeTypeAccessor: (edge) => edge.getData()?.kind,
edgeStyleMap: {
reference: { strokeColor: '#428bca' },
correlation: { strokeColor: '#888888', dashed: true, animateDash: false },
sighting: { strokeColor: '#f39a1f', dashed: true, markerEnd: 'circle' },
},
},
UI: {
filter: { edgeFacets: [{ key: 'kind', label: 'Relationship' }] },
},
}命名和样式化一个种类
edgeTypeAccessor 和 edgeStyleMap 完全镜像 nodeTypeAccessor / nodeStyleMap:访问器返回一个字符串(或 undefined),并且地图将该字符串转换为合并在默认边缘样式上的 Partial<EdgeStyle>。
render: {
edgeTypeAccessor: (edge) => edge.getData()?.kind,
edgeStyleMap: {
reference: { strokeColor: '#428bca', strokeWidth: 2 },
contains: { strokeColor: '#5cb85c', markerEnd: 'diamond' },
},
}每个 EdgeStyle 属性都是公平的游戏 - strokeColor、strokeWidth、opacity、curveStyle、dashed、animateDash、markerEnd、markerStart、rotateLabel。默认情况下,dashed 边缘会为其破折号设置动画;设置 animateDash: false 为一种应理解为平静的背景上下文。
没有种类的边或地图未提及的种类将保留默认的边样式。没有任何警告:无样式的类型是合理的选择。
优先级
与节点的顺序相同,最窄者获胜:
| 优先级 | 哪里 |
|---|---|
| 1(胜) | 边缘自己的style.styleCb — 请参阅下面的警告 |
| 2 | 边自己的静态 style 属性 |
| 3 | render.edgeStyleMap[kind] |
| 4 | render.defaultEdgeStyle.styleCb |
| 5 | render.defaultEdgeStyle 文字 |
这两个 styleCb 角色不是同一件事,值得保持一致。在边的 own 风格上,它是完全获胜的覆盖;在 render.defaultEdgeStyle 上,它是默认插槽* 的 * 计算形式,仅填充没有更窄集的内容 - 包括每条边 styleCb 遗漏的内容。特异性排序,而不是回调击败静态。
一条边自己的styleCb取代了它的整个层
当边自己的样式声明styleCb时,其返回值是该层的only源:边自己的静态属性和edgeStyleMap都被跳过,只有defaultEdgeStyle填补空白。因此,在同时设置 strokeColor 的边上返回 { strokeWidth: 4 } 的 styleCb 会失去该颜色,并且也会失去该种类的颜色。如果您想要回调 * 和 * 类型的样式,请在回调内进行查找,或者将回调放在 render.defaultEdgeStyle 上,在那里它会生成地图。
画布渲染器解析较少
renderers/canvas 尊重 edgeStyleMap 但仅读取九个 EdgeStyle 属性中的四个。 SVG 渲染器(默认)可以解决所有这些问题。
将一种类型设为图层
区分不同的样式只是成功的一半。 UI.filter.edgeFacets 声明哪些边尺寸是 可切换:
UI: {
filter: {
edgeFacets: [{ key: 'kind', label: 'Relationship' }],
},
}{ key: 'kind' }是一个完整的声明。边缘面具有边缘形状的默认值:层是 multiselect,其选项源自真实边缘实际携带的不同值,因此它永远不会提供返回空的选择。
这里没有任何东西是自动派生的。与节点面不同,它会回退到扫描数据,声明没有edgeFacets的图的行为与从未听说过层的图完全相同。边缘可见性非常重要,无法猜测。
过滤器面板会生成一个 Relationships 部分:每种类型一行,每行都有一个线样本和一个计数,立即应用 **** — 就像其上方的属性字段和旁边的图例一样。该面板中的任何内容都不会等待应用按钮。
不是图层的面
type 接受完整的 facet 词汇 — text、regex、select、multiselect、numberRange、boolean — 加上 accessor 和 predicate 对于非普通数据键的维度:
edgeFacets: [
{ key: 'kind', label: 'Relationship' }, // a layer
{ key: 'weight', label: 'Confidence', type: 'numberRange' }, // a batch control
{
key: 'recent',
label: 'Seen this week',
type: 'boolean',
accessor: (edge) => Date.now() - edge.getData().seenAt < 7 * 864e5,
},
]只有多选类型才是实时切换。其他一切都是批处理控件,因此它以面板的属性形式与节点面一起呈现,其中应用按钮是正确的可供性。
选项
| 选项 | 类型 | 默认值 | 它的作用 |
|---|---|---|---|
key | string | — | 过滤身份。 setEdgeFilter(key, …) 接受这个。 |
label | string | 美化了key | 逐字使用,因此它可以来自翻译层。 |
type | FilterFacetType | 'multiselect' | 图层是一组类型,每个类型打开或关闭。 |
options | array | (graph) => array | 导出的 | 每次重建时都会根据实时图表进行解决。 |
matchMode | FilterMatchMode | 'exact' | |
accessor | (edge) => unknown | edge.getData()[key] | 是什么使得计算方面成为可能。 |
predicate | (edge, value) => boolean | — | 完全控制;战胜accessor / matchMode。每个应用程序的每个边缘都运行,因此保持便宜。 |
order | number | 报关单 | 面板中的显示顺序。 |
切换是一个镜头,而不是布局变化
关闭图层会更改绘制的线条,而不会更改其他。节点位置、选择和相机逐位不变,并且不会重新启动模拟。
这是故意的,这就是专业工具所做的:vis-network 带有每条边 hidden * 和 * 一个单独的每条边 physics,Sigma 的 edgeReducer 永远不会到达布局,Cytoscape 和 KeyLines 仅在被要求时重新布局。隐藏关系是显示决策。如果隐藏相关层重新排列图形,则无法使用切换来读取图形,这是整个点。
改变它的一件事是选择加入,并且在节点侧:UI.filter.hideDisconnected隐藏了一层链的节点。这些节点离开模拟,因此图形重新设置 - 这就是为什么它默认关闭的原因,以及为什么它是一个节点过滤器而不是图层控件自己执行的操作。
机械地,Edge长出了第二个标志:
| 属性 | 含义 |
|---|---|
layerVisible | 该边缘的图层是否打开。对 visible 拥有否决权。 |
visibleIgnoringLayer | 如果每一层都打开,visible 会是什么:仅端点和手动隐藏原因。 |
setLayerVisible(on) | 切换图层,重新导出visible。返回是否有任何改变。 |
representedEdges | 对于替身来说:它所代表的真正优势。真实边缘上未定义。 |
链接力门控在visibleIgnoringLayer,因此层关闭的边会继续将其端点拉到一起。 visible 也是由端点过滤和 hideNode / showNode 编写的,这就是层状态与它分开的原因。
没有可见边缘的节点保持可见
隐藏它将是一个 node 过滤器决策,并且边缘面永远不会采取一个。如果您想要的话,请使用过滤器面板或queryEngine.setFilter。
空镐意味着每一层都脱落
对于节点多选,空列表是面板的拼写方式 unset — 无约束。边缘层控件准确地写入保持打开的内容,因此空的层列表意味着每个层都关闭。它没有任何其他含义,这就是为什么边缘部分没有“无法关闭最后一个”限制的原因。
对图例中的图层设置关键帧
声明 scope: 'edge' 的 legend 部分列出了带有 line 样本的类型 — 渲染器解析它们时的描边颜色、破折号和标记 — 位于同一个停靠卡中的节点范围部分旁边:
UI: {
legend: {
sections: [
{ key: 'type', title: 'Element' }, // nodes
{ key: 'kind', title: 'Relationship', scope: 'edge' }, // edges
],
},
}- 给定匹配的
edgeFacets声明,部分 ** 驱动该构面 ** — 面板和图例成为一个过滤器的两个视图,每个视图依次跟随另一个视图。 - 如果没有它,它保留了自己的一面并且仍然具有过滤性,因此图例绝不仅仅是装饰性的。
- 既没有
key也没有entries的部分使用render.edgeTypeAccessor,就像节点部分回落到nodeTypeAccessor一样。 - 计数具有 real 边:折叠集群的替代对象被排除在外,因此计数永远不会重复报告关系。
样本颜色是根据渲染器绘制的采样,因此以多种颜色渲染的颜色会保留第一个并发出警告。当种类不是笔划编码时,用您自己的 color 声明 entries。
塌陷的星团
当簇闭合时,其内部有一端的边会在任意深度被绘制到簇中。端点落在屏幕上相同两个节点上的边共享一条线,即替代,因此一条线可以代表多种真实关系。替身仅绘图:getEdges(),表格的“边缘”选项卡列出了真实的边缘。
因此,每个替身都携带representedEdges,并且当其中的任何通过过滤器时,它会存活下来。有两个值得了解的后果:
- 仅当隐藏图层背后的每个关系时,隐藏图层才会隐藏替身。当任何一个打开时,代表
reference和correlation的线都会保留。 - 每个分面类型都会到达折叠的簇内部 -
numberRange或predicate,而不仅仅是类型列表 - 因为分面与真实边缘而不是替身自己的(空)数据匹配。
单个边缘的替身看起来像该边缘,带有点,单击它可以选择该边缘。几个的替代品很简单,选择它会显示它代表了多少条边。
从代码驱动它
边缘面在构造函数中注册,因此编程过滤适用于每种模式 - 只有面板是full模式镶边。
graph.queryEngine.setEdgeFilter('kind', { value: ['reference'], matchMode: 'exact' })
graph.queryEngine.getHiddenEdgeCount() // 12
graph.queryEngine.removeEdgeFilter('kind') // every layer back on| 方法 | 它的作用 |
|---|---|
setEdgeFilter(key, config) | 编写一个边缘过滤器。 |
getEdgeFilters() | 活动边缘过滤器,无前缀。 |
removeEdgeFilter(key) | 删除一个 - 该图层集会重新出现。 |
getHiddenEdgeCount() | 一层隐藏了多少条边。 |
getEdgeFacetValues(key) | 不同的值,每个值都有一个计数和一个样本边缘。 |
setEdgeFacets(facets) | 替换声明的集合。 |
registerEdgeFacet(facet) | 添加一个附加项——图例部分用来保留自己的内容。 |
replaceFilters(ownedKeys, filters) | 仅更换您拥有的钥匙,不要打扰其他人。 |
节点和边缘过滤器共享一个 GraphFilters 记录,边缘键带有 edge: 前缀(EDGE_FILTER_PREFIX,从 GraphQueryEngine 导出),因此键名称可以同时是节点面和边缘面。上面的每个方法都隐藏了前缀;只有当你阅读原始记录时你才会遇到它。
renderer.getEdgeStyle(edge) 是公共的,返回渲染器实际解析的样式 - 图例的样本基于相同的调用,以及在测试中断言您声明的内容就是绘制的内容的方法。