Opciones de renderizado
Pivotick le permite personalizar cómo se representan los nodos, bordes y etiquetas a través de la opción render.
advertencia
Todos los estilos definidos aquí se aplican solo cuando render.type se establece en svg.
| Opción | Tipo | Predeterminado | Descripción |
|---|---|---|---|
type | 'svg' | 'canvas' | 'svg' | El método de renderizado. 'svg' usa SVG elementos, 'canvas' usa el lienzo HTML (experimental, no implementado completamente). |
renderNode | (node: Node) => HTMLElement | string | void | undefined | Representador personalizado para nodos. |
renderLabel | (edge: Edge) => HTMLElement | string | void | undefined | Representador personalizado para etiquetas de borde. |
defaultNodeStyle | NodeStyle | defaultNodeStyle | Estilo predeterminado aplicado a todos los nodos. |
defaultEdgeStyle | EdgeStyle | defaultEdgeStyle | Estilo predeterminado aplicado a todos los bordes. |
defaultLabelStyle | LabelStyle | defaultLabelStyle | Estilo predeterminado aplicado a todas las etiquetas de borde. |
markerStyleMap | Record<string, MarkerStyle> | defaultMarkerStyle | Estilos personalizados para marcadores de borde ('arrow', 'diamond', etc.). Ver MarkerStyle |
nodeTypeAccessor | (node: Node) => string | undefined | undefined | Función para acceder al tipo de nodo, utilizada con nodeStyleMap. |
nodeStyleMap | Record<string, NodeStyle> | {} | Asigna tipos de nodos (desde nodeTypeAccessor) a estilos. |
edgeTypeAccessor | (edge: Edge) => string | undefined | undefined | El tipo de un borde, usado con edgeStyleMap y como clave de capa. |
edgeStyleMap | Record<string, Partial<EdgeStyle>> | undefined | Asigna tipos de bordes (de edgeTypeAccessor) a estilos. Consulte Capas de borde. |
minZoom | number | 0.1 | Nivel mínimo de zoom. |
maxZoom | number | 10 | Nivel máximo de zoom. |
minFitScale | number | undefined | El zoom más bajo al que llega un ajuste. Se abre un gráfico demasiado grande para caber con este zoom, centrado en fitAnchor, y el minimapa muestra el resto. |
fitAnchor | string | undefined | Id. del nodo en el que se centra un ajuste mantenido en minFitScale. La vista se detiene en los bordes del gráfico, por lo que un ancla de un lado permanece cerca de ese lado. |
zoomEnabled | boolean | true | Habilite el zoom. false también toma los botones de zoom del riel de la ventana gráfica, manteniéndose en forma y centrado. |
selectionBox | SelectionBox | undefined | Selección de región: enabled: false suelta el marco de arrastre y la herramienta Seleccionar ▸ Lazo. |
enableNodeExpansion | boolean | true | Expandiendo un grupo: false toma el galón, el atajo Enter y el contorno discontinuo colapsado con él. Un niño seleccionado todavía enciende su grupo cerrado. |
Tipo de renderizado
Consejo
Pivotick le brinda un control flexible sobre la renderización, desde valores predeterminados simples hasta una renderización totalmente personalizada. Aquí hay un resumen rápido:
renderNodeyrenderLabelle permiten personalizar completamente cómo se dibujan los nodos y las etiquetas (puede devolver HTML o texto).defaultNodeStyle.html(por nodo o por tipo) es la misma trampilla de escape dentro de la cadena de estilo; consulte HTML nodos.nodeTypeAccessor+nodeStyleMappermite un estilo dinámico basado en el tipo de cada elemento.defaultNodeStyle,defaultEdgeStyleydefaultLabelStyledefinen la apariencia base de todos los elementos.edgeTypeAccessor+edgeStyleMapson las contrapartes de los bordes y se doblan como la tecla mediante la cual se desactiva una capa de relación; consulte Capas de borde.
Tu tarjeta está medida, tenga la forma que tenga.
Pivotick mide lo que vuelves a dimensionar su <foreignObject> y para alimentar la fuerza Radio de colisión del diseño. La tarjeta se mide dentro de una caja retráctil del propia de la biblioteca, por lo que no tiene que hacer que su raíz tenga un tamaño propio: width: 100% en ella se resuelve contra su propio contenido en lugar de contra el marcador de posición.
Los siguientes tres ejemplos de representación utilizan los siguientes datos:
const data = {
nodes: [
{ id: 1, data: { label: 'A', type: 'hub' } },
{ id: 2, data: { label: 'B', type: 'spoke' } }
],
edges: [{ from: 1, to: 2 }]
}const options = {
render: {
defaultNodeStyle: {
shape: 'circle',
color: '#007acc',
size: 12,
strokeColor: '#fff',
strokeWidth: 2,
fontFamily: 'system-ui',
textColor: '#fff'
},
defaultEdgeStyle: {
markerStart: (edge: Edge) => edge.getData().mstart,
markerEnd: 'arrow',
curveStyle: 'straight',
},
}
}const options = {
render: {
nodeTypeAccessor: (node) => node.getData()?.type,
nodeStyleMap: {
'hub': {
shape: 'hexagon',
color: '#f90',
size: 25,
text: (node) => node.getData()?.label
},
'spoke': {
shape: 'triangle',
color: '#09f'
}
},
},
UI: {
mode: 'static'
}
}const options = {
render: {
renderNode: (node: Node): HTMLElement | string | void => {
const size = 12
const color = '#09f'
const style = [
'display: block',
`width: ${size}px`,
`height: ${size}px`,
`background-color: ${color}`,
'border: 2px solid #fff',
'border-radius: 50%',
'opacity: 1',
].join(';')
return `<span style="${style}"></span>`
}
}
}Ejemplo de renderizado de Map-Accessor
HTML nodos
Cuando ninguna combinación de shape, color, icon y text sea suficiente, entregue al renderizador algunos marcado. Hay dos formas de entrar, y la diferencia es solo donde se declaran:
| Declarado el | Alcanza | |
|---|---|---|
NodeStyle.html | defaultNodeStyle, nodeStyleMap[type], estilo propio de un nodo, un retorno styleCb | un tipo o un nodo |
render.renderNode | las opciones del renderizador | cada nodo, por delante de la cadena de estilo |
html es el que hay que alcanzar primero: es un canal de estilo ordinario, por lo que se resuelve a través de la misma cadena de precedencia que color o shape, y se puede entregar una tarjeta a uno especie de nodo mientras el resto mantiene sus formas.
const options = {
render: {
nodeTypeAccessor: (node) => node.getData()?.kind,
nodeStyleMap: {
// A card, and nothing else: `shape: 'none'` is what makes it the whole node.
service: {
shape: 'none',
html: (node) => {
const card = document.createElement('div')
card.className = 'my-service-card'
card.textContent = node.getData()?.name
return card
},
},
// Same graph, ordinary shapes.
host: { shape: 'circle', size: 18, color: '#0891b2' },
},
},
}shape: 'none'
Sin él, la forma ** todavía está dibujada detrás de tu tarjeta**, y size es la más pequeña se permite que el nodo sea, que es lo que desea para una tarjeta colocada en un disco de color, y No es lo que quieres para una tarjeta que es el nodo. shape: 'none' no dibuja ninguna forma y las manos En su lugar, el radio de colisión del nodo y el borde se anclan a la tarjeta.
Es un valor de forma como cualquier otro, por lo que se compone: un nodo de sólo etiqueta es shape: 'none' con un text y sin tarjeta, y un nodo de solo icono es shape: 'none' con un iconClass. Un nodo informe y sin ningún contenido es invisible, pero sigue ahí, aún se puede arrastrar y seleccionar sobre 2 × size.
Lo que una tarjeta not apaga
text es un canal separado, por lo que se dibujan juntas una tarjeta y una etiqueta de nodo. si tu tarjeta lleva su propio título, establecido text: '': un valor heredado no se puede borrar con undefined, que se ajusta a lo que dice el mapa de estilo.
Dimensionamiento
Se mide su tarjeta y el nodo crece hacia ella, por lo que nunca se recorta, la colisión fuerza los espacios de las cartas reales, y los bordes caen en el borde de la carta en lugar de en un círculo a su alrededor. No tienes que hacer nada para que eso funcione: devolver un width: 100% root está bien, porque la medición se realiza dentro de una caja que se contrae para ajustar.
Dos consecuencias que vale la pena conocer:
- La medición es asincrónica (no se puede medir una tarjeta antes de que esté en pantalla), por lo que el radio de un nodo tiene el estilo
sizepara el primer cuadro o dos y luego se convierte en el la de la tarjeta. El diseño se empuja una vez cuando aterriza. - Una tarjeta se mide una vez, en el render. Si su contenido luego cambia de tamaño por sí solo, Vuelva a renderizar el nodo para volver a medirlo.
Cardando solo algunos nodos
Ambas devoluciones de llamada pueden devolver nada para un nodo, lo que devuelve ese nodo al cadena de estilo: forma, entrada del mapa de estilo, íconos y etiqueta como de costumbre. Así que una única global renderNode puede cardar los nodos que lo merecen:
renderNode: (node) => node.getData()?.featured ? buildCard(node) : undefinedSolo marcado confiable
Todo lo que devuelva se inserta tal cual. Constrúyalo con textContent, o escápelo, no lo hagas. interpolar datos de nodo en una cadena de marcado. Consulte la guía de seguridad.
Etiquetas de nodo completo
Una etiqueta de nodo más larga que la habitación que tiene se acorta con puntos suspensivos en el medio (Supe…abel). En su lugar, configure textTruncate: false para dibujarlo completo; de forma predeterminada, por tipo de nodo, o por nodo:
const options = {
render: {
defaultNodeStyle: { textTruncate: false },
},
}Entre los dos, textMaxWidth tapa la etiqueta con el ancho que usted elija, en unidades de gráfico (CSS píxeles con zoom 1), en lugar del espacio que le da el nodo. Se dibuja una etiqueta que encaja en su totalidad, y uno más largo se acorta con una elipsis media a ese ancho:
const options = {
render: {
defaultNodeStyle: { textTruncate: true, textMaxWidth: 160 },
},
}Tamaño de fuente de la etiqueta
La etiqueta de un nodo se dibuja en max(12, size × 0.45) de forma predeterminada, por lo que crece con el nodo. Cuando un nodo es grande por lo que dibuja en lugar de por lo mucho que importa, como una imagen miniatura, establezca textFontSize (unidades de gráfico) para mantener su etiqueta alineada con sus vecinas:
const options = {
render: {
nodeStyleMap: {
image: { size: 80, imagePath: (node) => node.getData()?.url, textFontSize: 12 },
},
},
}La etiqueta todavía se encuentra justo por encima del nodo, el presupuesto incorporado todavía toma su ancho de el nodo (para que una fuente más pequeña se ajuste a más caracteres) y el puerta de zoom lo juzga según el tamaño que establezca.
El límite escala con el zoom como el resto del nodo, y puede ser una función del nodo. Se ignora cuando textTruncate es false.
Una etiqueta completa o tapada generalmente sobrepasa la forma del nodo, por lo que se dibuja en el mismo píldora temática como etiqueta flotante para permanecer legible sobre el lienzo. Combínalo con textVerticalShift: 1 (o textHorizontalShift) para borrar toda la etiqueta del nodo. Las etiquetas de borde nunca se truncan.
text es una etiqueta en un nodo, no un sustituto de uno. Un nodo que es su texto debería ser dibujado como el nodo, a través de html, renderNode o un tier: esos son los dibujos del nodo y el zoom los mantiene independientemente minLabelFontSize hace con las etiquetas.
Insignias de nodo
Cuando un gráfico es útil, color, shape, size y iconClass suelen ser todos llevando algo. badges es un canal en sí mismo: pequeños indicadores fijados al borde del nodo, sin gastar ninguno de los demás:
const options = {
render: {
defaultNodeStyle: {
badges: (node) => {
const { notes, disputed } = node.getData()
return [
notes && { text: String(notes), color: '#2563eb', title: `${notes} notes` },
disputed && { iconClass: 'fa fa-exclamation', color: '#b94a48', title: 'Disputed' },
].filter(Boolean)
},
},
},
}Dar una insignia text (un conteo, o uno o dos caracteres), un iconClass, iconUnicode o svgIcon, y un title para su información sobre herramientas nativa. text gana si usted suministra ambos. El texto más largo hace que la insignia se convierta en una píldora, y después de tres caracteres que representa 99+.
donde van
Omita position y las insignias llenarán las esquinas libres en el sentido de las agujas del reloj desde 'ne'. Nombre uno ('ne' | 'nw' | 'se' | 'sw') y se respeta textualmente, incluidas las superposiciones.
Cuatro caben en un nodo simple, dos contra uno con hijos. La expansión/contraer El control se ubica al noreste cuando un nodo colapsa y al sureste cuando está colapsado. expandido, por lo que en cualquier nodo expandible ambas las esquinas este están reservadas; de lo contrario cada insignia cambiaría de esquina en el momento en que se abriera un grupo. Insignias más allá de lo que encaja en un pliegue +n cuya información sobre herramientas los nombra.
Las insignias se escalan con el nodo entre el piso y el techo, por lo que permanecen legibles en un pequeño nodo sin hinchazón en uno grande, y se asientan en la forma real borde: la esquina de un cuadrado o una imagen enmarcada, el punto de 45° de un círculo.
Clics
Una insignia se puede probar pero es transparente de forma predeterminada: sin controlador, su clic falla y selecciona el nodo debajo, por lo que una insignia nunca es un punto muerto.
{ text: '3', onClick: (event, node, badge) => openNotes(node) }Dale a una insignia un onClick o declara callbacks.onBadgeClick por el comportamiento que todos comparten, y toma el cursor del puntero y consume su clic, dejando el nodo no seleccionado. Ambos disparan, el de la placa primero. Al presionar una insignia todavía se arrastra el nodo en cualquier dirección, y un oyente badgeClick en el bus de interacción puede cancel() ambos.
Alcance
Las insignias describen solo el nodo en el que se encuentran. Un clúster colapsado no agregue sus hijos: camine node.children en su propia función badges si eso es lo que quieres, ya que sólo tú sabes si un hecho suma, gana o ninguna de las dos cosas.
Detalle que sigue al zoom
Un dibujo que se lee bien de cerca es ilegible en una vista general, y un punto que se ajusta a un La descripción general no puede decir qué es. tiers permite que un nodo lleve varios dibujos y selecciones entre ellos del tamaño que representa actualmente el nodo.
const options = {
render: {
defaultNodeStyle: {
tiers: [
// Small: a coloured dot.
{ width: 32, height: 32, style: { shape: 'circle', size: 16 } },
// Once there is room for it: a labelled chip.
{ width: 140, height: 44, style: { shape: 'none', html: buildChip } },
],
},
},
}Los niveles se ordenan primero los más pequeños y gana el más rico que encaje. Cuando ninguno lo hace, el El nodo dibuja en su estilo base, por lo que el estilo que ya tienes es el piso: un gráfico que declara no tiers no se ve afectado en todos los aspectos.
Qué tier hereda
Un nivel se fusiona sobre el estilo base, por lo que se hereda un canal al que no nombra. el dibujo es la excepción: iconUnicode, iconClass, svgIcon, imagePath y html son una ranura, por lo que un nivel que nombre cualquiera de ellos reemplaza el dibujo de la base (y su imageFit) por completo. Un glifo en reposo con un nivel de carta no necesita nada más que la carta:
const options = {
render: {
defaultNodeStyle: {
svgIcon: buildGlyph,
tiers: [
{ width: 140, height: 44, style: { shape: 'none', html: buildChip } },
],
},
},
}Un nivel que no nombra ningún dibujo, solo size, color o text digamos, mantiene el glifo de la base.
Para eliminar un canal que el nivel no reemplaza, configúrelo en null, lo que significa el nivel atrae ese en absoluto. strokeColor: null suelta el contorno de la base, por instancia. undefined no puede entrar: significa "No voy a nombrar este canal", que es exactamente cómo sobrevive el valor de la base.
Esta es la única capa donde null funciona de esa manera. En todos los demás lugares de la cadena de estilos null todavía cae a la capa inferior, porque un styleCb devuelve un nulo directamente de datos del nodo tiene una forma ordinaria y siempre ha significado "usar el valor predeterminado".
Para darle forma a un nodo, use shape: 'none' en lugar de borrar shape.
¿Qué elige un nivel?
El tamaño renderizado: la huella del nodo en CSS píxeles, que es footprint × zoom. un El nivel se activa una vez que alcanza su minRenderedSize, que por defecto es el propio nivel. width, por lo que { width: 140 } se lee como "participar una vez que haya espacio para dibujar 140 píxeles de nodo".
La escala de zoom por sí sola no serviría. Multiplica las coordenadas del diseño inventado, por lo que la misma escala significa un tamaño aparente diferente en un gráfico diferente, y un umbral ajustado en un conjunto de datos sería incorrecto en el siguiente.
Un nivel que se ha comprometido se mantiene hasta que el tamaño representado cae al 85 % de su umbral. cada El nodo comparte un umbral, por lo que sin esa banda un lienzo estacionado en uno parpadearía como un entero.
La huella se queda
El cuadro que un nodo reserva en el diseño no cambia cuando lo hace su dibujo. es layoutSize, y por defecto es la mitad del nivel declarado más amplio, por lo que declarar niveles da la gráfica el espaciado correcto sin un segundo número. Nada se mueve cuando se intercambia un nivel: el El dibujo cambia dentro de una caja que ya tenía el tamaño correcto, y las fuerzas nunca ven el diferencia.
width y height se declaran en lugar de medirse, por la misma razón. El diseño tiene para conocer la huella antes del primer tic, y una tarjeta medida solo informa su tamaño una vez ha sido dibujado.
Establezca layoutSize para espaciar el gráfico más estrecho o más ancho que el nivel más ancho. Nota que un nivel se dibuja en su tamaño de diseño sólo cuando su ancho es igual a la huella; un uno más estrecho se acopla proporcionalmente antes y se dibuja proporcionalmente más pequeño. Dale un explícito minRenderedSize si eso importa.
El dibujo de enfoque
focusTier es el dibujo que utiliza un nodo mientras está suspendido o seleccionado por sí solo, cualquiera que sea el zoom. Aquí es donde un nodo dice todo sobre sí mismo, por lo que leer uno nunca significa acercarse a él.
const options = {
render: {
defaultNodeStyle: {
tiers: [/* … */],
focusTier: { shape: 'none', html: buildDetailCard },
},
},
}Se fusiona sobre el estilo base del nodo en lugar de sobre el nivel activo, por lo que un nivel de chip shape o html no pueden filtrarse. Mantiene un tamaño constante en la pantalla: el dibujo es contraescala contra el zoom, por lo que una tarjeta de 280 × 150 tiene 280 × 150 CSS píxeles por muy lejos que esté la gráfica es. Y nunca toca la geometría del nodo, por lo que los bordes siguen aterrizando en el nivel. debajo y flotando no se mueve nada.
El dibujo de enfoque lleva las insignias del nodo en su propio borde, al mismo tamaño en pantalla que el de la tarjeta. Las propias insignias del nodo están ocultas mientras se muestra, por lo que no se dibuja ninguna. dos veces. Dale a focusTier un badges propio para mostrar un conjunto diferente en la tarjeta.
Solo se promociona un nodo seleccionado por sí solo. Una selección de caja de cincuenta nodos sería una pared. de tarjetas superpuestas.
render.focusTierTrigger dice cuando se activa: 'both' (el valor predeterminado), 'hover', 'selection' o 'off'. Busque 'off' cuando esté incrustando un estilo preestablecido a alguien demás se envía y desea que se suprima el dibujo de enfoque sin editarlo.
Cuando un nivel ya lo muestra
A veces, el dibujo de enfoque es el mismo que uno de los niveles de zoom: un glifo en reposo que se desplaza sobre un chip, y el chip también se dibuja una vez que el gráfico se acerca lo suficiente. Allí, al pasar el cursor se pintaría un segundo chip más pequeño sobre el que ya está en la pantalla. focusTierYieldsAt nombra el índice en tiers desde el cual el dibujo de enfoque deja de dispararse:
defaultNodeStyle: {
tiers: [{ width: 140, height: 44, style: { shape: 'none', html: chipFor } }],
focusTier: { shape: 'none', html: chipFor },
focusTierYieldsAt: 0,
}Mientras el nodo está dibujado en ese nivel o en uno más rico, pase el cursor y haga una sola selección, déjelo como lo es. Sigue el nivel activo, no el nivel de zoom, por lo que utiliza los mismos umbrales que el intercambiar. Al acercar la tarjeta abierta, la imagen se desvanece a medida que el nivel se acerca y al volver a alejarla lo devuelve sin mover el puntero. Déjelo sin configurar en un nodo cuyo dibujo de enfoque diga más que cualquier nivel, y un nodo sin tiers lo ignora.
La información sobre herramientas aún se activa
Una tarjeta de enfoque no reemplaza la información sobre herramientas. Los dos son independientes y puede aparecer información sobre herramientas. llevar algo que la tarjeta no tiene.
El intercambio en sí
Un nodo se funde de un dibujo al siguiente en lugar de cortarlo. el saliente El dibujo se mantiene en una capa propia y los dos se desvanecen entre sí, por lo que un nodo nunca se elimina. ausente a mitad del intercambio, solo brevemente más suave donde se superponen.
render.detailTransition es el tiempo que lleva, en milisegundos. El valor predeterminado es 160 y cubre cada dibujo que el zoom decide: un cruce de niveles, el dibujo de enfoque y una etiqueta cruzando minLabelFontSize. Configúrelo en 0 para reemplazar el dibujo en un solo marco:
const options = {
render: {
detailTransition: 0,
defaultNodeStyle: { tiers: [/* … */] },
},
}Cada nodo en la pantalla se cruza al mismo tiempo, por lo que un cruce inicia tantos desvanecimientos como sea posible. hay nodos cambiando. Medido en 210 nodos, cada uno con una tarjeta de 140 × 44, el desvanecimiento se ejecuta a 60 fps en toda su duración; lo que cuesta son unos 26ms en el cuadro único del cruce ya gasta, y esa cifra no crece con la duración. Apágalo en un gráfico donde ese marco importa más que la transición.
prefers-reduced-motion lo apaga solo, diga lo que diga la opción.
Etiquetas en un tamaño legible
Una etiqueta recorre el gráfico y escala con él, por lo que cuanto más alejada está la vista, más pequeña es pintado. Un gráfico se abre en cualquier escala que elija el ajuste, y esa escala cae a medida que el gráfico crece: más allá de unos cientos de nodos, el marco de apertura es un texto que nadie puede leer, dibujado sobre el gráfico que está nombrando.
render.minLabelFontSize es el tamaño renderizado, en CSS píxeles, debajo del cual no se muestra una etiqueta dibujado. El valor predeterminado es 9.
const options = {
render: {
minLabelFontSize: 9,
},
}La prueba es fontSize × zoom, en píxeles renderizados en lugar de la escala de zoom: una escala multiplica las coordenadas del diseño inventado, por lo que el mismo valor significa un tamaño aparente diferente en el siguiente conjunto de datos.
Es un número para todo el lienzo, tanto para las etiquetas de los bordes como para las etiquetas de los nodos. la diferencia entre ellos ya está en el tamaño de fuente: se dibuja una etiqueta de borde en defaultLabelStyle.fontSize (12 por defecto), mientras que un nodo se deriva del nodo, max(12, size × 0.45), por lo que un nodo grande mantiene su etiqueta con un zoom menor que uno pequeño. El textFontSize de un estilo de nodo reemplaza ese tamaño derivado.
0 apaga la puerta y dibuja cada etiqueta en cada zoom.
¿Qué cuenta como etiqueta?
El texto que coloca la biblioteca: label de un borde, text de un nodo y lo que sea render.renderLabel regresa. El html, renderNode o tarjeta de nivel de un nodo es su dibujo, y tiers es lo que elige entre dibujos.
Una etiqueta que se muestra se mantiene hasta que su tamaño renderizado cae al 85% del umbral, por lo que La vista estacionada en la línea se estabiliza en lugar de parpadear. Cada etiqueta dibujada en un tamaño responde juntos, sea cual sea el elemento al que pertenezca.
Un borde seleccionado por sí solo muestra su etiqueta cualquiera que sea el zoom, contraescala para que sea legible en lugar de los dos píxeles en los que estaba oculto. Un borde no tiene información sobre herramientas ni panel, por lo que su etiqueta es lo único que responde "¿qué es esto?". Un nodo no necesita nada de eso: ya responde a través de su información sobre herramientas, la barra lateral y su dibujo focusTier.
Una etiqueta oculta no sólo es invisible, sino que no está en el gráfico, que es donde va el costo. Se reposiciona una etiqueta en cada tick de simulación y en un gráfico grande que muestra los costos por sí solos. más que un marco. Lo que queda después de la puerta es el trazo, que es barato.
lo que no hace
Por encima del umbral, las etiquetas aún pueden superponerse entre sí. Una etiqueta de borde suele ser más ancha que el borde que nombra, y esa proporción no cambia con el zoom. Esta opción se trata de legibilidad, sin desorden.
API
Pivotick expone un controlador de renderizado que le permite interactuar directamente con el motor de renderizado. Todos los métodos están disponibles en línea
Ajustar y ampliar
graph.renderer.fitAndCenter()graph.renderer.zoomIn()
graph.renderer.zoomOut()