PerfectVector
Di Irene Kim

Immagini SVG nei nodi Cytoscape.js: adatta i margini

Adatta grafica SVG personalizzata ai nodi Cytoscape.js con un esempio funzionante. Confronta spazio vuoto, contain e cover, poi controlla caricamento ed etichette.

10 min di lettura
In questa pagina

Usa un URL di immagine SVG nello stile background-image del nodo, poi scegli l’adattamento per la grafica da mostrare. Se lo stemma si carica ma appare minuscolo, esamina lo spazio vuoto nel viewport SVG prima di ingrandire il nodo del grafo. Se le estremità scompaiono, confronta le proporzioni dell’immagine con quelle del nodo e controlla il ritaglio.

Cytoscape.js documenta gli sfondi SVG dei nodi, compresi gli adattamenti contain, cover e none. Questa guida usa un nostro stemma a tracciato unico per distinguere i limiti della sorgente dallo stile del grafo. Conserva il master modificabile della grafica insieme alla configurazione del grafo.

Separa l’immagine sorgente dal nodo del grafo

Ci sono tre rettangoli da esaminare: i limiti disegnati della grafica, il viewport dell’immagine SVG e il corpo del nodo. Il viewBox SVG definisce il rettangolo di coordinate sorgente mappato nel viewport. Può includere molto più spazio del disegno visibile.

La nostra sorgente con margini ridotti misura 120 × 60, con lo stemma corallo da x=6 a x=114 e da y=6 a y=54. L’apertura centrale fa parte dello stesso tracciato:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg>
<svg xmlns="http://www.w3.org/2000/svg"
     width="120" height="60" viewBox="0 0 120 60">
  <path fill="#f36f59" fill-rule="evenodd"
    d="M6 30L30 6H90L114 30L90 54H30Z M50 20H70V40H50Z"/>
</svg>

La variante con margini ampi cambia solo le dimensioni esterne dell’SVG e il viewBox:

<svg xmlns="http://www.w3.org/2000/svg"
     width="200" height="140" viewBox="-40 -40 200 140">

Conserva la stessa intestazione, il tracciato e il tag di chiusura. I due file disegnano coordinate identiche. Il secondo le circonda con più spazio vuoto nella sorgente. Quello spazio si ridimensiona con l’immagine, quindi cambiare l’adattamento dello sfondo non può sostituire in modo affidabile la scelta di limiti sorgente adeguati. La guida al riquadro di delimitazione SVG aiuta quando il viewport del file e la grafica visibile non coincidono.

Esegui l’esempio con quattro casi

Abbiamo testato Cytoscape.js 3.34.3 con un bundle browser ufficiale fissato a quella versione e servito localmente. Salva il bundle di quel tag di rilascio come cytoscape-3.34.3.min.js accanto all’example.html seguente. Servi la cartella tramite HTTP locale, per esempio con python3 -m http.server 8000, e apri http://localhost:8000/example.html.

L’esempio codifica l’SVG originale in un URI di dati. encodeURIComponent() applica l’escape ai caratteri URI, incluso il # del colore di riempimento. La guida SVG della libreria raccomanda questa codifica anziché Base64 e l’intestazione XML mostrata qui. È uno stemma autonomo senza font o immagini esterni.

<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>SVG node fit comparison</title>
<style>
  body { font: 16px system-ui; margin: 20px; }
  #cy { width: 1100px; height: 250px; border: 1px solid #ddd; }
  #status { white-space: pre-wrap; }
</style>
<div id="cy"></div>
<pre id="status">Loading images</pre>
<script src="cytoscape-3.34.3.min.js"></script>
<script>
const header = '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg>';
const path = 'M6 30L30 6H90L114 30L90 54H30Z M50 20H70V40H50Z';
function artwork(padded) {
  const width = padded ? 200 : 120;
  const height = padded ? 140 : 60;
  const viewBox = padded ? '-40 -40 200 140' : '0 0 120 60';
  return header + `<svg xmlns="http://www.w3.org/2000/svg"
    width="${width}" height="${height}" viewBox="${viewBox}">
    <path fill="#f36f59" fill-rule="evenodd" d="${path}"/></svg>`;
}
const cases = [
  ['tight contain', false, 'contain'],
  ['tight cover', false, 'cover'],
  ['padded contain', true, 'contain'],
  ['padded cover', true, 'cover']
].map(([label, padded, fit]) => ({
  label, fit,
  image: 'data:image/svg+xml;utf8,' + encodeURIComponent(artwork(padded))
}));
Promise.all(cases.map(item => new Promise((resolve, reject) => {
  const image = new Image();
  image.onload = () => resolve({
    label: item.label,
    width: image.naturalWidth,
    height: image.naturalHeight
  });
  image.onerror = () => reject(new Error(item.label + ' failed to load'));
  image.src = item.image;
}))).then(loaded => {
  cytoscape({
    container: document.getElementById('cy'),
    elements: cases.map((item, index) => ({
      data: { id: 'n' + index, ...item },
      position: { x: 110 + index * 260, y: 95 }
    })),
    style: [{ selector: 'node', style: {
      width: 120, height: 80, padding: 0, shape: 'rectangle',
      'background-color': '#f1f3f5',
      'background-image': 'data(image)',
      'background-fit': node => node.data('fit'),
      'background-width': 'auto', 'background-height': 'auto',
      'background-width-relative-to': 'inner',
      'background-height-relative-to': 'inner',
      'background-position-x': '50%', 'background-position-y': '50%',
      'background-repeat': 'no-repeat', 'background-clip': 'node',
      'border-width': 1, 'border-color': '#222',
      label: 'data(label)', 'text-valign': 'bottom',
      'text-halign': 'center', 'text-margin-y': 10, 'font-size': 12
    }}],
    layout: { name: 'preset', fit: false },
    zoom: 1, pan: { x: 0, y: 0 },
    userZoomingEnabled: false, userPanningEnabled: false,
    boxSelectionEnabled: false
  });
  document.getElementById('status').textContent =
    'Cytoscape ' + cytoscape.version + '\n' +
    JSON.stringify(loaded, null, 2);
}).catch(error => {
  document.getElementById('status').textContent = error.message;
});
</script>
</html>

