界面选项
Pivotick 在图表顶部提供灵活的 UI 层,允许您控制用户与节点、边和画布交互的方式。使用 UI 选项,您可以:
- 配置 UI 的整体 mode(完整、查看器、静态等)。
- 自定义 sidebar 和面板以显示属性或额外信息。
- 为节点和边定义 tooltips,并使用可选的自定义渲染器。
- 为节点、边和画布配置 上下文菜单。
- 声明 filter 面板的构面,或者让它们从您的数据中派生。
- 将 legend 停靠在画布上 - 颜色的键,兼作过滤器,当您的颜色由声明的节点类型解释时,它会单独出现。
- 根据您按需获取的数据,异步填充这些表面 ****。
- 关闭您的集成没有用的任何功能。
- 将库自己的文本转换为用户的语言:请参阅翻译 UI。
用户界面模式
mode 选项控制图形 UI 的整体行为和交互级别。
full默认:完整的 UI,启用所有面板、菜单和交互。light:启用基本交互的最小 UI。viewer:仅允许导航图形(平移、缩放、拖动),而不显示任何 UI 面板。static:静态图,没有UI面板或交互;该图是只读的。
对于 Pivotick 的图像样式用法,请使用以下内容:
const container = document.getElementById('graph-container')
const options = {
UI: {
mode: 'viewer'
},
}
const graph = Pivotick(container, options)其他UI组件可以通过各自的命名空间进行配置
const options = {
UI: {
sidebar: {},
mainHeader: {},
propertiesPanel: {},
extraPanels: [],
tooltip: {},
contextMenu: {},
filter: {},
}
}full模式控制面
在full模式下,镶边是模式驱动的布局:左侧模式导轨(选择/创建/查看/物理),用于活动指针模式的上下文工具面板,两个设置弹出窗口 - View(画布背景和开关)和Physics(布局 + 模拟)— 顶栏(搜索、过滤、注释、撤消/重做)、选择侧边栏(属性、构面、邻居和批量操作行)以及右侧视口Rail(适合居中、缩放、设置、全屏),以及位于空闲右下角的迷你地图,当画布太小而无法节省空间时(UI.minimap: false无法放下它),它会自行折叠起来。 light模式掉落侧边栏和小地图; viewer 仅保留视口导轨; static是一块裸露的画布。
从角落镀铬迁移
浮动的 GraphControls 和 GraphToolbar 覆盖层已被移除。布局和物理移至物理弹出按钮 (UIManager.physicsFlyout) - 它们在 1.5.0 中包含在视图弹出按钮 (UIManager.viewFlyout) 中,现在包含画布背景和网格开关。在工具面板 (UIManager.toolPanel) 和模式轨 (UIManager.modeRail) 中实时选择/创建工具。 UI.selectionMenu 选项已消失 - 使用 contextMenu 进行每个节点操作,使用侧边栏批量操作行进行多选操作。 UIManager.graphNaviation更名为graphNavigation。 UI.modeRail 选项及其禁用的 Explore / Enrich 插槽已被删除 - 使用 addRailMode 注册实模式。参见CHANGELOG。
Rail 内置了四种模式,但不是它可以容纳的唯一模式:插件添加了自己的 addRailMode,这就是构建了解 your 数据含义的探索或丰富模式的方式。
关闭功能
UI 模式决定图表获得多少镶边。 Chrome 中的每一项功能也可以一次关闭一项,这就是集成如何删除其后端或用户不需要的功能的方式。
关闭的功能需要一切:按钮、面板、上下文菜单条目和键盘快捷键都在一起,所以没有留下任何东西可以点击或按下并悄悄拒绝。
const options = {
UI: {
mode: 'full',
notes: { enabled: false },
history: { enabled: false },
inspector: { enabled: false },
editors: { deletion: { enabled: false } },
},
}开关
| 选项 | 搭配什么 |
|---|---|
UI.topBar.enabled | 顶部条带,其保留的高度,其控件拥有的快捷方式(Shift+J,Shift+K,Shift+N,Mod+Z)以及任何主机操作。使用下面的开关放下一颗药丸并保留其余的。 |
UI.search.enabled | 搜索丸,它的节点选择器和Shift+J。 |
UI.filter.enabled | Filter Graph 药丸、其面板和 Shift+K。 graph.queryEngine 仍然从代码中过滤。 |
UI.notes.enabled | 注释药丸和面板、Shift+N、添加注释工具、画布菜单的添加注释、N、注释上下文菜单和noteManager.addNote(拒绝)。 |
UI.history.enabled | 撤消/重做按钮、历史记录下拉列表和 Mod+Z / Mod+Shift+Z。 graph.history 继续录音。 |
UI.inspector.enabled | 节点菜单的“检查属性”条目和I。 |
UI.notifications.enabled | 干杯。 graph.notifier.* 变为无操作返回undefined。 |
UI.sidebar.enabled | 整个侧柱,以及它所占用的宽度。 |
UI.propertiesPanel.enabled | 侧边栏的属性面板及其分隔符。 |
UI.neighborsPanel.enabled | 侧边栏的相邻面板及其分隔符。 |
UI.viewFlyout.enabled | 查看栏按钮及其面板。 |
UI.physicsFlyout.enabled | 物理轨道按钮及其面板。 |
UI.tooltip.enabled | 悬停工具提示,包括固定的工具提示。还需要 { nodes, edges, groups } 或 (element, kind) => boolean,请参阅工具提示。 |
UI.contextMenu.enabled | 每个上下文菜单。 |
UI.navigation.enabled | 视口导轨:适合、缩放和全屏。 |
UI.legend: false | 画布图例,包括它自己衍生的图例。 |
UI.minimap: false | 小地图。 |
UI.emptyState: false | 空画布 显示卡片。 |
UI.table: false | 数据码头及其Shift+T。 |
UI.pivotMode: false | 拓展轨道模式,无论注册什么。 |
写入路径功能在 UI.editors 下具有相同的开关,因此只读集成会删除可供性,而不是否决每次点击:nodeCreator、edgeCreator、nodeEditor、edgeEditor 和 deletion。
渲染器行为在 render 下关闭:zoomEnabled(也使用轨道的缩放按钮,保持适合和居中)、dragEnabled、selectionBox.enabled(选框 ** 和 ** 选择 ▸ 套索工具)、enableNodeExpansion(V 形、其 Enter 和虚线折叠轮廓)、enableFocusMode和interactionEnabled同时显示所有内容。 simulation.enabled stops the layout from running.
创建模式遵循其工具
创建轨道模式仅包含四个工具:添加节点、添加边缘、添加注释和编辑节点。关闭所有四个,模式将离开导轨及其 C 快捷方式,而不是打开到空面板。选择始终保留。
顶部栏中您自己的操作
整个画布上的操作(例如保存画布)属于撤消/重做组旁边的顶部栏中。 UI.topBar.actions 声明以与“搜索”、“过滤器”和“注释”相同的样式绘制药丸,因此重新设计这些样式的主题也会重新设计它们。
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 }]
: [],
}],
},
},
}- Where.
placement: 'end'(默认)将药丸放在撤消重做组之前;'start'放在左边内置药丸后面。 Pills keep the order they were declared in. - 它说的是什么。
text、title、visible和enabled采用图形的值或函数。每次数据更改后,在graph.UIManager.refreshTopBar()上,并且一旦onclick返回的 Promise 解决后,都会再次读取这些函数。虽然这个承诺已经兑现,但药丸已被禁用,因此缓慢的保存不能启动两次。 - 它得到什么。
onclick(event, ctx)接收图形和两个打开库模态的帮助器:ctx.promptData({ fields })在取消时解析为值或null,ctx.confirm({ body })仅在确认按钮上解析true。ctx.refresh()重读每一个动作。 - 插入符号。 使用
menu,药丸将成为拆分按钮:标签运行onclick,并且插入符号打开行,其行格式与 上下文菜单(无子菜单)相同。函数形式被赋予相同的ctx,并在每次刷新和每次打开时调用;虽然它不返回任何行,但该药丸没有插入符号。 Escape or a click elsewhere closes the rows. - 快捷方式。
shortcut在药丸上画一个徽章。它只是一个标签:您自己注册绑定。
插件添加了一个带有 ctx.addTopBarAction(action) 的药丸,它返回一个处理器(参见 Plugins)。药丸遵循条带:没有 viewer 或 static 模式,也没有 UI.topBar.enabled: false 模式。
空画布
没有节点和注释的图表会在画布中间显示一张卡片,因此没有任何可绘制内容的源不会被读取为无法加载的图表。它会说“画布上还没有任何内容”,除非你给它别的东西要说:
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
},
},
},
}卡遵循数据。添加一个节点或注释会将其删除,然后手动删除最后一个或通过撤消带来它们的摄取,将其恢复。过滤器隐藏的节点仍然计数:图形变窄,而不是空的。
render 每次卡片出现时都会运行,而不是在卡片出现时每次更改时运行。 initial 是true,直到图表包含一个节点,因此清空整个画布的分析师可以被告知除空源之外的其他信息。返回的字符串呈现为纯文本,并且render可能是async,就像下面的钩子一样。
该卡片使用了镀铬的表面和边框,因此它遵循主题。它允许画布的手势通过,因此平移、缩放和画布菜单可以在其上工作,但交互内容除外:按钮、链接、表单控件或带有 tabindex 的任何内容都有自己的点击。 UI.emptyState: false什么也没显示。
异步内容
每个消费者提供的内容挂钩都可能返回 Promise 而不是内容本身。涵盖侧边栏的 mainHeader.render、propertiesPanel.render / nodePropertiesMap / edgePropertiesMap、neighborsPanel.render、额外面板的 title 和render、工具提示的、render、renderNodeExtra、renderEdgeExtra和属性图,以及空画布的render。
这种情况存在于以下情况:节点的数据是记录的引用,而不是记录本身,并且有趣的内容位于 HTTP 调用后面:
const options = {
UI: {
tooltip: {
renderNodeExtra: async (node, { signal }) => {
const res = await fetch(`/enrich/${node.getData().uuid}`, { signal })
return renderChips(await res.json()) // an HTMLElement
},
},
},
}添加async,转发signal,库会处理剩下的事情:
| 占位符 | 当承诺悬而未决时,一个主题骨架占据了这个位置。 |
| 交换 | 解析时,内容将替换适当的占位符。 |
| 陈旧 | 在其槽消失后到达的结果 - 您将鼠标悬停在另一个节点上,更改了选择,刷新了面板 - 是dropped。只有表面的最新渲染才能提交,无论它们解析的顺序如何。 |
| 取消 | 当渲染被取代或图表被拆除时,ctx.signal 会中止,因此转发的 fetch 会被取消而不是泄漏。 |
| 失败 | 被拒绝的 Promise 会呈现一个紧凑的错误行,而不是永远留下一个旋转器。中止的渲染并不是失败,也不会显示任何内容。 |
渲染上下文
每个内容挂钩都会接收 RenderContext 作为其 last 参数。现有的同步钩子只是忽略它。
render: async (element, { signal, isStale }) => {
const rows = await fetchRows(element, signal)
if (isStale()) return '' // cheap guard for non-abortable work
return renderRows(rows)
}自定义占位符
UI.asyncContent 覆盖待处理和失败时显示的内容。两者都接受一个字符串、一个 HTMLElement 或一个曲面函数:
const options = {
UI: {
asyncContent: {
placeholder: (surface) => surface === 'tooltip' ? 'Loading…' : mySkeleton(),
error: 'Could not load',
},
},
}surface是'tooltip'、'properties'、'neighbors'、'mainHeader'、'extraPanel'或'emptyState'之一。
同步钩子未受影响
直接返回内容的行为与往常一样 - 相同的调用、相同的框架、没有占位符和包装元素。现有集成没有任何变化。
什么不能是异步的
两组有意保持同步:
HeaderMapEntry.title/subtitle提供自动调整标题槽和节点搜索(resolveNodeByName),两者现在都需要文本。如果您需要在标头中获取详细信息,请使用异步mainHeader.render。PropertyEntry.name/value— 改为获取行:异步nodePropertiesMap解析一次,然后返回普通条目,而不是在每个单元格中放置一个旋转器。
每帧渲染器挂钩(render.renderNode、renderLabel、renderCluster 和 NodeStyle.html)也是仅同步的:它们在每个节点、每个刻度的绘制路径内运行。如果您需要异步节点decoration,请获取节点的数据并让同步渲染器读取它。