Naar inhoud

Randlagen ​

Een grafiek waarvan de relaties allemaal op elkaar lijken, is niet meer leesbaar op het moment dat hij draagt meer dan één soort relatie. Randlagen zijn de drie dingen die u nodig heeft repareer dat, en ze zijn bedoeld om samen te worden gebruikt:

  1. Noem het soort — render.edgeTypeAccessor.
  2. Maak het apart — render.edgeStyleMap.
  3. Schakel het uit — UI.filter.edgeFacets, weergegeven als live-schakelaars in de filterpaneel en optioneel als legendesectie.
ts
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' }] },
    },
}

Als u een laag uitschakelt, wordt de grafiek nooit verplaatst

Dit is de eigenschap waar het hele gebouw omheen is gebouwd – zie Toggle is een lens. Lay-out, selectie en camera komen bit-voor-bit terug identiek, tenzij u zich hiervoor aanmeldt niet-verbonden knooppunten verbergen.

Een soort benoemen en stylen ​

edgeTypeAccessor en edgeStyleMap spiegel nodeTypeAccessor / nodeStyleMap precies: de accessor retourneert een string (of undefined), en de kaart verandert die string in een Partial<EdgeStyle> samengevoegd over de standaardrandstijl.

ts
render: {
    edgeTypeAccessor: (edge) => edge.getData()?.kind,
    edgeStyleMap: {
        reference: { strokeColor: '#428bca', strokeWidth: 2 },
        contains:  { strokeColor: '#5cb85c', markerEnd: 'diamond' },
    },
}

Elke eigenschap EdgeStyle is eerlijk spel — strokeColor, strokeWidth, opacity, curveStyle, dashed, animateDash, markerEnd, markerStart, rotateLabel. Een rand van dashed animeert standaard zijn streepje; stel animateDash: false in voor een soort dat zou moeten lezen als een rustige achtergrondcontext.

Een rand zonder soort, of een soort die niet op de kaart wordt vermeld, behoudt de standaardrand stijl. Niets waarschuwt: een ongestylede soort is een legitieme keuze.

Voorrang ​

Dezelfde volgorde als knooppunten, smalste overwinningen:

PrioriteitWaar
1 (overwinningen)de eigen style.styleCb van de rand — zie de waarschuwing hieronder
2de eigen statische style-eigenschappen van de rand
3render.edgeStyleMap[kind]
4render.defaultEdgeStyle.styleCb
5render.defaultEdgeStyle letterlijke waarden

De twee styleCb-rollen zijn niet hetzelfde en het is de moeite waard om ze te behouden recht. Bij de eigen-stijl van een edge is het een override die direct wint; op render.defaultEdgeStyle het is de berekende vorm van het standaardslot, gevuld alleen wat niets smaller is ingesteld - inclusief wat een per-rand styleCb is weggelaten. Specificiteitsvolgorde, niet callback-beats-statisch.

De eigen styleCb van een rand vervangt zijn hele niveau

Wanneer de eigen stijl van een rand een styleCb declareert, is de retourwaarde only bron op dat niveau: de eigen statische eigenschappen van de rand en edgeStyleMap zijn beide overgeslagen, en alleen defaultEdgeStyle vult de gaten. Dus een styleCb retour { strokeWidth: 4 } op een rand die ook ondergaat, strokeColor verliest die kleur, en verliest ook de kleur van het soort. Als je teruggebeld wilt worden met de stijl en van het soort, doe dan de zoek binnen de callback, of zet de callback op render.defaultEdgeStyle, waar het geeft in plaats daarvan toe aan de kaart.

De canvasrenderer lost minder op

renderers/canvas eert edgeStyleMap maar leest slechts vier van de negen EdgeStyle eigenschappen. De renderer SVG – de standaardinstelling – lost ze allemaal op.

Van een soort een laag maken ​

Het onderscheiden van soorten is slechts de helft. UI.filter.edgeFacets geeft aan welke rand afmetingen zijn schakelbaar:

ts
UI: {
    filter: {
        edgeFacets: [{ key: 'kind', label: 'Relationship' }],
    },
}

{ key: 'kind' } is een volledige declaratie. Een randfacet is randvormig standaardwaarden: een laag is een multiselect, en de opties ervan zijn afgeleid van de verschillende waarden die je echte randen feitelijk met zich meedragen, zodat het nooit een keuze kan bieden dat zou leeg terugkomen.

Niets hier wordt ooit automatisch afgeleid. In tegenstelling tot knooppuntfacetten, die vallen terug naar het scannen van uw gegevens: een grafiek die geen edgeFacets aangeeft, gedraagt zich precies zoals iemand die nog nooit van lagen heeft gehoord. Randzichtbaarheid is te belangrijk voor raad eens.

