خيارات الشريط الجانبي
يمكن طي الشريط الجانبي افتراضيًا حسب حجم الشاشة أو تفضيلات المستخدم.
يحدد ما إذا كان الشريط الجانبي مطويًا بشكل افتراضي.
'auto'افتراضي: يبقي الشريط الجانبي مفتوحًا ما لم تكن هناك مساحة شاشة كافية، وفي هذه الحالة يتم طيه تلقائيًا.trueيبدأ الشريط الجانبي في الانهيار.falseيبدأ توسيع الشريط الجانبي.
يعرض الشريط الجانبي معلومات سياقية لعناصر الرسم البياني. يحتوي على ثلاثة مكونات قابلة للتخصيص:
- الرأس الرئيسي كـ
mainHeader - لوحة الخصائص كـ
propertiesPanel - لوحات إضافية مثل
extraPanels
UI.sidebar.enabled: false يسقط العمود بالكامل ويعيد عرضه إلى اللوحة القماشية. تحتوي لوحات الخصائص والجيران على مفتاح لكل منهما — UI.propertiesPanel.enabled، UI.neighborsPanel.enabled — الذي يزيل تلك اللوحة وفاصلها بينما بقية يبقى الشريط الجانبي. راجع إيقاف تشغيل الميزات.
انقر لرؤية الرمز
UI: {
mode: 'full',
sidebar: {
collapsed: false,
},
mainHeader: {
render: (element) => {
const div = document.createElement('div')
div.textContent = 'Main Header'
div.style.fontWeight = 'bold'
div.style.color = 'darkred'
div.style.background = 'var(--pvt-bg-color-8)'
div.style.padding = '4px 8px'
div.style.borderRadius = '4px'
return div
}
},
propertiesPanel: {
render: (element) => {
const div = document.createElement('div')
div.textContent = 'Properties Panel'
div.style.fontWeight = 'bold'
div.style.color = 'darkred'
div.style.background = 'var(--pvt-bg-color-8)'
div.style.padding = '4px 8px'
div.style.borderRadius = '4px'
return div
}
},
extraPanels: [
{
title: 'Extra panel #1',
render: (node) => {
const div = document.createElement('div')
div.textContent = 'Extra Panel #1'
div.style.fontWeight = 'bold'
div.style.color = 'darkred'
div.style.background = 'var(--pvt-bg-color-8)'
div.style.padding = '4px 8px'
div.style.borderRadius = '4px'
return div
},
},
{
title: 'Extra panel #2',
render: (node) => {
const div = document.createElement('div')
div.textContent = 'Extra Panel #2'
div.style.fontWeight = 'bold'
div.style.color = 'darkred'
div.style.background = 'var(--pvt-bg-color-8)'
div.style.padding = '4px 8px'
div.style.borderRadius = '4px'
return div
},
},
],
tooltip: {
enabled: false,
},
contextMenu: {
enabled: false,
},
},العنوان الرئيسي الواجهة
يعرض ملخصًا موجزًا للعقدة أو الحافة المحددة، مثل العنوان والعنوان الفرعي. يساعد المستخدمين على التعرف بسرعة على العنصر المحدد الحالي.
يمكن تخصيص لوحة الرأس الرئيسية من خلال وظائف رسم الخرائط. التعيين الافتراضي للعقدة هو
{
title: node => node.data.label ?? "Could not resolve title"
subtitle: node => node.data.description ?? ""
}يمكنك تغيير هذا التعيين عن طريق تجاوز الأجزاء التي تحتاجها:
const options = {
UI: {
mainHeader: {
nodeHeaderMap: {
title: node => `Node ${node.id}`,
subtitle: node => node.data.type ?? "",
}
}
}
}const options = {
UI: {
mainHeader: {
edgeHeaderMap: {
title: node => `Node ${node.id}`,
subtitle: node => node.data.type ?? "",
}
}
}
}const options = {
UI: {
mainHeader: {
render: (element) => {
const div = document.createElement('div')
div.textContent = 'Main Header'
return div
}
}
}
}تحذير
عند توفير render()، يتخطى Pivotick كل منطق التعيين الافتراضي، ما لم يُرجع undefined. النتيجة undefined (أو الوعد بالتحويل إلى undefined) ترسم الرأس الافتراضي لهذا التحديد: العنوان nodeHeaderMap / edgeHeaderMap لعنصر واحد، وعدد التحديد لعدة عناصر، وإجمالي اللوحة عندما لا يتم تحديد أي شيء. ارجع null لترك الرأس فارغًا.
mainHeader: {
// A custom header for a lone element, the default counts for everything else.
render: (element) => (element && !Array.isArray(element)) ? myHeader(element) : undefined,
}لوحة الخصائص الواجهة
يعرض الخصائص التفصيلية للعقدة أو الحافة المحددة في الشريط الجانبي. كل خاصية لها اسم وقيمة يمكن أن تكون ثابتة أو محسوبة ديناميكيًا.
السلوك الافتراضي هو إظهار جميع أزواج المفاتيح/القيمة من العقدة أو الحافة getData().
يمكنك تخصيص الخصائص التي يتم عرضها وكيفية عرضها باستخدام وظائف التعيين (nodePropertiesMap وedgePropertiesMap) أو عارض مخصص كامل.
const options = {
UI: {
propertiesPanel: {
nodePropertiesMap: (node: Node) => {
return [
{
name: 'Node ID',
value: node.id,
},
{
name: (node) => `Type of node`,
value: (node) => el ? el.type : 'Unknown'
},
{
name: 'Custom HTML',
value: document.createElement('div')
}
]
}
}
}
}const options = {
UI: {
propertiesPanel: {
edgePropertiesMap: (node: Node) => {
return [
{
name: 'Edge ID',
value: node.id,
},
{
name: (node) => `Type of edge`,
value: (node) => el ? el.type : 'Unknown'
},
{
name: 'Custom HTML',
value: document.createElement('div')
}
]
}
}
}
}const options = {
UI: {
propertiesPanel: {
render: (element: Node | Edge | Node[] | Edge[] | null) => {
const div = document.createElement('div')
div.textContent = `Element ID: ${element?.id}`
div.style.fontWeight = 'bold'
return div
}
}
}
}const options = {
UI: {
propertiesPanel: {
nodePropertiesMap: (node: Node) => {
return Object.entries(node.getData())
.filter(([key, value]) => key && value)
.map(([key, value]) => ({ name: key, value }))
}
}
}
}قد تقوم خريطة الخصائص بإرجاع عدة إدخالات بنفس الاسم، مثل إدخال Tag واحد لكل علامة. في التحديد المتعدد، تقوم كل قيمة بعد ذلك بحساب العقد التي تحملها، ويطابق الاحتفاظ/الاستبعاد أيًا من إدخالات العقدة، وتحصل كل قيمة على شريط خاص بها، نظرًا لتداخل القيم.
nodePropertiesMap: (node) => node.getData().tags.map((tag) => ({ name: 'Tag', value: tag }))نصيحة
عند توفير render()، يتخطى Pivotick كل منطق التعيين الافتراضي، ما لم يُرجع undefined. نتيجة undefined (أو وعد بالتحويل إلى undefined) ترسم اللوحة الافتراضية لهذا التحديد: الصفوف nodePropertiesMap / edgePropertiesMap لعنصر واحد، والجدول المجمع، مع مرشحات الاحتفاظ/الاستبعاد الخاصة به، لعدة عناصر. ارجع null لترك اللوحة فارغة.
const options = {
UI: {
propertiesPanel: {
// A custom view for a lone node, the default aggregated table for everything else.
render: (element) => (element instanceof Node) ? myNodeView(element) : undefined,
}
}
}لوحة الجيران الواجهة
يعرض اتصالات العقدة المحددة: رسم بياني صغير لجيرانها، وإحصائيات الاتصال، وقائمة.
يتم رسم الرسم البياني المجاور باستخدام خيارات عرض الرسم البياني الرئيسي بشكل افتراضي. يمكن للأنماط التي تناسب لوحة قماشية كاملة، مثل طبقات تفاصيل العقدة أو بطاقة التركيز، أن تحشد لوحة بهذا الحجم، لذا فإن graph يأخذ تجاوزات خاصة به:
- تم دمج
graph.renderفي خيارات عرض الرسم البياني الرئيسي. لا تزال إعدادات اللوحة الخاصة (بدون سحب، أو تكبير/تصغير، أو توسيع العقدة) سارية. يحددmaxZoomهنا أيضًا مدى تكبير الرسم البياني بحيث لا يتم تضخيم العقدة مع جار واحد. - تم دمج
graph.layoutفوق التخطيط الشعاعي للوحة. الجذر هو دائمًا العقدة المحددة.
const options = {
UI: {
neighborsPanel: {
graph: {
render: {
// Plain small nodes: no tiers, no focus card.
nodeStyleMap: { event: { shape: 'circle', size: 10 } },
maxZoom: 1,
},
layout: { radialGap: 80 },
},
},
},
}لوحات اضافية واجهة
يسمح بإضافة لوحات مخصصة بالكامل بمحتوى ديناميكي أو ثابت. تعتبر هذه اللوحات مثالية لعرض معلومات سياقية إضافية أو عناصر تحكم مخصصة أو عناصر واجهة مستخدم تفاعلية مرتبطة بالعنصر المحدد.
تحتوي كل لوحة إضافية على title وrender() اختياريين، وكلاهما يمكن أن يكون ثابتًا (سلسلة/HTMLelement) أو وظيفة من التحديد الحالي. يتم عرض string الذي تم إرجاعه كـ نص؛ قم بإرجاع HTMLElement لتقديم العلامات الخاصة بك. ارجع null لترك جسم اللوحة فارغًا.
const options = {
UI: {
extraPanels: [
{
title: "Info",
render: "This is a static extra panel content"
}
]
}
}// The selection is a Node, an Edge, an array of either, or null — this example
// only cares about a single element:
const single = (element) => (element && !Array.isArray(element)) ? element : null
const options = {
UI: {
extraPanels: [
{
// Both are called with the live selection, on every selection change.
title: (element) => single(element) ? `Node #${single(element).id}` : 'Nothing selected',
render: (element) => {
const div = document.createElement('div')
div.textContent = single(element)?.getData().description ?? 'No description'
return div
}
}
]
}
}التحديد الذي يتم عرض اللوحة به
يتم إعادة استدعاء title وrender في كل تغيير اختيار، مع ما تم تحديده حاليًا:
| التحديد | حجة |
|---|---|
| عقدة واحدة/حافة واحدة | Node أو Edge |
| عدة العقد / الحواف | a Node[] / Edge[] |
| لم يتم تحديد أي شيء | null |
يتم عرض اللوحة ** فقط أثناء تحديد شيء ما، ما لم يتم تعيين alwaysVisible: true — ولكن تتم إعادة عرض اللوحة التفاعلية في كلتا الحالتين، لذلك لا تحتوي أبدًا على محتوى يصف تحديدًا قديمًا.
قم بتعيين reactive: false للوحة لا تصف التحديد ويكون إنشاؤها مكلفًا: يتم عرضها بعد ذلك مرة واحدة، ولا يقوم سوى refreshPanel() الصريح بإعادة بنائها.
تسجيل اللوحات في وقت التشغيل
UI.extraPanels هو النموذج التصريحي لنفس السجل. أي شيء يمكنك الإعلان عنه هناك، يمكنك أيضًا تسجيله - وإزالته - في أي وقت في حياة الرسم البياني، من خلال UIManager:
const graph = new Pivotick(container, data, options)
// Register a panel that depends on the graph itself. Returns a disposer.
const dispose = graph.UIManager.addPanel({
id: 'unlinked-items',
title: 'Unlinked items',
alwaysVisible: true,
order: -1, // sorts above the option-declared panels
render: (selection) => tray.render(selection),
})
// Your own data changed (a save landed) rather than the selection —
// ask for a re-render instead of hand-patching the panel's DOM.
graph.UIManager.refreshPanel('unlinked-items')
// Gone for good (equivalent to calling `dispose()`):
graph.UIManager.removePanel('unlinked-items')| الطريقة | |
|---|---|
addPanel(panel) | تسجيل لوحة. يعود المتخلص. يتم إنشاء id تلقائيًا عند حذفه. يعمل قبل وبعد أن يصبح الرسم البياني جاهزًا، ومن البرنامج المساعد install (مثل ctx.addPanel). |
removePanel(id) | قم بإزالة اللوحة وDOM الخاص بها. |
refreshPanel(id?) | أعد عرض لوحة واحدة، أو جميعها. يقوم بتحديث اللوحات reactive: false أيضًا. |
getPanels() | اللوحات المسجلة، بترتيب العرض. |
يتم فرز اللوحات حسب order (تصاعدي، افتراضي 0) وتحتفظ بترتيب التسجيل ضمن نفس القيمة، لذلك تتم قراءة UI.extraPanels من أعلى إلى أسفل ويتم إلحاق لوحات وقت التشغيل بعدها.
تتلقى اللوحة title / render وسيطة ثانية - مقبض على نفسها - حتى تتمكن من إجراء التحديثات الخاصة بها دون الوصول إلى الرسم البياني:
render: (selection, panel) => {
const button = document.createElement('button')
button.textContent = 'Reload'
button.onclick = () => panel.refresh() // …or panel.remove()
return button
}الشريط الجانبي فقط
يتم عرض اللوحات بواسطة الشريط الجانبي الموجود في الوضع full. ينجح التسجيل في أي وضع — ببساطة ليس لدى اللوحة مكان لعرضه حتى يتم عرض الشريط الجانبي.
ملء لوحة بشكل غير متزامن
title و render قد يكونان async، كما هو الحال في لوحة الخصائص render / nodePropertiesMap / edgePropertiesMap والرأس الرئيسي render. تعرض اللوحة عنصرًا نائبًا أثناء تعليق الوعد:
graph.UIManager.addPanel({
id: 'sightings',
title: 'Sightings',
render: async (selection, panel, { signal }) => {
if (!(selection instanceof Node)) return 'Select a node'
const res = await fetch(`/sightings/${selection.id}`, { signal })
return renderSightings(await res.json())
},
})لاحظ ترتيب الوسيطة: يظل مقبض اللوحة في المرتبة الثانية، ويظل مقبض اللوحة في المرتبة الثانية RenderContext هو دائما الأخير.
ونظرًا لإعادة عرض اللوحة عند كل تغيير في التحديد، يتم إجراء عملية جلب بشكل روتيني يحل محله قبل أن يحل. المكتبة تتولى ذلك نيابة عنك: القديم يتم إحباط العرض signal، ووصول النتيجة بعد استمرار التحديد يتم إسقاطه بدلاً من رسمه في لوحة تصف عقدة مختلفة. ال وينطبق الشيء نفسه على refreshPanel() وعلى إزالة اللوحة. انظر محتوى غير متزامن للعقد كاملاً.