PerfectVector
Von Irene Kim

Cytoscape.js: SVG-Knotenbilder passend einfügen

Passe eigene SVG-Grafiken mit einem lauffähigen Beispiel in Cytoscape.js-Knoten ein. Vergleiche Quellleerraum, contain und cover und prüfe Laden und Beschriftung.

9 Min. Lesezeit
Auf dieser Seite

Verwende eine SVG-Bild-URL im Knotenstil background-image und wähle dann die passende Einpassung für die gewünschte Grafik. Wird das Emblem geladen, wirkt aber winzig, prüfe vor dem Vergrößern des Graphknotens den Leerraum im SVG-Viewport. Verschwinden seine Enden, vergleiche die Bildproportionen mit denen des Knotens und prüfe das Abschneiden.

Cytoscape.js dokumentiert SVG-Knotenhintergründe, einschließlich der Einpassungen contain, cover und none. Dieser Leitfaden verwendet ein selbst erstelltes Emblem aus einem Pfad, um Quellgrenzen vom Graphstil zu trennen. Bewahre die bearbeitbare Grafik-Masterdatei zusammen mit der Graphkonfiguration auf.

Trenne Quellbild und Graphknoten

Es gibt drei Rechtecke zu prüfen: die gezeichneten Grenzen der Grafik, den SVG-Bild-Viewport und den Knotenkörper. Die SVG-viewBox definiert das Quellkoordinatenrechteck, das in den Viewport abgebildet wird. Es kann deutlich mehr Platz als die sichtbare Zeichnung enthalten.

Unsere eng begrenzte Quelle ist 120 × 60 groß. Das korallfarbene Emblem reicht von x=6 bis x=114 und von y=6 bis y=54. Seine mittige Öffnung gehört zum selben Pfad:

<?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>

Die Variante mit Rand ändert nur die äußeren SVG-Abmessungen und die viewBox:

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

Behalte denselben Header, Pfad und schließenden Tag. Beide Dateien zeichnen identische Pfadkoordinaten. Die zweite umgibt sie mit mehr leerem Quellraum. Dieser Raum skaliert mit dem Bild. Eine andere Hintergrundeinpassung ersetzt daher nicht zuverlässig die Wahl geeigneter Quellgrenzen. Der Leitfaden zum SVG-Begrenzungsrahmen hilft, wenn der Viewport der Datei und die sichtbare Grafik nicht übereinstimmen.

Führe das Beispiel mit vier Fällen aus

Wir haben Cytoscape.js 3.34.3 mit einem lokal bereitgestellten offiziellen Browser-Bundle in festgelegter Version getestet. Speichere das Bundle dieses Release-Tags als cytoscape-3.34.3.min.js neben der unten gezeigten Datei example.html. Stelle den Ordner über lokales HTTP bereit, etwa mit python3 -m http.server 8000, und öffne http://localhost:8000/example.html.

Das Beispiel kodiert das ursprüngliche SVG als Daten-URI. encodeURIComponent() maskiert URI-Zeichen, darunter das # in unserer Füllfarbe. Die SVG-Hinweise der Bibliothek empfehlen diese Kodierung statt Base64 sowie den hier gezeigten XML-Header. Dies ist ein eigenständiges Emblem ohne externe Schriften oder Bilder.

<!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>

Der Statusblock meldet die Abmessungen der vor der Graphinitialisierung vorgeladenen Bilder. naturalWidth liest die intrinsische, dichtekorrigierte Bildbreite in CSS-Pixeln aus, wie MDN beschreibt. In dieser Testdatei meldeten die eng begrenzten Bilder 120 × 60 und die Bilder mit Rand 200 × 140. Das sind Bildabmessungen, keine Messungen des korallfarbenen Pfads.

Vergleiche Änderungen bei gleicher Knotengröße

Alle vier Modellknoten sind 120 × 80 groß und haben keinen inneren Knotenabstand. Wir prüften die ursprüngliche Testdatei in Chrome bei Graphzoom 1 und 1.5. Der Knotenstil blieb bei 120 × 80. Seine gemeldeten gerenderten Abmessungen wurden bei 1.5 zu 180 × 120. Das war ein statischer Vergleich in diesem Browser, kein Kompatibilitäts- oder Zoomleistungsbenchmark.