Het filterpaneel groeit met een sectie Relationships: één rij per soort, elk met een lijnstaal en een telling, waarbij in één keer wordt toegepast — zoals de attribuutvelden erboven en de legende ernaast. Niets in dat paneel wacht achter een sollicitatieknop.

Facetten die geen lagen zijn ​

type accepteert de volledige facetvocabulaire — text, regex, select, multiselect, numberRange, boolean — plus accessor en predicate voor dimensies die geen gewone gegevenssleutel zijn:

ts
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,
    },
]

Alleen de multiselect-soort is een live-schakelaar. Al het andere is een batchcontrole, dus het wordt weergegeven in de attribuutvorm van het paneel naast de knooppuntfacetten, waar een van toepassing is knop is de juiste prijs.

Opties ​

OptieTypStandaardWat het doet
keystring—Filter identiteit. setEdgeFilter(key, …) neemt dit.
labelstringmooier keyLetterlijk gebruikt, zodat het uit een vertaallaag kan komen.
typeFilterFacetType'multiselect'Een laag is een reeks soorten, elk aan of uit.
optionsarray | (graph) => arrayafgeleidOpgelost tegen de livegrafiek bij elke herbouw.
matchModeFilterMatchMode'exact'
accessor(edge) => unknownedge.getData()[key]Wat computerfacetten mogelijk maakt.
predicate(edge, value) => boolean—Volledige controle; wint van accessor / matchMode. Draait per rand per toepassing, dus houd het goedkoop.
ordernumberdeclaratie opdrachtWeergavevolgorde in het paneel.

Wisselen is een lens, geen wijziging van de lay-out ​

Als u een laag uitschakelt, verandert welke lijnen worden getekend en niets anders. Knooppunt posities, de selectie en de camera zijn bit voor bit ongewijzigd, en nee simulatie wordt opnieuw gestart.

Dat is doelbewust, en het is wat de professionele tools doen: vis-netwerk draagt een per-rand hidden en een aparte per-rand physics, Sigma's edgeReducer bereikt nooit de lay-out, Cytoscape en KeyLines re-layout alleen wanneer daarom wordt gevraagd. EEN verborgen relatie is een weergavebeslissing. Als u een correlatielaag verbergt, wordt de grafiek, kunt u de schakelaar niet gebruiken om de grafiek, die het hele punt is, te lezen.

Het enige dat het verbuigt is opt-in, en aan de knooppuntzijde: UI.filter.hideDisconnected verbergt de knooppunten in een laag strengen. Die knooppunten verlaten de simulatie, dus de grafiek wordt opnieuw ingesteld - en dat is de reden waarom dat zo is standaard uitgeschakeld, en waarom het een knooppuntfilter is in plaats van iets dat de laagcontrole doet op zichzelf.

Mechanisch gezien groeide Edge een tweede vlag:

EigendomBetekenis
layerVisibleOf de laag van deze rand is ingeschakeld. Een veto over visible.
visibleIgnoringLayerWat visible zou zijn als elke laag aan zou staan: alleen al het eindpunt en de redenen voor handmatig verbergen.
setLayerVisible(on)Wissel van laag en herleid visible. Geeft terug of er iets is veranderd.
representedEdgesVoor een stand-in: de echte randen waar het voor spreekt. Ongedefinieerd op een echte rand.

De verbindingskracht gaat naar visibleIgnoringLayer, dus een rand waarvan de laag uit is, gaat over het samenbrengen van de eindpunten. visible wordt ook geschreven door eindpuntfiltering en door hideNode / showNode, wat de reden is dat de laagstatus er los van leeft.

Een knooppunt zonder zichtbare randen blijft zichtbaar ​

Het verbergen ervan zou een node-filterbeslissing zijn, en een randfacet neemt er nooit één. Gebruik het filterpaneel of queryEngine.setFilter als u dat wilt willen.

Een lege keuze betekent dat elke laag uitgeschakeld is ​

Voor een multiselect-knooppunt is een lege lijst de manier waarop het paneel unset spelt — nee beperking. Een edge-laagbesturing schrijft precies wat er blijft staan, dus een geleegd lagenlijst betekent dat elke laag is uitgeschakeld. Er is niets anders dat het zou kunnen betekenen, en dat is het ook Daarom heeft een randsectie geen limiet "kan de laatste niet uitschakelen".

De lagen in de legenda intoetsen ​

Een sectie legend waarin scope: 'edge' wordt aangegeven, vermeldt de soorten met een line staal — lijnkleur, streepje en markering zoals de renderer ze heeft opgelost — naast secties met een knooppuntbereik op dezelfde gekoppelde kaart:

