Camadas de borda
Um gráfico cujas relações são todas iguais deixa de ser legível no momento em que carrega mais de um tipo de relação. Camadas de borda são as três coisas que você precisa para corrigir isso e devem ser usadas juntas:
- Nomeie o tipo —
render.edgeTypeAccessor. - Estilize-o à parte —
render.edgeStyleMap. - Desligar —
UI.filter.edgeFacets, apareceu como alternância ao vivo no painel de filtro e, opcionalmente, como uma seção de legenda.
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' }] },
},
}Desativar uma camada nunca move o gráfico
Esta é a propriedade em torno da qual todo o recurso é construído - consulte Alternar é uma lente. Layout, seleção e câmera voltam bit a bit idênticos, a menos que você opte por ocultar nós não conectados.
Nomeando e estilizando um tipo
edgeTypeAccessor e edgeStyleMap espelham nodeTypeAccessor / nodeStyleMap exatamente: o acessador retorna uma string (ou undefined), e o mapa transforma essa string em um Partial<EdgeStyle> mesclado sobre o estilo de borda padrão.
render: {
edgeTypeAccessor: (edge) => edge.getData()?.kind,
edgeStyleMap: {
reference: { strokeColor: '#428bca', strokeWidth: 2 },
contains: { strokeColor: '#5cb85c', markerEnd: 'diamond' },
},
}Cada propriedade EdgeStyle é um jogo justo - strokeColor, strokeWidth, opacity, curveStyle, dashed, animateDash, markerEnd, markerStart, rotateLabel. Uma aresta dashed anima seu traço por padrão; defina animateDash: false para um tipo que deve ser lido como um contexto de fundo calmo.
Uma aresta sem tipo, ou um tipo que o mapa não menciona, mantém o estilo de aresta padrão. Nada avisa: um tipo sem estilo é uma escolha legítima.
Precedência
Na mesma ordem dos nós, as vitórias mais estreitas:
| Prioridade | Onde |
|---|---|
| 1 (vitórias) | o próprio style.styleCb da borda — veja o aviso abaixo |
| 2 | as próprias propriedades estáticas style da borda |
| 3 | render.edgeStyleMap[kind] |
| 4 | render.defaultEdgeStyle.styleCb |
| 5 | render.defaultEdgeStyle literais |
As duas funções styleCb não são a mesma coisa e vale a pena mantê-las corretas. No estilo own de um edge é um override que vence imediatamente; em render.defaultEdgeStyle é a forma computada * do slot padrão*, preenchendo apenas o que nada mais restrito definiu - incluindo o que um styleCb por aresta deixou de fora. Ordenação de especificidade, não callback-beats-static.
O próprio styleCb de uma vantagem substitui todo o seu nível
Quando o próprio estilo de uma borda declara um styleCb, seu valor de retorno é a fonte only naquela camada: as próprias propriedades estáticas da borda * e* edgeStyleMap são ignoradas e apenas defaultEdgeStyle preenche as lacunas. Portanto, um styleCb retornando { strokeWidth: 4 } em uma aresta que também define strokeColor perde aquela cor e perde a cor do tipo também. Se você quiser um retorno de chamada * e * o estilo do tipo, faça a pesquisa dentro do retorno de chamada ou coloque o retorno de chamada em render.defaultEdgeStyle, onde ele cede ao mapa.
O renderizador de tela resolve menos
renderers/canvas honra edgeStyleMap mas lê apenas quatro das nove propriedades EdgeStyle. O renderizador SVG — o padrão — resolve todos eles.
Fazendo uma espécie de camada
Estilizar os tipos separados é apenas metade disso. UI.filter.edgeFacets declara quais dimensões de borda são switchable:
UI: {
filter: {
edgeFacets: [{ key: 'kind', label: 'Relationship' }],
},
}{ key: 'kind' } é uma declaração completa. Uma faceta de aresta tem padrões de formato de aresta: uma camada é multiselect e suas opções são derivadas dos valores distintos que suas arestas reais realmente carregam, portanto, ela nunca pode oferecer uma escolha que voltaria vazia.
Nada aqui é derivado automaticamente. Ao contrário de facetas de nó, que recorrem à varredura de seus dados, um gráfico que declara não edgeFacets se comporta exatamente como aquele que nunca ouviu falar de camadas. A visibilidade da borda é muito importante para ser adivinhada.
O painel de filtro cria uma seção Relationships: uma linha por tipo, cada uma com uma amostra de linha e uma contagem, aplicando de uma só vez — como os campos de atributos acima e a legenda ao lado. Nada nesse painel fica atrás de um botão de aplicação.
Facetas que não são camadas
type aceita o vocabulário de facetas completo — text, regex, select, multiselect, numberRange, boolean — mais accessor e predicate para dimensões que não são uma chave de dados simples:
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,
},
]Somente o tipo de seleção múltipla é uma alternância ativa. Todo o resto é um controle em lote, portanto ele é renderizado no formato de atributo do painel junto com as facetas do nó, onde um botão aplicar é a capacidade correta.
Opções
| Opção | Tipo | Padrão | O que isso faz |
|---|---|---|---|
key | string | — | Filtrar identidade. setEdgeFilter(key, …) pega isso. |
label | string | embelezado key | Usado literalmente, portanto pode vir de uma camada de tradução. |
type | FilterFacetType | 'multiselect' | Uma camada é um conjunto de tipos, cada um ativado ou desativado. |
options | array | (graph) => array | derivado | Resolvido em relação ao gráfico ao vivo em cada reconstrução. |
matchMode | FilterMatchMode | 'exact' | |
accessor | (edge) => unknown | edge.getData()[key] | O que torna possíveis as facetas computadas. |
predicate | (edge, value) => boolean | — | Controle total; vence accessor / matchMode. Executa por borda por aplicativo, portanto, mantenha-o barato. |
order | number | ordem de declaração | Ordem de exibição no painel. |
Alternar é uma lente, não uma mudança de layout
Desativar uma camada altera quais linhas são desenhadas e nada mais. As posições dos nós, a seleção e a câmera permanecem inalteradas bit a bit e nenhuma simulação é reiniciada.
Isso é deliberado e é o que as ferramentas profissionais fazem: vis-network carrega um hidden * e * por borda separado physics, o edgeReducer da Sigma nunca atinge o layout, o Cytoscape e o KeyLines re-layout apenas quando solicitado. Uma relação oculta é uma decisão de exibição. Se ocultar uma camada de correlação refluísse no gráfico, você não poderia usar a alternância para ler o gráfico, que é o ponto inteiro.
A única coisa que o dobra é o opt-in, e no lado do nó: UI.filter.hideDisconnected esconde os nós em uma camada de fios. Esses nós saem da simulação, então o gráfico é reinstalado – e é por isso que ele está desativado por padrão e é por isso que é um filtro de nó em vez de algo que o controle da camada faz por conta própria.
Mecanicamente, Edge cresceu uma segunda bandeira:
| Propriedade | Significado |
|---|---|
layerVisible | Se a camada desta borda está ativada. Um veto sobre visible. |
visibleIgnoringLayer | O que seria visible se todas as camadas estivessem ativadas: apenas o ponto final e os motivos de ocultação manual. |
setLayerVisible(on) | Troque a camada, derivando novamente visible. Retorna se algo mudou. |
representedEdges | Para um substituto: as verdadeiras vantagens que ele representa. Indefinido em uma borda real. |
O link força as portas em visibleIgnoringLayer, então uma aresta cuja camada está desativada continua unindo suas extremidades. visible também é escrito pela filtragem de endpoint e por hideNode / showNode, e é por isso que o estado da camada vive separado dele.
Um nó deixado sem arestas visíveis permanece visível
Ocultá-lo seria uma decisão de filtro node, e uma faceta de borda nunca toma uma. Use o painel de filtro ou queryEngine.setFilter se for isso que você deseja.
Uma escolha vazia significa todas as camadas removidas
Para uma seleção múltipla de nó, uma lista vazia é como o painel soletra unset - sem restrição. Um controle de camada de borda grava exatamente o que permanece ativado, portanto, uma lista de camadas vazia significa que todas as camadas estão desativadas. Não há mais nada que isso possa significar, e é por isso que uma seção de borda não tem limite "não é possível desligar a última".
Digitando as camadas na legenda
Uma seção legend declarando scope: 'edge' lista os tipos com uma amostra line - cor do traço, traço e marcador conforme o renderizador os resolveu - ao lado das seções com escopo de nó no mesmo cartão encaixado:
UI: {
legend: {
sections: [
{ key: 'type', title: 'Element' }, // nodes
{ key: 'kind', title: 'Relationship', scope: 'edge' }, // edges
],
},
}- Dada uma declaração
edgeFacetscorrespondente, a seção direciona essa faceta — o painel e a legenda tornam-se duas visualizações de um filtro, uma seguindo a outra. - Sem ela, ela reserva uma faceta própria e ainda filtra, portanto uma legenda nunca é meramente decorativa.
- Uma seção sem
keynementriesusarender.edgeTypeAccessor, exatamente como uma seção de nó volta paranodeTypeAccessor. - As contagens são de arestas real: os substitutos de um cluster recolhido são excluídos, portanto, uma contagem nunca relata duas vezes uma relação.
As cores da amostra são amostradas a partir do que o renderizador pintou, portanto, um tipo renderizado em mais de uma cor mantém a primeira e avisa. Declare entries com seu próprio color quando os tipos não forem os codificados pelos traços.
Clusters recolhidos
Enquanto um cluster está fechado, uma aresta com uma extremidade dentro dela é desenhada para o cluster, em qualquer profundidade. Arestas cujas extremidades pousam nos mesmos dois nós na tela compartilham uma linha, um stand-in, então uma linha pode falar por várias relações reais de vários tipos. Os substitutos estão desenhando apenas: getEdges() e a guia Arestas da tabela lista as arestas reais.
Cada substituto, portanto, carrega representedEdges e sobrevive enquanto qualquer deles passa no filtro. Duas consequências que vale a pena conhecer:
- Ocultar uma camada oculta um substituto apenas quando todas as relações por trás dela estiverem ocultas. Uma linha que representa
referenceecorrelationpermanece enquanto qualquer uma delas está ativada. - Cada tipo de faceta chega a um cluster recolhido - um
numberRangeou umpredicate, não apenas uma lista de tipos - porque a faceta é comparada com as arestas reais em vez dos próprios dados (vazios) do substituto.
Um substituto para uma única aresta se parece com aquela aresta, pontilhada, e clicar nele seleciona a aresta. Um substituto para vários é simples e selecioná-lo mostra quantas arestas ele representa.
Conduzindo a partir do código
As facetas da borda são registradas no construtor, portanto, a filtragem programática ** funciona em todos os modos** - apenas o painel é cromado no modo full.
graph.queryEngine.setEdgeFilter('kind', { value: ['reference'], matchMode: 'exact' })
graph.queryEngine.getHiddenEdgeCount() // 12
graph.queryEngine.removeEdgeFilter('kind') // every layer back on| Método | O que isso faz |
|---|---|
setEdgeFilter(key, config) | Escreva um filtro de borda. |
getEdgeFilters() | Os filtros de borda ativos, sem prefixo. |
removeEdgeFilter(key) | Solte um - esse conjunto de camadas volta. |
getHiddenEdgeCount() | Quantas arestas estão ocultas por uma camada. |
getEdgeFacetValues(key) | Os valores distintos, cada um com uma contagem e uma borda de amostra. |
setEdgeFacets(facets) | Substitua o conjunto declarado. |
registerEdgeFacet(facet) | Adicione um aditivo – o que uma seção de legenda usa para reservar a sua própria. |
replaceFilters(ownedKeys, filters) | Substitua apenas as chaves que você possui, deixando as outras em paz. |
Os filtros de nó e borda compartilham um registro GraphFilters, com chaves de borda transportadas sob um prefixo edge: (EDGE_FILTER_PREFIX, exportado de GraphQueryEngine) para que um nome de chave possa ser uma faceta de nó e uma faceta de borda ao mesmo tempo. Cada método acima oculta o prefixo; você só o encontrará se ler o registro bruto.
renderer.getEdgeStyle(edge) é público, retornando o estilo que o renderizador realmente resolveu — a mesma chamada na qual as amostras da legenda são construídas e a maneira de afirmar em um teste que o que você declarou é o que está pintado.
Veja também
- Cartão de galeria de camadas de borda — todas as três superfícies em uma tela
- Opções de renderização — a metade do nó do par acessador/mapa
- Filters — facetas do nó e reutilização das facetas da borda do vocabulário
- Legend — seções e o que uma amostra pode ou não saber