Quelle und EinpassungBeobachtetes Aussehen in dieser Testdatei
Eng begrenzt, containVollständiges Emblem mit sichtbaren spitzen Enden
Eng begrenzt, coverGrößeres Emblem mit links und rechts am Knoten abgeschnittenen Spitzen
Mit Rand, containKleineres Emblem mit viel umgebendem Leerraum
Mit Rand, coverEtwas größer als mit Rand und contain, aber weiterhin viel kleiner als die eng begrenzten Fälle

Die eng begrenzte Quelle hat ein Bildverhältnis von 2:1, der Knoten dagegen 1.5:1. Wird das vollständige 120 × 60 große Bild in 120 × 80 eingepasst, bleibt vertikaler Raum. Beim Abdecken dieses Knotens wird das Bild vor dem Abschneiden auf 160 × 80 skaliert, sodass seine horizontalen Enden über den Körper hinausragen.

Bei der Quelle mit Rand enthält das verfügbare Bildrechteck auf jeder Seite 40 Einheiten zusätzlichen Raum. Mit contain begrenzt 80/140 statt 120/200 den Maßstab. Das unveränderte, 108 Einheiten breite Emblem belegt daher ungefähr 62 Modelleinheiten. Diese Zahl ist aus den angegebenen Abmessungen berechnet, keine Pixelmessung eines Screenshots.

Quellgrenzen und Einpassung
Illustration eines kleinen Emblems mit großzügigem Quellleerraum, eines vollständigen größeren Emblems in einem Knotenrahmen und eines Emblems mit durch einen schmaleren Rahmen abgeschnittenen Spitzen.
Illustration: Quellleerraum und Einpassung können die sichtbare Grafik unabhängig voneinander verändern. Diese schematische Darstellung ist weder ein Cytoscape-Screenshot noch ein Konvertierungsergebnis.

Wähle die Einpassung nach Prüfung der Grafikgrenzen

Beginne mit der eng begrenzten Quelle und contain, wenn das vollständige Emblem wichtig ist. Behalte genügend Quellrand für alle Konturen und Effekte, die sichtbar bleiben müssen. Ein zu eng gesetzter Viewport kann berechtigte Grafikbestandteile abschneiden. Das ist keine Aufforderung, jeden Rand zu entfernen.

Verwende cover, wenn abgeschnittene Kanten für den Entwurf akzeptabel sind. In unserem Beispiel verschwinden die spitzen Enden. Deshalb ist es ungeeignet, wenn diese Spitzen das Emblem kennzeichnen. Ein breiterer Knoten kann das Einpassungsverhältnis ändern und die Spitzen sichtbar machen, verändert aber auch das Graphlayout. Eine proportionale Vergrößerung beider Abmessungen behält denselben Beschnitt. Entscheide, welche Einschränkung du ändern möchtest.

Lass background-width und background-height für diesen Vergleich auf auto. Ausdrückliche Werte können die zur Einpassung verwendeten Bildabmessungen überschreiben. Das Knoten-padding ist eine weitere separate Eingabe. Die Bibliothek dokumentiert, ob die Hintergrundgröße diesen Abstand einschließt oder den inneren Körper verwendet. Sieh dir die Referenz zu background-image an, bevor du diese Einstellungen ergänzt. Unsere Testdatei ohne Innenabstand isoliert zunächst den Quellleerraum.

Für meet, slice und Ausrichtungsentscheidungen auf SVG-Ebene lies den Leitfaden zu preserveAspectRatio. Die interne Einpassung eines SVGs zu ändern und Cytoscapes Hintergrundeinpassung zu ändern sind getrennte Operationen.

Prüfe das Laden vor dem Abschneiden

Wenn der Status einen Ladefehler meldet, ist der Wechsel von contain zu cover nicht der nächste Schritt. Öffne die Bildressource allein, prüfe URL und angegebene Abmessungen und reduziere sie anschließend auf das obige eigenständige Emblem nur aus Pfaden. Kodiere bei einer Daten-URI die gesamte SVG-Zeichenfolge, statt unverarbeitetes Markup oder einen nicht maskierten Farbwert anzuhängen.

Für ein als Bild verwendetes SVG gelten andere Einschränkungen als für ein als Dokument geöffnetes SVG. MDNs Leitfaden zu SVG als Bild beschreibt Einschränkungen für Skripte und externe Ressourcen in Bildkontexten. Eine Grafikdatei, die ein externes Stylesheet oder eine externe Schrift benötigt, braucht einen eigenen Auslieferungstest. Dieses Beispiel vermeidet solche Abhängigkeiten und platziert die Graphbeschriftungen außerhalb des SVGs.

