Capas de borde
Un gráfico cuyas relaciones parecen todas iguales deja de ser legible en el momento en que lleva más de un tipo de relación. Capas de borde son las tres cosas que necesitas solucione eso, y están destinados a usarse juntos:
- Nombra el tipo —
render.edgeTypeAccessor. - Dale estilo —
render.edgeStyleMap. - Apágalo —
UI.filter.edgeFacets, apareció como alternancia en vivo en el panel de filtro y, opcionalmente, como sección de leyenda.
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' }] },
},
}Desactivar una capa nunca mueve el gráfico
Esta es la propiedad en torno a la cual se construye toda la función; consulte Alternar es una lente. El diseño, la selección y la cámara vuelven poco a poco idéntico, a menos que usted opte por ocultar nodos no conectados.
Nombrar y diseñar un tipo
edgeTypeAccessor y edgeStyleMap espejo nodeTypeAccessor / nodeStyleMap exactamente: el El descriptor de acceso devuelve una cadena (o undefined), y el mapa convierte esa cadena en una Partial<EdgeStyle> fusionado sobre el estilo de borde predeterminado.
render: {
edgeTypeAccessor: (edge) => edge.getData()?.kind,
edgeStyleMap: {
reference: { strokeColor: '#428bca', strokeWidth: 2 },
contains: { strokeColor: '#5cb85c', markerEnd: 'diamond' },
},
}Cada propiedad EdgeStyle es un juego limpio: strokeColor, strokeWidth, opacity, curveStyle, dashed, animateDash, markerEnd, markerStart, rotateLabel. Un borde dashed anima su guión de forma predeterminada; establecer animateDash: false para un tipo eso debería leerse como un contexto de fondo tranquilo.
Un borde sin tipo, o un tipo que el mapa no menciona, mantiene el borde predeterminado estilo. Nada avisa: un modelo sin estilo es una elección legítima.
Prioridad
El mismo orden que los nodos, gana el más estrecho:
| Prioridad | donde |
|---|---|
| 1 (gana) | el propio borde style.styleCb — ver la advertencia a continuación |
| 2 | las propias propiedades estáticas style del borde |
| 3 | render.edgeStyleMap[kind] |
| 4 | render.defaultEdgeStyle.styleCb |
| 5 | render.defaultEdgeStyle literales |
Los dos roles styleCb no son lo mismo y vale la pena mantenerlos recto. En el estilo propio de una ventaja, es una anulación la que gana por completo; en render.defaultEdgeStyle es la forma calculada de la ranura predeterminada, llenando solo lo que no se establece en nada más limitado, incluido lo que un borde styleCb omitió. Orden de especificidad, no callback-beats-static.
El styleCb propio de una ventaja reemplaza todo su nivel
Cuando el estilo propio de un borde declara un styleCb, su valor de retorno es el only fuente en ese nivel: las propiedades estáticas propias del borde y edgeStyleMap son ambas se omitió y solo defaultEdgeStyle llena los espacios en blanco. Entonces un styleCb regresando { strokeWidth: 4 } en una arista que también fija strokeColor pierde ese color, y Pierde el color del tipo también. Si desea una devolución de llamada y el estilo del tipo, haga lo busque dentro de la devolución de llamada, o coloque la devolución de llamada en render.defaultEdgeStyle, donde en su lugar, cede al mapa.
El renderizador del lienzo resuelve menos
renderers/canvas honra edgeStyleMap pero solo lee cuatro de los nueve EdgeStyle propiedades. El renderizador SVG, el predeterminado, los resuelve todos.
Haciendo una especie de capa
Diseñar distintos tipos es sólo la mitad. UI.filter.edgeFacets declara qué borde las dimensiones son conmutables:
UI: {
filter: {
edgeFacets: [{ key: 'kind', label: 'Relationship' }],
},
}{ key: 'kind' } es una declaración completa. Una faceta de borde tiene forma de borde valores predeterminados: una capa es un multiselect, y sus opciones se derivan del valores distintos que sus ventajas reales realmente conllevan, por lo que nunca puede ofrecer una opción eso volvería vacío.
Nada aquí se deriva automáticamente. A diferencia de facetas de nodo, que caen Volviendo a escanear sus datos, un gráfico que declara no edgeFacets se comporta exactamente como quien nunca ha oído hablar de capas. La visibilidad del borde es demasiado importante para adivina.
El panel de filtro crece en una sección Relationships: una fila por tipo, cada una con un muestra de línea y un recuento, aplicando ** a la vez**, como los campos de atributos que se encuentran arriba y la leyenda al lado. Nada en ese panel espera detrás de un botón de aplicar.
Facetas que no son capas
type acepta el vocabulario completo de facetas — text, regex, select, multiselect, numberRange, boolean - más accessor y predicate para dimensiones que no son una clave de datos simple:
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,
},
]Sólo el tipo de selección múltiple es un cambio en vivo. Todo lo demás es un control por lotes, por lo que se representa en el formulario de atributos del panel junto con las facetas del nodo, donde se aplica El botón es la opción adecuada.
Opciones
| Opción | Tipo | Predeterminado | que hace |
|---|---|---|---|
key | string | — | Filtrar identidad. setEdgeFilter(key, …) toma esto. |
label | string | embellecida key | Se usa palabra por palabra, por lo que puede provenir de una capa de traducción. |
type | FilterFacetType | 'multiselect' | Una capa es un conjunto de estilos, tanto activados como desactivados. |
options | array | (graph) => array | derivado | Resuelto contra el gráfico en vivo en cada reconstrucción. |
matchMode | FilterMatchMode | 'exact' | |
accessor | (edge) => unknown | edge.getData()[key] | Qué hace posibles las facetas calculadas. |
predicate | (edge, value) => boolean | — | Control total; gana sobre accessor / matchMode. Se ejecuta por borde por aplicación, así que manténgalo económico. |
order | number | orden de declaración | Orden de visualización en el panel. |
Alternar es una lente, no un cambio de diseño
Desactivar una capa cambia qué líneas se dibujan y nada más. Nodo posiciones, la selección y la cámara se mantienen bit a bit sin cambios, y no La simulación se reinicia.
Esto es deliberado y es lo que hacen las herramientas profesionales: vis-network lleva un por borde hidden y un por borde separado physics, Sigma's edgeReducer nunca llega al diseño, Cytoscape y KeyLines vuelven a diseñar solo cuando se les solicita. un La relación oculta es una decisión de visualización. Si ocultar una capa de correlación volvía a fluir, gráfico, no podrías usar el interruptor para leer el gráfico, que es el punto completo.
Lo único que lo cambia es la suscripción voluntaria, y en el lado del nodo: UI.filter.hideDisconnected oculta los nodos una capa hebras. Esos nodos abandonan la simulación, por lo que el gráfico se vuelve a asentar, razón por la cual es está desactivado de forma predeterminada y por qué es un filtro de nodo en lugar de algo que hace el control de capa por sí solo.
Mecánicamente, Edge creció una segunda bandera:
| Propiedad | Significado |
|---|---|
layerVisible | Si la capa de este borde está activada. Un veto sobre visible. |
visibleIgnoringLayer | ¿Qué sería visible si todas las capas estuvieran activadas: solo el punto final y los motivos de ocultación manual? |
setLayerVisible(on) | Cambia la capa, volviendo a derivar visible. Devuelve si algo cambió. |
representedEdges | Para un sustituto: las ventajas reales de las que habla. Indefinido en un límite real. |
El enlace fuerza las puertas en visibleIgnoringLayer, por lo que un borde cuya capa está apagada pasa en unir sus puntos finales. visible también está escrito mediante filtrado de puntos finales y por hideNode / showNode, razón por la cual el estado de capa vive aparte de él.
Un nodo dejado sin bordes visibles permanece visible
Ocultarlo sería una decisión de filtro nodo, y una faceta de borde nunca requiere una. Utilice el panel de filtro o queryEngine.setFilter si eso es lo que desea quiero.
Una selección vacía significa que todas las capas están eliminadas.
Para una selección múltiple de nodos, una lista vacía es como el panel escribe unset - no restricción. Un control de capa de borde escribe exactamente lo que permanece, por lo que un control de capa vaciado La lista de capas significa que todas las capas están desactivadas. No hay nada más que pueda significar, y Es por eso que una sección de borde no tiene límite de "no se puede apagar la última".
Tecleando las capas en la leyenda
Una sección leyenda que declara scope: 'edge' enumera los tipos con un línea muestra: color de trazo, guión y marcador tal como los resolvió el renderizador— sentado al lado de secciones con alcance de nodo en la misma tarjeta acoplada:
UI: {
legend: {
sections: [
{ key: 'type', title: 'Element' }, // nodes
{ key: 'kind', title: 'Relationship', scope: 'edge' }, // edges
],
},
}- Dada una declaración
edgeFacetscoincidente, la sección ** impulsa esa faceta**: la El panel y la leyenda se convierten en dos vistas de un filtro, una detrás de la otra. - Sin uno, se reserva una faceta propia y aún se filtra, por lo que se crea una leyenda. nunca meramente decorativo.
- Una sección sin
keynientriesusarender.edgeTypeAccessor, exactamente cuando una sección de nodo vuelve a caer anodeTypeAccessor. - Los conteos son de bordes real: los sustitutos de un clúster colapsado están excluidos, por lo que un El recuento nunca informa dos veces una relación.
Los colores de muestra se toman sa de lo que pintó el renderizador, por lo que un tipo renderizado en más de un color mantiene el primero y avisa. Declara entries con los tuyos color cuando los tipos no son lo que codifican los trazos.
Clústeres colapsados
Mientras un grupo está cerrado, un borde con un extremo dentro se dibuja hacia el grupo. en cambio, a cualquier profundidad. Los bordes cuyos extremos aterrizan en los mismos dos nodos en la pantalla se comparten una línea, un suplente, por lo que una línea puede hablar de varias relaciones reales de varios tipos. Los sustitutos solo se dibujan: getEdges() y la pestaña Bordes de la tabla es real bordes.
Por lo tanto, cada sustituto lleva representedEdges y sobrevive mientras cualquier de ellos pasa el filtro. Dos consecuencias que vale la pena conocer:
- Ocultar una capa oculta un sustituto solo una vez que se ocultan todas las relaciones detrás de ella. Una línea que representa tanto un
referencecomo uncorrelationpermanece mientras cualquiera está encendido. - Cada tipo de faceta llega al interior de un grupo colapsado: un
numberRangeo unpredicate, no solo una lista de tipos, porque la faceta se compara con la bordes reales en lugar de los propios datos (vacíos) del sustituto.
Un sustituto para un solo borde se parece a ese borde, con puntos, y al hacer clic en él se selecciona el borde. Un sustituto de varios es simple y al seleccionarlo se muestra cuántos bordes representa. para.
Conduciéndolo desde el código
Las facetas de los bordes están registradas en el constructor, por lo que el filtrado programático ** funciona en cada modo**: solo el panel es cromado en modo full.
graph.queryEngine.setEdgeFilter('kind', { value: ['reference'], matchMode: 'exact' })
graph.queryEngine.getHiddenEdgeCount() // 12
graph.queryEngine.removeEdgeFilter('kind') // every layer back on| Método | que hace |
|---|---|
setEdgeFilter(key, config) | Escribe un filtro de borde. |
getEdgeFilters() | Los filtros de borde activos, sin prefijo. |
removeEdgeFilter(key) | Suelte uno: ese conjunto de capas vuelve a activarse. |
getHiddenEdgeCount() | Cuántos bordes están ocultos por una capa. |
getEdgeFacetValues(key) | Los distintos valores, cada uno con un recuento y una ventaja de muestra. |
setEdgeFacets(facets) | Reemplace el conjunto declarado. |
registerEdgeFacet(facet) | Agregue uno de forma aditiva: lo que usa una sección de leyenda para reservar la suya. |
replaceFilters(ownedKeys, filters) | Reemplace sólo las llaves que posee, dejando las demás en paz. |
Los filtros de nodo y borde comparten un registro GraphFilters, con las claves de borde debajo un prefijo edge: (EDGE_FILTER_PREFIX, exportado desde GraphQueryEngine), por lo que una clave El nombre puede ser una faceta de nodo y una faceta de borde a la vez. Cada método anterior oculta el prefijo; solo lo cumples si lees el registro sin procesar.
renderer.getEdgeStyle(edge) es público y devuelve el estilo real del renderizador. resuelto: la misma llamada en la que se basan las muestras de la leyenda y la forma de afirmar en una prueba que lo que declaraste es lo que está pintado.
Ver también
- Tarjeta de galería de capas de borde: los tres superficies en un lienzo
- Opciones de renderizado: la mitad del nodo del par de acceso/mapa
- Filtros: facetas de nodo y reutilización de facetas de borde de vocabulario
- Leyenda: secciones y lo que una muestra puede y no puede saber