> [Site index](https://perfectvector.com/llms.txt) — available pages and descriptions.

# SVG в узлах Cytoscape.js: вписывание и отступы

> Впишите собственную SVG-графику в узлы Cytoscape.js с рабочим примером. Сравните пустое место исходника, contain и cover, затем проверьте загрузку и размещение подписей.

Source: https://perfectvector.com/ru/blog/cytoscape-svg-node-artwork

Language: ru
Author: Irene Kim
Published: 2026-10-02T08:00:00+09:00
Updated: 2026-10-02T08:00:00+09:00

Используйте URL изображения SVG в стиле узла `background-image`, затем выберите вписывание для графики, которую хотите показать. Если эмблема загружается, но выглядит крошечной, перед увеличением узла графа проверьте пустое пространство в области просмотра SVG. Если её концы исчезают, сравните пропорции изображения и узла и проверьте обрезку.

Cytoscape.js [описывает SVG-фоны узлов](https://js.cytoscape.org/#style/background-image), включая режимы вписывания `contain`, `cover` и `none`. В этом руководстве оригинальная эмблема из одного контура помогает отделить границы исходника от оформления графа. Держите редактируемый мастер графики рядом с конфигурацией графа.

## Отделите исходное изображение от узла графа

Нужно проверить три прямоугольника: границы нарисованной графики, область просмотра SVG-изображения и тело узла. [SVG `viewBox`](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/viewBox) задаёт прямоугольник исходных координат, отображаемый в область просмотра. Он может включать намного больше пространства, чем видимый рисунок.

Наш плотно ограниченный исходник имеет размер 120 × 60, а коралловая эмблема занимает x=6–x=114 и y=6–y=54. Центральное отверстие — часть того же контура:

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

Вариант с полями меняет только внешние размеры SVG и `viewBox`:

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

Сохраните те же заголовок, контур и закрывающий тег. Оба файла рисуют одинаковые координаты контура. Второй окружает их большим пустым пространством исходника. Это пространство масштабируется вместе с изображением, поэтому изменение вписывания фона не может надёжно заменить подходящие границы исходника. [Руководство по ограничивающему прямоугольнику SVG](https://perfectvector.com/ru/blog/svg-bounding-box) поможет, когда область просмотра файла не соответствует видимой графике.

## Запустите пример с четырьмя случаями

Мы проверили Cytoscape.js [3.34.3](https://github.com/cytoscape/cytoscape.js/releases/tag/v3.34.3) с официальной браузерной сборкой закреплённой версии, размещённой локально. Сохраните [сборку из этого тега выпуска](https://raw.githubusercontent.com/cytoscape/cytoscape.js/v3.34.3/dist/cytoscape.min.js) как `cytoscape-3.34.3.min.js` рядом с приведённым ниже `example.html`. Раздавайте папку по локальному HTTP, например с помощью `python3 -m http.server 8000`, и откройте `http://localhost:8000/example.html`.

Пример кодирует исходный SVG в data URI. [`encodeURIComponent()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) экранирует символы URI, включая `#` в цвете заливки. Рекомендации библиотеки для SVG советуют это кодирование вместо Base64 и показанный здесь заголовок XML. Это одна самодостаточная эмблема без внешних шрифтов или изображений.

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

Блок состояния сообщает размеры изображений, предварительно загруженных до инициализации графа. `naturalWidth` читает собственную ширину изображения с поправкой на плотность в CSS-пикселях, как описано в [MDN](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/naturalWidth). В этом примере плотно ограниченные изображения сообщили 120 × 60, а изображения с полями — 200 × 140. Это размеры изображения, а не измерения кораллового контура.

## Сравните изменения при одном размере узла

Все четыре модельных узла имеют размер 120 × 80 и нулевой внутренний отступ. Мы проверили исходный пример в Chrome при масштабе графа 1 и 1,5. Размер в стиле узла оставался 120 × 80; сообщаемые отрисованные размеры при 1,5 стали 180 × 120. Это статичное сравнение в данном браузере, а не проверка совместимости или производительности масштабирования.

| Исходник и вписывание    | Наблюдаемый вид в этом примере                                                                        |
| ------------------------ | ----------------------------------------------------------------------------------------------------- |
| Плотные границы, contain | Полная эмблема с видимыми заострёнными концами                                                        |
| Плотные границы, cover   | Более крупная эмблема с левым и правым концами, обрезанными узлом                                     |
| С полями, contain        | Меньшая эмблема, окружённая значительным пустым пространством                                         |
| С полями, cover          | Немного крупнее варианта с полями и contain, но всё ещё намного меньше вариантов с плотными границами |

Плотно ограниченный исходник имеет пропорции изображения 2:1, а узел — 1,5:1. Вписывание полного изображения 120 × 60 внутрь 120 × 80 оставляет место по вертикали. Покрытие этого узла масштабирует изображение до 160 × 80 перед обрезкой, поэтому горизонтальные концы выходят за тело узла.

У исходника с полями доступный прямоугольник изображения включает по 40 дополнительных единиц с каждой стороны. При contain масштаб ограничивается отношением 80/140, а не 120/200. Поэтому неизменённая эмблема шириной 108 единиц занимает примерно 62 модельные единицы. Это арифметика из объявленных размеров, а не измерение пикселей снимка экрана.

**Границы исходника и вписывание**

![Иллюстрация маленькой эмблемы с большим пустым пространством исходника, полной более крупной эмблемы внутри рамки узла и эмблемы с концами, обрезанными более узкой рамкой.](https://perfectvector.com/blog/cytoscape-svg-node-artwork/source-bounds-fit.webp)

*Иллюстрация: пустое место исходника и вписывание могут независимо менять видимую графику. Эта концептуальная схема не является снимком Cytoscape или результатом преобразования.*

## Выбирайте вписывание после проверки границ графики

Начните с плотных границ исходника и contain, если важна полная эмблема. Сохраняйте достаточный запас в исходнике для обводки или эффекта, который должен остаться видимым. Слишком сильное сужение области просмотра может обрезать нужную графику; это не указание убрать все поля.

Используйте cover, когда обрезка краёв допустима для дизайна. В нашем примере он скрывает заострённые концы, поэтому плохо подходит, если они определяют эмблему. Более широкий узел может изменить пропорции вписывания и открыть концы, но также меняет компоновку графа. Пропорциональное увеличение обоих размеров сохраняет ту же обрезку. Решите, какое ограничение хотите изменить.

Для этого сравнения оставьте `background-width` и `background-height` равными `auto`. Явные значения могут переопределить размеры изображения, используемые при вписывании. `padding` узла — ещё один отдельный фактор; библиотека описывает, включает ли размер фона этот отступ или использует внутреннее тело. Прежде чем добавлять эти настройки, см. [справочник background-image](https://js.cytoscape.org/#style/background-image). Наш пример с нулевым отступом сначала изолирует пустое пространство исходника.

Для решений meet, slice и выравнивания на уровне SVG перейдите к [руководству по preserveAspectRatio](https://perfectvector.com/ru/blog/svg-preserveaspectratio). Изменение внутреннего вписывания SVG и изменение вписывания фона Cytoscape — разные операции.

## Диагностируйте загрузку до обрезки

Если состояние сообщает об ошибке загрузки, смена contain на cover — не следующий шаг. Откройте ресурс изображения отдельно, проверьте URL и объявленные размеры, затем сократите его до самодостаточной эмблемы только из контуров, приведённой выше. Для data URI кодируйте всю строку SVG, а не склеивайте необработанную разметку или неэкранированное значение цвета.

SVG, используемый как изображение, имеет иные ограничения, чем SVG, открытый как документ. [Руководство MDN по SVG как изображению](https://developer.mozilla.org/en-US/docs/Web/SVG/Guides/SVG_as_an_image) описывает ограничения сценариев и внешних ресурсов в контексте изображения. Файлу графики, зависящему от внешней таблицы стилей или шрифта, нужна отдельная проверка передачи. Этот пример избегает таких зависимостей и размещает подписи графа вне SVG.

Если изображение загружается, проверьте вписывание и обрезку узла на явно широкой фигуре. Затем проверьте настоящую графику при размере узла и в браузерных средах, которые поддерживает приложение. Документация Cytoscape отмечает особенности SVG в разных браузерах; это наблюдение в Chrome не решает их для Firefox или любого другого движка.

## Держите подписи отдельно от редактируемой графики

Пример использует `label: 'data(label)'` для подписей графа и не содержит текста SVG. Вы можете менять формулировки без перестроения эмблемы. Контур SVG остаётся в исходном мастер-файле, а граф управляет идентичностью узла, положением и связями.

Проверенный пример рисовал на поверхностях Canvas. Наличие SVG-фона там не превращает внутренние контуры в отдельно редактируемые элементы графа. Сохраняйте мастер, если нужно менять отверстие, силуэт или цвета. Экспорт графа — отдельный процесс, требующий выбранного экспортёра и проверки передачи; это руководство не обещает, что экспортированный граф сохранит редактируемые контуры эмблемы. [Руководство по графике Graphviz](https://perfectvector.com/ru/blog/graphviz-svg-node-images) исследует передачу ссылок на изображения в другом средстве отрисовки диаграмм.

Если ваша эмблема существует только в PNG или JPG, [преобразуйте этот исходник в векторную графику](https://perfectvector.com/ru/image-to-vector), затем проверьте силуэт, отверстие и мелкие детали до настройки границ SVG. PerfectVector может помочь восстановить редактируемую исходную геометрию. Оформление фона, подписи узлов и экспорт графа остаются отдельными этапами. Уже подходящий SVG может сразу перейти к проверкам вписывания.

## Частые вопросы

**Почему SVG-изображение узла крошечное даже при cover?**
В исходном изображении может быть много пустого пространства области просмотра вокруг контура. Сравните копию с плотными границами при тех же размерах узла до изменения компоновки графа.

**Выбрать contain или cover для собственной эмблемы?**
Выбирайте contain, когда важна полная эмблема. Выбирайте cover, только если наблюдаемая обрезка краёв допустима для дизайна, и проверяйте это на собственном исходнике и форме узла.

**Создаёт ли SVG-фон узла редактируемые контуры графа?**
Проверенный пример Canvas использует SVG для рисования изображения. Держите мастер графики для правки контуров; внутренние контуры в этом примере не являются отдельными узлами или рёбрами графа.

**Можно ли поместить подписи в SVG?**
Этот пример хранит подписи в данных графа и использует графику только из контуров. Текст SVG, шрифты и зависимости контекста изображения требуют собственных браузерных проверок и проверок передачи.

## Источники

1. [Cytoscape.js — Фоновое изображение](https://js.cytoscape.org/#style/background-image) — оформление URL изображения, вписывание, переопределение размеров, опорные области отступов и особенности SVG.
2. [Cytoscape.js — Выпуск v3.34.3](https://github.com/cytoscape/cytoscape.js/releases/tag/v3.34.3) — закреплённый выпуск, использованный в исходном примере.
3. [Cytoscape.js — Браузерная сборка v3.34.3](https://raw.githubusercontent.com/cytoscape/cytoscape.js/v3.34.3/dist/cytoscape.min.js) — официальная реализация из тега, локально размещённая для браузерного теста.
4. [MDN — viewBox](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/viewBox) — прямоугольник исходных координат и отображение в область просмотра.
5. [MDN — encodeURIComponent](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) — экранирование компонента data URI SVG.
6. [MDN — naturalWidth](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/naturalWidth) — размеры загруженного изображения, отличающиеся от границ контура.
7. [MDN — SVG как изображение](https://developer.mozilla.org/en-US/docs/Web/SVG/Guides/SVG_as_an_image) — ограничения контекста изображения и проверки зависимостей.

Если эмблема начинается с растра, [создайте редактируемый мастер SVG](https://perfectvector.com/ru/image-to-vector), проверьте контуры и границы исходника, затем сравните contain и cover в собственной компоновке узлов.

## Explore

- [Read the HTML article](https://perfectvector.com/ru/blog/cytoscape-svg-node-artwork)
- [Маркеры SVG в Leaflet: совместите кончик с iconAnchor](https://perfectvector.com/ru/blog/leaflet-svg-marker-anchor.md)
- [Измеряйте длину контура SVG, не путая масштаб](https://perfectvector.com/ru/blog/measure-svg-path-length.md)
- [Product facts](https://perfectvector.com/product-facts.md)
- [FAQ](https://perfectvector.com/faq.md)
- [Pricing and credits](https://perfectvector.com/pricing.md)