Il blocco di stato riporta le dimensioni delle immagini precaricate prima dell’inizializzazione del grafo. naturalWidth legge la larghezza intrinseca dell’immagine, corretta per la densità, in pixel CSS, come descritto da MDN. In questo file di prova, le immagini con margini ridotti riportavano 120 × 60 e quelle con margini ampi 200 × 140. Sono dimensioni delle immagini, non misure del tracciato corallo.

Confronta cosa cambia con la stessa dimensione del nodo

Tutti e quattro i nodi del modello misurano 120 × 80, con padding del nodo pari a zero. Abbiamo esaminato il file originale in Chrome con zoom del grafo 1 e 1.5. Lo stile del nodo restava 120 × 80; le dimensioni renderizzate riportate diventavano 180 × 120 a 1.5. Era un confronto statico in quel browser, non un benchmark di compatibilità o prestazioni dello zoom.

Sorgente e adattamentoAspetto osservato in questo file di prova
Margini ridotti, containStemma completo con estremità appuntite visibili
Margini ridotti, coverStemma più grande con punte sinistra e destra tagliate dal nodo
Margini ampi, containStemma più piccolo circondato da molto spazio vuoto
Margini ampi, coverLeggermente più grande del caso precedente, ancora molto più piccolo dei casi con margini ridotti

La sorgente con margini ridotti ha un rapporto d’immagine 2:1, mentre il nodo è 1.5:1. Adattare l’intera immagine 120 × 60 dentro 120 × 80 lascia spazio verticale. Coprire quel nodo scala l’immagine a 160 × 80 prima del ritaglio, quindi le estremità orizzontali escono dal corpo.

Per la sorgente con margini ampi, il rettangolo disponibile include 40 unità di spazio aggiuntivo su ogni lato. Con contain, la scala è limitata da 80/140 anziché 120/200. Lo stemma invariato, largo 108 unità, occupa quindi circa 62 unità del modello. È un calcolo dalle dimensioni dichiarate, non una misura in pixel della schermata.

Limiti sorgente e adattamento
Illustrazione di uno stemma piccolo con molto spazio vuoto nella sorgente, uno stemma completo più grande dentro la cornice di un nodo e uno stemma con punte tagliate da una cornice più stretta.
Illustrazione: spazio vuoto della sorgente e adattamento possono cambiare indipendentemente la grafica visibile. Questo diagramma concettuale non è una schermata di Cytoscape né un risultato di conversione.

Scegli l’adattamento dopo aver rivisto i limiti della grafica

Parti dalla sorgente con margini ridotti e contain quando conta mostrare lo stemma completo. Conserva abbastanza margine nella sorgente per ogni contorno o effetto che deve restare visibile. Restringere troppo un viewport può tagliare grafica legittima; non è un invito a rimuovere ogni margine.

Usa cover quando il ritaglio dei bordi è accettabile per il disegno. Nel nostro esempio nasconde le punte, quindi è una cattiva scelta se identificano lo stemma. Un nodo più largo può cambiare il rapporto di adattamento e mostrare le punte, ma cambia anche il layout del grafo. Ingrandire proporzionalmente entrambe le dimensioni conserva lo stesso ritaglio. Decidi quale vincolo vuoi cambiare.

Mantieni background-width e background-height su auto per questo confronto. Valori espliciti possono sovrascrivere le dimensioni dell’immagine usate per l’adattamento. Il padding del nodo è un input distinto; la libreria documenta se il dimensionamento dello sfondo lo include o usa il corpo interno. Consulta il riferimento background-image prima di aggiungere quei controlli. Il nostro test con padding zero isola prima lo spazio vuoto della sorgente.

