Leyenda
UI.legend acopla una leyenda en una esquina del lienzo: una fila por categoría, cada una con un muestra de color, una etiqueta y el número de nodos detrás de ella. Apuntando a una fila de luces esa categoría en el lienzo; Al hacer clic en uno, se oculta, por lo que la leyenda funciona como filtro más rápido en la interfaz de usuario.
const options = {
UI: {
legend: { key: 'type', title: 'Node type' },
},
}Es posible que no necesites ese bloque en absoluto: sin UI.legend, aparece una leyenda ** en su propio** cuando los colores de su gráfico se explican mediante un render.nodeTypeAccessor declarado — consulte Activado de forma predeterminada. UI.legend: false lo apaga.
Un gráfico que codifica varias cosas a la vez necesita varias claves: pasar sections en lugar de una sola tecla, consulte Varias teclas a la vez.
La leyenda es parte del cromo, por lo que aparece solo en los modos full y light: viewer y static no tienen ninguno.
La leyenda nunca colorea nada.
La leyenda es descriptiva. Lee el color que el renderizador ya resolvió. un nodo (renderer.getNodeStyle(node).color) y lo informa. La coloración se queda donde era: render.defaultNodeStyle.color, render.nodeStyleMap o un estilo por nodo - normalmente a través de ColorPaletteMapper. Cambia la paleta y la leyenda sigue sola.
Activado de forma predeterminada
Sólo vale la pena mostrar una leyenda sin que se la pregunte si se garantiza que dice la verdad, por lo que la automático, uno comienza a partir de algo que ya has declarado en lugar de una suposición sobre tus datos: render.nodeTypeAccessor, la dimensión que apuntas nodeStyleMap a las.
Sin embargo, tener un candidato no es suficiente: una dimensión puede particionar sus datos sin tener algo que ver con sus colores. Entonces, antes de representar algo, la leyenda comprueba que esta dimensión explica los colores:
- cada categoría se resuelve exactamente en un color;
- hay al menos dos colores distintos (de lo contrario, los colores no son reveladores) las categorías aparte);
- hay como máximo 24 categorías: una dimensión similar a una identificación produce un valor por nodo, cada uno con su propio color, que de otro modo pasaría por el control anterior.
Si algo de eso falla, no aparece ninguna leyenda y no se registra nada: usted no solicitó ninguna. La leyenda automática también se omite más allá de 5000 nodos, donde se muestrean los datos de cada nodo. No vale la pena pagar por el color sin ser invitado, eso se advierte, por lo que la ausencia es explicable. Declarar UI.legend (o true) eleva ambos.
// 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 placementUna leyenda automática clave en un descriptor de acceso en lugar de una clave de datos, por lo que no puede comparte un filtro con una faceta declarada: dale una explícito key para eso.
De donde vienen las entradas
Derivado de una clave de datos
key es la configuración completa en el caso común: los distintos valores de node.getData()[key] se convierten en las filas, en el orden en que se ven por primera vez, etiquetadas con el valor mismo.
UI: { legend: { key: 'type' } }Una clave con valor de matriz contribuye con una fila por elemento, y un nodo cuenta menos cada uno de ellos (tags: ['public', 'critical'] aparece debajo de ambos).
Vale la pena saber dos cosas sobre las filas derivadas:
- Los nodos sin valor para la clave (
null,undefined,'') no obtienen fila y el La leyenda nunca puede ocultarlos: solo actúa sobre las categorías que enumera. Un tiempo de desarrollo La advertencia nombra la clave y cuántos nodos no están representados. - Una categoría pintada en más de un color mantiene el primer color encontrado, con un Advertencia: una fila solo puede mostrar una muestra. Declare las entradas usted mismo si el la agrupación no es realmente de un solo color.
Entradas declaradas
Pase entries cuando las categorías no sean una clave de datos simple: agrupaciones calculadas, etiquetas traducidas, una escala de colores fija. Cada entrada lleva su propio predicate, que es lo que filtra el interruptor.
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 también puede ser una función del gráfico, que se vuelve a resolver siempre que los datos cambios, por lo que la lista sigue los datos sin que la declaración se agite:
UI: {
legend: {
key: 'type',
entries: (graph) => distinct(graph, 'type').map((type) => ({
id: type,
label: t(`type.${type}`), // translated, used verbatim
color: palette.getColor(type),
})),
},
}Declarar tanto entries como key es el término medio útil que se muestra arriba: el las entradas dan las etiquetas y los colores, y key proporciona el predicado predeterminado (data[key] === id) para entradas que no llevan uno. Una entrada sin ninguno de los dos advierte. y no coincide con nada.
El estado de alternancia de una fila sobrevive a una nueva resolución; una entrada que desaparece de los datos lo pierde en lugar de permanecer como un fantasma oculto.
Varias teclas a la vez
Un gráfico que codifica tres cosas: tipo en el relleno, procedencia en el recinto, relación en el trazo: necesita tres claves, no una. Pase sections y cada uno obtiene su propio bloque titulado, apilado de arriba a abajo en orden de declaración dentro de uno acoplado tarjeta:
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 },
],
},
}Una sección toma todo lo que toma una sola leyenda excepto position, que pertenece a la tarjeta. Las secciones son independientes en todo lo demás: sus propias entradas, sus propios recuentos, su propio estado de pliegue, su propio filtro.
Filtros y juntos
Cada sección filtrable controla su propio filtro, y el motor de consulta los envía: apague attribute en la primera sección y self en la segunda, y qué Lo que permanece en el lienzo son los nodos que son ninguno. Cada sección es show all borra sólo esa sección.
Una sección escribe en __legend:<id>, donde la identificación es id de la sección, de lo contrario es key, de lo contrario su lugar en la pila (section-0). Una leyenda de una sola clave: el objeto forma: mantiene la llanura __legend que siempre ha usado. Como ocurre con una leyenda solitaria, una sección cuyo key nombra una faceta select / multiselect declarada controla esa faceta en cambio, y sus hermanos son no afectado.
Bordes clave en lugar de nodos
Una sección que declara scope: 'edge' enumera los tipos de relación del gráfico con una línea muestra (color de trazo, guión y marcador a medida que el renderizador los resolvió) y sus opciones Ocultar capas de bordes en lugar de nodos. Se encuentra junto a las secciones con alcance de nodo en la misma tarjeta. y los deja intactos. Consulte Capas de borde para conocer la función completa.
UI: {
legend: {
sections: [
{ key: 'type', title: 'Element' },
{ key: 'kind', title: 'Relationship', scope: 'edge' },
],
},
}Nombrar la dimensión por la que diseñas
Una sección que no tiene ni key ni entries es la dimensión que ya declaraste como render.nodeTypeAccessor: la única forma de escribir una dimensión de estilo que no es una clave de datos simples. Se salta la comprobación de color: dentro de una lista sections tu lo pediste. Sólo una sección puede hacer esto; se cae un segundo con una advertencia.
UI: { legend: { sections: [{}, { key: 'scope', title: 'Provenance' }] } }
// ↑ whatever nodeTypeAccessor returns, headed "Type"Una sección desconectada de la dimensión del color.
Las muestras se toman de los colores que el renderizador resolvió, y esa es la única canal que la leyenda puede leer. Una sección codificada en una dimensión que los colores no codifican — procedencia, cuando la procedencia se dibuja como un recinto — obtiene el color del primero nodo en cada categoría y advierte que la categoría representa más de uno. declarar entries con tu propio color en esa sección para darle muestras de ese significado algo.
espacio
Las secciones se pliegan individualmente; alt-haga clic en cualquier galón para doblar o desplegar todo apilar de una vez. Cada sección todavía desplaza su propia lista más allá de maxVisibleEntries, y la tarjeta en su conjunto está tapada contra la altura del lienzo y se desplaza en lugar de creciendo más allá de él, por lo que seis secciones permanecen dentro de la ventana gráfica.
Una sección que se resuelve en sin entradas (una clave que ningún nodo lleva, un vacío declaración) se omite por completo en lugar de mostrarse como un cuadro con título vacío; una tarjeta cuyas secciones están todas vacías no muestra nada en absoluto.
Pasando el cursor sobre una categoría
Señale una fila y el lienzo responderá: los elementos que representa esa categoría mantienen el Mira que tienen, todo lo demás se atenúa hasta que el puntero se va. Nada se filtra y nada se mueve, por lo que es la forma más económica de encontrar dónde se ubica una categoría antes de decidir si apagarlo.
Una fila en una sección scope: 'edge' ilumina su líneas, con los nodos retrocediendo junto con las otras capas. Un borde doblado en forma de un grupo cerrado o un grupo simplify ilumina la línea dibujada en su lugar.
Señalar una categoría que ya está desactivada no atenúa nada: no hay nada dejado en el lienzo para que se ilumine.
highlightOnHover: false lo desactiva para una sección. Una tecla filterable: false resalta también, donde es lo único que hace una fila.
El mismo conjunto se puede encender a partir del código y se mantiene hasta que se borra:
graph.emphasiseElements(graph.getMutableNodes().filter((node) => node.getData()?.type === 'md5'))
graph.clearEmphasis()Ambos toman los elementos que dibujó el renderizador, por lo que leen getMutableNodes() / getMutableEdges() en lugar de los captadores de clonación.
Filtrado
Al alternar una fila se escribe un filtro en graph.queryEngine, el mismo motor que el panel de filtro unidades, por lo que nada de esto es un segundo paralelo mecanismo:
- Los nodos agregados después de un interruptor, en una categoría oculta, llegan ocultos.
- Una categoría oculta permanece oculta dentro del subgrafo de un grupo expandido.
resetFilters(), o ** Reset ** del panel, vuelve a iluminar cada fila.- Con cada fila mostrada, el filtro se eliminado, por lo que el recuento de filtros activos del encabezado No relata una leyenda que no esconde nada.
De forma predeterminada, la leyenda posee una clave de filtro reservada propia (__legend) que coincide a través de un predicado, uno por sección, con un espacio de nombres como __legend:<id>, en el forma apilada.
Compartir un filtro con el panel
Cuando key nombra un select / multiselect declarado faceta, la leyenda controla la clave de esa faceta. La leyenda y el panel se convierten entonces en dos vistas de un filtro: apague una muestra y la selección múltiple del panel elimina ese valor; elegir valores en el panel y la leyenda se vuelve a encender en consecuencia.
UI: {
filter: { facets: [{ key: 'type', label: 'Type', type: 'multiselect', options: … }] },
legend: { key: 'type' }, // ⇒ writes setFilter('type', …)
}Dos consecuencias de hablar el idioma del panel:
- Una selección múltiple vacía significa sin restricciones para el panel, por lo que la leyenda no puede expresar "ocultar todo": la última fila mostrada está deshabilitada en lugar de escribir un valor que recuperaría todo el gráfico. Una leyenda por sí sola no tiene tal límite.
- Los nodos con sin valor para la clave están ocultos por cualquier selección, exactamente como están cuando filtras desde el panel.
Si key nombra una faceta de otro tipo (text, regex, numberRange, boolean) La leyenda mantiene su propia clave y advierte: una lista de valores no tiene significado allí.
Leyendo los alternadores
Cada cambio se anuncia en el bus de eventos de datos:
graph.on('legendToggle', ({ section, hidden, visible }) => {
localStorage.setItem(`legend.hidden.${section}`, JSON.stringify(hidden))
})section es la identificación de la sección que se cambió, y hidden / visible son esas filas de la sección. Una leyenda de una sola clave informa su propia identificación derivada (es key, de lo contrario section-0).
Restaurar es el mismo llamado que hace la leyenda:
graph.queryEngine.setFilter('__legend', { value: visible, matchMode: 'exact' })Cambiar la leyenda en tiempo de ejecución
graph.setLegend(config) reemplaza UI.legend en vivo. Un gráfico que comenzó sin legend crea uno en el lugar y false lo elimina, limpiando su filtro con para que nada quede oculto detrás de una leyenda que ya no existe.
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 oneAl intercambiar entre los dos formularios se cambia el nombre de las claves de filtro, por lo que los filtros del formulario que Las secciones que quedan se eliminan: nada queda oculto detrás de una sección que ya no está.
Opciones
UI.legend también toma un booleano: false suprime la leyenda, true deriva uno desde render.nodeTypeAccessor sin examinar primero los colores. Todo lo que aparece a continuación es la forma del objeto.
La forma stacked es { enabled?, position?, sections }: sections es la lista a continuación menos position y enabled / position describen la tarjeta completa.
| Opción | Tipo | Predeterminado | que hace |
|---|---|---|---|
enabled | boolean | true | false mantiene la declaración pero no muestra nada (igual que legend: false). |
id | string | key, si no section-<index> | Identidad de la sección: su clave de filtro (__legend:<id>) y el campo legendToggle section. |
title | string | embellecido key, más 'Legend' | Texto del encabezado, usado palabra por palabra (para que pueda traducirse). |
key | string | — | Clave de datos de la que se derivan las filas y predicado predeterminado para las entradas declaradas. Omita esto y entries para la leyenda automatic. |
entries | LegendEntry[] | (graph) => LegendEntry[] | — | Filas declaradas; una función se vuelve a resolver al cambiar los datos. |
position | 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right' | 'bottom-right' en modo full, en caso contrario 'bottom-left' | En qué esquina del lienzo se acopla. Pertenece a la tarjeta, por lo que es no una opción de sección. 'top-left' comparte su ancla con el panel de herramientas contextual, que cubre la leyenda mientras está abierto. |
collapsible | boolean | true | Muestre el galón que lo dobla hasta su título. |
collapsed | boolean | false | Empiece doblado. |
showCounts | boolean | true | Muestra el recuento de nodos por categoría (en todo el gráfico, para que no parpadee al alternar). |
filterable | boolean | true | false genera una clave simple y no interactiva. |
highlightOnHover | boolean | true | Al pasar el cursor sobre una fila, se ilumina esa categoría en el lienzo y se atenúa el resto. |
maxVisibleEntries | number | 12 | Las filas que se muestran antes de que la lista se desplace dentro de la leyenda. |
Un LegendEntry es { id, label?, color, badge?, predicate?, order? }. id es la fila identidad, el valor escrito en el filtro y el respaldo de la etiqueta.
Cuando los nodos se distinguen por una badge en lugar de por su relleno, proporcione la entrada que badge y la fila muestra la marca en lugar de un punto. Está dibujado de la forma en que El lienzo lo dibuja y una insignia con el nombre color toma la entrada. El filtrado no ha cambiado.
{ id: 'enriched', label: 'From enrichment', color: '#8b5cf6',
badge: { svgIcon: sparkle }, predicate: (node) => node.getData().enriched }maxVisibleEntries es un techo en la altura de la leyenda; el lienzo es el otro.
En el modo full, la leyenda se acopla en la parte inferior derecha de forma predeterminada, apilándose encima del minimapa. ese modo también se monta: la columna izquierda pertenece al carril del modo y sus paneles, y un El modo Rail, cuyo panel es un espacio de trabajo en lugar de una hoja de configuración, llega lo suficientemente lejos. Bájelo para dejar la leyenda en una sola fila. Cuando un minimapa comparte la esquina elegida, La leyenda se ubica encima de él, siguiéndolo mientras se contrae, cambia de tamaño o se desmonta.
Una leyenda bottom-left comparte su columna con el carril modal, por lo que en una ventana gráfica corta se reduce a la habitación entre ellos y se desplaza en cualquier fila que aterrice, en lugar de que crecer bajo la barandilla. Nunca mueve una esquina por sí solo.
Interacción
| gesto | Efecto |
|---|---|
| Coloca el cursor sobre una fila | Ilumina esa categoría en el lienzo, atenúa todo lo demás. |
| Haga clic en una fila | Ocultar/mostrar esa categoría |
| Alt-hacer clic en una fila | Mostrar solo esa categoría |
| Encabezado mostrar todo | Vuelva a iluminar cada fila (borra el filtro de la leyenda) |
| Encabezado invertir | Intercambiar las categorías que se muestran |
| Encabezado chevron | Dobla esa sección a su título. |
| Alt-haga clic en el galón | Doblar o desplegar cada sección a la vez |
Las filas son botones reales: accesibles mediante tabulación, Enter / Space alternar y aria-pressed lleva el estado. Se dibuja una fila oculta con una muestra hueca y texto atenuado, por lo que el color nunca es la única señal.
Vea la tarjeta de la galería Leyenda filtrable para un ejemplo vivo, y LegendOptions / LegendGroupOptions para el tipos completos.