SVG иконки

SVG-изображения в CesiumJS не рендерятся напрямую как в DOM или браузерных интерфейсах. Вся сцена работает через WebGL, поэтому любые векторные данные SVG неизбежно проходят стадию растеризации и превращаются в растровые текстуры перед отображением. Это фундаментальное ограничение определяет архитектуру использования иконок в 3D-карте и влияет на производительность, качество и способы интеграции SVG.

CesiumJS не интерпретирует SVG как векторную графику внутри сцены. Вместо этого SVG используется как источник изображения, которое:

  • загружается как ресурс (URL, Blob или Data URI)
  • декодируется браузером
  • преобразуется в bitmap
  • передаётся в WebGL как текстура

Таким образом, итоговая отрисовка всегда растровая, даже если исходник — вектор.

Ключевая особенность:

SVG не сохраняет векторную природу в сцене CesiumJS — он служит лишь форматом источника изображения.

Это означает, что масштабирование после загрузки не увеличивает детализацию, как в классическом SVG в HTML.


SVG как источник иконок для BillboardGraphics

Основной сценарий использования SVG в CesiumJS — иконки маркеров через BillboardGraphics в системе сущностей.

const viewer = new Cesium.Viewer("cesiumContainer");

viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(37.6173, 55.7558),
    billboard: {
        image: "icons/marker.svg",
        width: 32,
        height: 32
    }
});

SVG передаётся как обычный URL. Cesium передаёт его в загрузчик изображения браузера, после чего результат становится текстурой.

Ограничение поведения

При таком подходе:

  • отсутствует динамическая перекраска SVG на уровне вектора
  • невозможно менять отдельные элементы SVG после загрузки
  • масштабирование не улучшает чёткость

Использование Data URI для SVG

SVG может быть встроен прямо в код через Data URI. Это удобно для динамической генерации иконок.

const svg = `
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64">
  <circle cx="32" cy="32" r="30" fill="red"/>
</svg>
`;

const dataUri = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svg);

viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(10, 10),
    billboard: {
        image: dataUri,
        width: 32,
        height: 32
    }
});

Такой подход часто используется для:

  • генерации иконок на лету
  • создания параметрических маркеров
  • избежания сетевых запросов

Загрузка SVG через Cesium.Resource

Cesium предоставляет Cesium.Resource, который управляет загрузкой изображений с учётом кэша и асинхронности.

const resource = Cesium.Resource.fetchImage({
    url: "icons/pin.svg"
});

viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(20, 20),
    billboard: {
        image: resource,
        width: 40,
        height: 40
    }
});

Особенность такого подхода — унифицированный pipeline загрузки ресурсов Cesium, включая:

  • кэширование
  • обработку CORS
  • контроль асинхронного состояния

Цветовая модификация SVG-иконок

CesiumJS не редактирует SVG как DOM-объект, но предоставляет механизмы постобработки уже растеризованного изображения.

Основной инструмент — color, colorBlendMode и colorBlendAmount у BillboardGraphics.

viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(30, 30),
    billboard: {
        image: "icons/arrow.svg",
        color: Cesium.Color.BLUE,
        colorBlendMode: Cesium.ColorBlendMode.REPLACE,
        colorBlendAmount: 1.0
    }
});

Режимы смешивания

  • REPLACE — полная замена цвета текстуры
  • MIX — смешивание исходного изображения с цветом
  • HIGHLIGHT — усиление яркости выбранного оттенка

Эти режимы работают на уровне шейдера, а не SVG.


Ограничения SVG в CesiumJS

Использование SVG сопровождается рядом технических ограничений:

1. Потеря векторной масштабируемости

После загрузки SVG превращается в текстуру фиксированного разрешения.

2. Ограниченная поддержка фильтров

SVG-фильтры (blur, drop-shadow, feGaussianBlur) могут:

  • игнорироваться браузером при рендере в canvas
  • отображаться некорректно в WebGL-текстуре

3. Шрифты

Текст внутри SVG может:

  • заменяться системными шрифтами
  • рендериться с отличиями между платформами

4. Производительность

Частая загрузка SVG увеличивает нагрузку из-за:

  • парсинга XML
  • растеризации
  • создания текстур WebGL

Проблема растеризации и контроль качества