Wenn das Bild geladen wird, prüfe Einpassung und Knotenbeschnitt mit einer deutlich breiten Form. Teste danach deine tatsächliche Grafik in der Knotengröße und den Browserumgebungen, die deine Anwendung unterstützt. Die Cytoscape-Dokumentation nennt browserspezifische SVG-Aspekte. Diese Chrome-Beobachtung klärt sie nicht für Firefox oder jede andere Engine.

Halte Beschriftungen und bearbeitbare Grafik getrennt

Das Beispiel verwendet label: 'data(label)' für Graphbeschriftungen und enthält keinen SVG-Text. Du kannst den Wortlaut ändern, ohne das Emblem neu zu bauen. Der SVG-Pfad bleibt in seiner Quell-Masterdatei, während der Graph Identität, Platzierung und Beziehungen der Knoten verwaltet.

Die untersuchte Testdatei zeichnete auf Canvas-Flächen. Ein dort sichtbarer SVG-Hintergrund macht dessen interne Pfade nicht zu separat bearbeitbaren Graphelementen. Bewahre die Masterdatei auf, wenn du Öffnung, Silhouette oder Farben ändern musst. Der Graphexport ist ein eigener Ablauf, für den du einen Exporter wählen und die Ausgabe testen musst. Dieser Leitfaden verspricht nicht, dass ein exportierter Graph bearbeitbare Emblempfade erhält. Der Graphviz-Grafikleitfaden untersucht die Übergabe über Bildreferenzen bei einem anderen Diagrammrenderer.

Wenn dein eigenes Emblem nur als PNG oder JPG existiert, konvertiere diese Vorlage in Vektorgrafik. Prüfe danach Silhouette, Öffnung und kleine Details, bevor du die SVG-Grenzen festlegst. PerfectVector kann helfen, bearbeitbare Quellgeometrie wiederherzustellen. Hintergrundgestaltung, Knotenbeschriftung und Graphexport bleiben separate Schritte. Ein vorhandenes geeignetes SVG kann direkt zu den Einpassungsprüfungen gehen.

Häufige Fragen

Warum ist mein SVG-Knotenbild selbst mit cover winzig? Das Quellbild kann viel leeren Viewport-Raum um seinen Pfad enthalten. Vergleiche bei denselben Knotenabmessungen eine eng begrenzte Kopie, bevor du das Graphlayout änderst.

Sollte ich für ein eigenes Emblem contain oder cover verwenden? Wähle contain, wenn das vollständige Emblem wichtig ist. Wähle cover nur, wenn der beobachtete Kantenbeschnitt für deinen Entwurf akzeptabel ist, und prüfe es mit deiner eigenen Quelle und Knotenform.

Erzeugt ein SVG-Knotenhintergrund bearbeitbare Graphpfade? Die getestete Canvas-Datei verwendet das SVG als Bildfüllung. Behalte die Grafik-Masterdatei für Pfadänderungen. Ihre internen Konturen sind in diesem Beispiel keine separaten Graphknoten oder -kanten.

Kann ich Beschriftungen im SVG unterbringen? Dieses Beispiel hält Beschriftungen in den Graphdaten und verwendet eine reine Pfadgrafik. SVG-Text, Schriften und Abhängigkeiten im Bildkontext brauchen eigene Browser- und Auslieferungsprüfungen.

Quellen

  1. Cytoscape.js – Hintergrundbild – Bild-URL-Stil, Einpassung, Größenüberschreibungen, Innenabstandsbezüge und SVG-Aspekte.
  2. Cytoscape.js – Release v3.34.3 – Festgelegte Version der ursprünglichen Testdatei.
  3. Cytoscape.js – Browser-Bundle v3.34.3 – Offizielle getaggte Implementierung, lokal für den Browsertest bereitgestellt.
  4. MDN – viewBox – Quellkoordinatenrechteck und Viewport-Abbildung.
  5. MDN – encodeURIComponent – Maskierung der SVG-Daten-URI-Komponente.
  6. MDN – naturalWidth – Abmessungen geladener Bilder, unabhängig von Pfadgrenzen.
  7. MDN – SVG als Bild – Einschränkungen im Bildkontext und Prüfung von Abhängigkeiten.

Wenn dein Emblem als Rasterbild vorliegt, erstelle eine bearbeitbare SVG-Masterdatei, prüfe Konturen und Quellgrenzen und vergleiche dann contain und cover in deinem eigenen Knotenlayout.

Mehr aus dem Blog

PerfectVector

Starte mit einer sauberen SVG,
die leichter zu bearbeiten ist

Keine Kreditkarte nötig