ts
UI: {
    legend: {
        sections: [
            { key: 'type', title: 'Element' },                     // nodes
            { key: 'kind', title: 'Relationship', scope: 'edge' },  // edges
        ],
    },
}
  • Gegeven een overeenkomende edgeFacets-declaratie, stuurt de sectie ** dat facet** aan: de paneel en de legenda worden twee weergaven van één filter, die elkaar opvolgen.
  • Zonder één behoudt het een eigen facet en filtert het nog steeds, zo is een legende nooit louter decoratief.
  • Een sectie zonder key noch entries gebruikt precies render.edgeTypeAccessor als een knooppuntsectie terugvalt naar nodeTypeAccessor.
  • Tellingen zijn van echte randen: de stand-ins van een samengevouwen cluster zijn uitgesloten, dus een count rapporteert nooit dubbel een relatie.

Swatchkleuren zijn sampled van wat de renderer heeft geschilderd, dus een soort weergegeven in meer dan één kleur behoudt de eerste en waarschuwt. Verklaar entries met uw eigen verklaring color wanneer de soorten niet zijn wat de streken coderen.

Samengevouwen clusters ​

Terwijl een cluster gesloten is, wordt een rand met een uiteinde erin naar de cluster getrokken in plaats daarvan, op elke diepte. Randen waarvan de uiteinden op dezelfde twee knooppunten op het scherm terechtkomen, worden gedeeld één regel, een stand-in, dus één regel kan spreken voor meerdere reële relaties van meerdere soorten. Stand-ins tekenen alleen: getEdges() en de tabelranden op het tabblad Randen zijn echt randen.

Elke stand-in draagt daarom representedEdges en overleeft terwijl any daarvan passeert het filter. Twee gevolgen die de moeite waard zijn om te weten:

  • Het verbergen van een laag verbergt een stand-in slechts zodra elke relatie erachter verborgen is. Een lijn die zowel voor een reference als voor een correlation staat, blijft staan terwijl een van beide staat aan.
  • Elk facettype reikt tot binnen een samengevouwen cluster: een numberRange of a predicate, niet zomaar een lijst met soorten — omdat het facet wordt vergeleken met de echte randen in plaats van de eigen (lege) gegevens van de stand-in.

Een stand-in voor een enkele rand ziet eruit als die rand, gestippeld, en als u erop klikt, wordt de rand. Een stand-in voor meerdere is duidelijk, en als u deze selecteert, ziet u hoeveel randen deze heeft voor.

Rijden vanuit code ​

Randfacetten worden geregistreerd in de constructor, dus programmatisch filteren werkt elke modus — alleen het paneel is chroom in de full-modus.

ts
graph.queryEngine.setEdgeFilter('kind', { value: ['reference'], matchMode: 'exact' })
graph.queryEngine.getHiddenEdgeCount()      // 12
graph.queryEngine.removeEdgeFilter('kind')  // every layer back on
MethodeWat het doet
setEdgeFilter(key, config)Schrijf één randfilter.
getEdgeFilters()De actieve randfilters, zonder prefix.
removeEdgeFilter(key)Laat er één vallen - die lagenset wordt weer ingeschakeld.
getHiddenEdgeCount()Hoeveel randen zijn verborgen door een laag.
getEdgeFacetValues(key)De verschillende waarden, elk met een telling en een monsterrand.
setEdgeFacets(facets)Vervang de aangegeven set.
registerEdgeFacet(facet)Voeg er één toe: wat een legendasectie gebruikt om zijn eigen sectie te reserveren.
replaceFilters(ownedKeys, filters)Vervang alleen de sleutels die u bezit, en laat anderen met rust.

Knooppunt- en randfilters delen één GraphFilters record, met daaronder de randsleutels een voorvoegsel edge: (EDGE_FILTER_PREFIX, geëxporteerd vanuit GraphQueryEngine) dus een sleutel naam kan tegelijkertijd een knooppuntfacet en een randfacet zijn. Elke bovenstaande methode verbergt de voorvoegsel; je ontmoet het alleen als je het onbewerkte record leest.

renderer.getEdgeStyle(edge) is openbaar en geeft de stijl terug die de renderer daadwerkelijk gebruikt opgelost – dezelfde oproep waarop de swatches van de legende zijn gebouwd, en de manier om te beweren in een test dat wat u verklaarde, is wat er is geschilderd.

Zie ook ​

  • Galeriekaart randlagen — alle drie oppervlakken op één canvas
  • Weergaveopties — de knooppunthelft van het accessor/kaart-paar
  • Filters — knooppuntfacetten en hergebruik van de woordenschatrandfacetten
  • Legend — secties, en wat een staal wel en niet kan weten