Per decisioni di meet, slice e allineamento a livello SVG, prosegui con la guida a preserveAspectRatio. Cambiare l’adattamento interno di un SVG e quello dello sfondo in Cytoscape sono operazioni separate.

Diagnostica il caricamento prima del ritaglio

Se lo stato riporta un errore di caricamento, passare da contain a cover non è il passo successivo. Apri la risorsa immagine da sola, controllane URL e dimensioni dichiarate, poi riducila allo stemma autonomo con soli tracciati sopra. Per un URI di dati, codifica l’intera stringa SVG anziché concatenare markup grezzo o un valore colore senza escape.

Un SVG usato come immagine ha restrizioni diverse da un SVG aperto come documento. La guida MDN a SVG come immagine descrive le restrizioni su script e risorse esterne nei contesti immagine. Una grafica che dipende da un foglio di stile o un font esterni richiede una prova di consegna separata. Questo esempio evita tali dipendenze e colloca le etichette del grafo fuori dall’SVG.

Se l’immagine si carica, controlla adattamento e ritaglio del nodo con una forma palesemente larga. Poi prova la tua grafica reale alle dimensioni dei nodi e negli ambienti browser supportati dall’applicazione. La documentazione Cytoscape segnala aspetti SVG specifici dei browser; questa osservazione in Chrome non li risolve per Firefox o ogni altro motore.

Mantieni separate etichette e grafica modificabile

L’esempio usa label: 'data(label)' per le etichette del grafo e non contiene testo SVG. Puoi cambiare quelle parole senza ricostruire lo stemma. Il tracciato SVG resta nel master sorgente, mentre il grafo gestisce identità, posizione e relazioni dei nodi.

Il file di prova esaminato disegnava su superfici Canvas. Vedere lì uno sfondo SVG non rende i suoi tracciati interni elementi del grafo modificabili separatamente. Conserva il master quando devi cambiare apertura, sagoma o colori. L’esportazione del grafo è un procedimento separato che richiede un esportatore scelto e una prova di consegna specifica; questa guida non promette che un grafo esportato conservi tracciati modificabili dello stemma. La guida alla grafica in Graphviz esplora il passaggio tramite riferimenti a immagini in un altro renderer di diagrammi.

Se il tuo stemma personalizzato esiste solo come PNG o JPG, converti quella sorgente in grafica vettoriale, poi esamina sagoma, apertura e piccoli dettagli prima di impostare i limiti SVG. PerfectVector può aiutare a recuperare geometria sorgente modificabile. Stile dello sfondo, etichette dei nodi ed esportazione del grafo restano passaggi separati. Un SVG già adatto può passare direttamente ai controlli di adattamento.

Domande frequenti

Perché l’immagine SVG del nodo è minuscola anche con cover? L’immagine sorgente può contenere molto spazio vuoto nel viewport attorno al tracciato. Confronta una copia con limiti più vicini alle stesse dimensioni del nodo prima di cambiare il layout del grafo.

Devo usare contain o cover per uno stemma personalizzato? Scegli contain quando conta lo stemma completo. Scegli cover solo quando il ritaglio osservato dei bordi è accettabile per il disegno e verificalo con la tua sorgente e la forma del nodo.

Uno sfondo SVG del nodo crea tracciati modificabili nel grafo? Il test Canvas usa l’SVG come immagine dipinta. Conserva il master della grafica per modificare i tracciati; i suoi contorni interni non sono nodi o archi separati del grafo in questo esempio.

Posso inserire etichette nell’SVG? Questo esempio mantiene le etichette nei dati del grafo e usa grafica con soli tracciati. Testo SVG, font e dipendenze del contesto immagine richiedono controlli specifici su browser e consegna.

Fonti

  1. Cytoscape.js — Immagine di sfondo — stile tramite URL immagine, adattamento, sostituzioni delle dimensioni, riferimenti al padding e aspetti SVG.
  2. Cytoscape.js — Rilascio v3.34.3 — rilascio fissato usato nel test originale.
  3. Cytoscape.js — Bundle browser v3.34.3 — implementazione ufficiale con tag servita localmente per il test nel browser.
  4. MDN — viewBox — rettangolo di coordinate sorgente e mappatura nel viewport.
  5. MDN — encodeURIComponent — escape del componente SVG dell’URI di dati.
  6. MDN — naturalWidth — dimensioni dell’immagine caricata, distinte dai limiti del tracciato.
  7. MDN — SVG come immagine — restrizioni del contesto immagine e controlli delle dipendenze.

Se lo stemma parte da raster, crea un master SVG modificabile, esamina contorni e limiti sorgente, poi confronta contain e cover nel tuo layout di nodi.

Altro dal blog

PerfectVector

Riparti da un SVG più pulito
e facile da modificare

Nessuna carta di credito