Cesium не управляет процессом преобразования SVG → bitmap напрямую. Итоговое качество зависит от:

  • браузерного движка (Chrome, Firefox)
  • devicePixelRatio
  • исходного размера SVG

Практическое правило:

SVG должен быть рассчитан на конечный размер отображения, а не на масштабирование в CesiumJS.

Пример:

width: 32,
height: 32

SVG желательно создавать с viewBox, соответствующим плотному разрешению.


Использование SVG в комбинации с Entity API

Entity API позволяет централизованно управлять иконками, включая SVG как источник изображения.

const entity = viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(40, 40),
    billboard: {
        image: "icons/hospital.svg",
        width: 48,
        height: 48,
        alignedAxis: Cesium.Cartesian3.UNIT_Z
    }
});

Дополнительно можно управлять поведением:

  • видимостью через show
  • масштабом через scale
  • расстоянием через distanceDisplayCondition

Анимация SVG-иконок через замену текстур

Cesium не анимирует SVG внутри сцены, но поддерживает имитацию анимации через смену изображений.

let frame = 0;
const frames = [
    "icons/a1.svg",
    "icons/a2.svg",
    "icons/a3.svg"
];

viewer.clock.onTick.addEventListener(() => {
    frame = (frame + 1) % frames.length;
    entity.billboard.image = frames[frame];
});

Этот подход используется для:

  • мигающих маркеров
  • эффектов пульсации
  • состояния активности объекта

SVG и альтернативы: Canvas и Sprite Sheet

SVG часто заменяется альтернативными подходами из-за производительности.

Canvas как источник текстуры

const canvas = document.createElement("canvas");
canvas.width = 64;
canvas.height = 64;

const ctx = canvas.getContext("2d");
ctx.fillStyle = "red";
ctx.beginPath();
ctx.arc(32, 32, 20, 0, Math.PI * 2);
ctx.fill();

viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(50, 50),
    billboard: {
        image: canvas
    }
});

Преимущество — полный контроль рендеринга без SVG-парсинга.


Sprite sheet подход

При большом количестве иконок используется атлас:

  • одна текстура
  • множество иконок внутри
  • смещение через imageSubRegion

Это уменьшает количество WebGL-текстур и повышает FPS.


Интеграция SVG с HTML Overlay

SVG может использоваться вне сцены CesiumJS как часть UI-слоя:

  • панель управления
  • легенда карты
  • интерактивные элементы

Такой подход отделяет:

  • 3D сцену (Cesium/WebGL)
  • интерфейс (DOM/SVG)

Это снижает нагрузку на рендеринг сцены и упрощает интерактивность.


Практика построения иконок на основе SVG

Типичная архитектура включает промежуточный слой:

  1. SVG как источник дизайна
  2. конвертация в canvas или PNG
  3. использование результата в Cesium billboards

Пример утилитарного подхода:

function svgToDataUri(svgString) {
    return "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svgString);
}

function createIcon(svg) {
    return {
        image: svgToDataUri(svg),
        width: 32,
        height: 32
    };
}

Поведение SVG при разных масштабах сцены

В CesiumJS масштабирование сцены не влияет на пиксельную плотность иконок напрямую.

Ключевые параметры:

  • scale — масштаб billboard
  • pixelOffset — смещение
  • eyeOffset — смещение в 3D пространстве
billboard: {
    image: "icons/point.svg",
    scale: 1.5,
    pixelOffset: new Cesium.Cartesian2(10, -10)
}

При увеличении масштаба карты SVG не становится «детальнее», так как он уже растеризован.


Типичные архитектурные ошибки при работе со SVG

  • использование слишком сложных SVG с фильтрами и градиентами
  • загрузка SVG в больших количествах без кэширования
  • попытка динамически изменять внутреннюю структуру SVG после загрузки
  • отсутствие фиксации размера viewBox

Оптимизационные стратегии

  • упрощение SVG до базовых фигур
  • предварительная оптимизация через minify
  • кэширование загруженных ресурсов
  • замена SVG на PNG при массовом рендере маркеров
  • использование атласов вместо отдельных файлов

SVG в CesiumJS функционирует не как векторный элемент сцены, а как промежуточный формат текстурирования, интегрированный в WebGL-пайплайн через стандартные механизмы загрузки изображений и entity-систему билбордов, что определяет его поведение, ограничения и оптимальные сценарии применения.