SDF иконки

Векторная отрисовка символов и пиктограмм в MapLibre GL JS опирается на концепцию Signed Distance Field (SDF), позволяющую превращать растровые изображения иконок в масштабируемые и стилизуемые графические примитивы без потери резкости. Это фундаментальный механизм символического слоя (symbol layer), обеспечивающий единообразное отображение значков при любом масштабе карты.

Принцип Signed Distance Field

SDF представляет собой способ кодирования изображения, при котором каждый пиксель хранит не цвет, а расстояние до ближайшей границы фигуры. Значение интерпретируется следующим образом:

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

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

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

SDF-иконки в символическом слое

В MapLibre GL JS SDF применяется через свойство iconSDF в описании слоя symbol. При включении этого режима движок интерпретирует альфа-канал изображения как поле расстояний.

Пример базовой конфигурации слоя:

map.addLayer({
  id: "poi-icons",
  type: "symbol",
  source: "points",
  layout: {
    "icon-image": "marker-15",
    "icon-size": 1.2,
    "icon-sdf": true
  },
  paint: {
    "icon-color": "#2E86AB",
    "icon-halo-color": "#ffffff",
    "icon-halo-width": 1
  }
});

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

Подготовка SDF-спрайтов

Иконки в MapLibre GL JS обычно хранятся в sprite atlas — наборе изображений и JSON-индексе. Для SDF-режима требуется специальная подготовка:

  1. исходные иконки должны быть монохромными (обычно белыми)
  2. генератор спрайтов должен пометить их как SDF
  3. в sprite metadata добавляется флаг sdf: true

Пример фрагмента sprite JSON:

{
  "airport-15": {
    "width": 20,
    "height": 20,
    "x": 0,
    "y": 0,
    "pixelRatio": 1,
    "sdf": true
  }
}

При отсутствии флага sdf движок будет трактовать изображение как обычную текстуру, и свойства icon-color перестанут работать корректно.

Цветовое управление через SDF

Ключевое отличие SDF-иконок заключается в том, что цвет задаётся динамически на GPU.

Основные параметры стилизации:

  • icon-color — основной цвет заливки
  • icon-halo-color — цвет обводки
  • icon-halo-width — толщина обводки
  • icon-opacity — прозрачность

Пример:

paint: {
  "icon-color": [
    "match",
    ["get", "type"],
    "airport", "#ffcc00",
    "hospital", "#ff4d4d",
    "#666666"
  ],
  "icon-halo-color": "#000000",
  "icon-halo-width": 2
}

SDF позволяет применять цветовые выражения без необходимости хранить отдельные версии иконок для каждого состояния.

Масштабирование без потери качества

Обычные растровые иконки при увеличении масштаба становятся размытыми. SDF решает эту проблему за счёт интерпретации границ как функции расстояния.

При увеличении:

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

Это особенно важно при работе с динамическим зумом, где символы могут изменять размер в диапазоне от 0.5× до 4× и выше.

Влияние на производительность

SDF-иконки обрабатываются на уровне шейдеров WebGL. Это переносит значительную часть вычислений на GPU:

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

Однако есть и ограничения:

  • увеличение сложности шейдеров
  • чувствительность к качеству исходного SDF-изображения
  • возможные артефакты при слишком тонких линиях

Поведение при трансформациях

SDF-иконки сохраняют корректное отображение при:

  • вращении карты (icon-rotate)
  • наклоне камеры (pitch)
  • масштабировании (zoom interpolation)
  • динамическом изменении стиля

Пример вращения:

layout: {
  "icon-image": "arrow-15",
  "icon-rotate": ["get", "bearing"],
  "icon-rotation-alignment": "map",
  "icon-sdf": true
}

Ограничения SDF-иконок

Несмотря на гибкость, SDF имеет ряд ограничений:

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

SDF подходит исключительно для символических иконок, логотипов и пиктограмм.

Совместимость с выражениями стилей

SDF-иконки интегрируются с системой выражений MapLibre GL JS, что позволяет динамически изменять их внешний вид:

"icon-color": [
  "case",
  ["boolean", ["feature-state", "selected"], false],
  "#ff0000",
  "#333333"
]

Такой подход позволяет реализовывать интерактивные состояния:

  • выделение объектов
  • фильтрация категорий
  • реакция на события hover/click

Использование в тематических слоях

SDF-иконки широко применяются в слоях:

  • транспортных объектов (остановки, станции)
  • POI (points of interest)
  • аналитических карт
  • навигационных интерфейсов

Пример тематического слоя:

map.addLayer({
  id: "transport",
  type: "symbol",
  source: "transport-data",
  layout: {
    "icon-image": ["get", "icon"],
    "icon-sdf": true,
    "icon-size": [
      "interpolate",
      ["linear"],
      ["zoom"],
      5, 0.6,
      12, 1.2
    ]
  },
  paint: {
    "icon-color": "#1f78b4"
  }
});

Взаимодействие с текстовыми слоями

Symbol layer часто комбинирует иконки и текст. SDF влияет на визуальную согласованность между ними:

  • текст масштабируется отдельно
  • иконки сохраняют чёткость
  • возможна синхронизация размеров через icon-text-fit

Пример:

layout: {
  "icon-image": "label-bg",
  "icon-sdf": true,
  "text-field": ["get", "name"],
  "text-size": 12,
  "icon-text-fit": "both"
}

Генерация качественных SDF-иконок

Ключевые требования к исходным изображениям:

  • высокая контрастность (обычно белый на прозрачном фоне)
  • отсутствие шумов и антиалиасинговых артефактов
  • достаточный padding вокруг формы
  • единый визуальный стиль в наборе иконок

Неправильная подготовка приводит к:

  • “размытым” границам
  • утечке цвета за пределы формы
  • артефактам при зуме

Оптимизация больших наборов иконок

При работе с крупными наборами SDF-иконок используются следующие подходы:

  • агрегация в единый sprite atlas
  • группировка по тематическим слоям
  • минимизация уникальных форм (переиспользование шаблонов)
  • кэширование sprite JSON

Эти меры уменьшают время загрузки и ускоряют первичную отрисовку карты.

Роль SDF в архитектуре рендеринга

Внутри WebGL-конвейера SDF-иконки проходят следующие стадии:

  1. загрузка sprite atlas
  2. декодирование текстуры
  3. интерпретация alpha как distance field
  4. применение шейдерной функции сглаживания
  5. окрашивание через uniform-параметры
  6. компоновка в symbol layer

Такой pipeline обеспечивает стабильную производительность даже при тысячах одновременно отображаемых символов.