Canvas источник

MapLibre GL JS поддерживает несколько типов источников данных (sources), среди которых выделяется canvas-источник — механизм подключения произвольного HTML5 Canvas как растрового слоя внутри карты. Этот тип источника позволяет интегрировать динамически рисуемую графику непосредственно в систему рендеринга карты и синхронизировать её с географическими координатами.

Canvas-источник функционирует как промежуточный слой между процедурной графикой браузера и WebGL-пайплайном карты. В отличие от тайловых источников (vector/raster tiles), он не разбивает данные на тайлы, а использует единое изображение, обновляемое в реальном времени.


Место Canvas-источника в архитектуре источников

В MapLibre GL JS источники данных делятся на несколько категорий:

  • векторные тайлы (vector tiles)
  • растровые тайлы (raster tiles)
  • изображения (image source)
  • видео (video source)
  • canvas source

Canvas-источник занимает особое положение, поскольку:

  • не опирается на сетку тайлов
  • не требует серверной агрегации данных
  • обновляется через API браузера Canvas 2D или WebGL Canvas
  • существует как единый динамический растр

Основная идея заключается в том, что Canvas выступает как «генератор текстуры», которая затем проецируется на карту с привязкой к географическому прямоугольнику.


Объявление canvas source

Canvas-источник задаётся через метод addSource, где указывается тип canvas и параметры привязки:

map.addSource('dynamic-canvas', {
  type: 'canvas',
  canvas: 'myCanvas',
  animate: true,
  coordinates: [
    [-80.425, 37.78],
    [-71.516, 37.78],
    [-71.516, 30.89],
    [-80.425, 30.89]
  ]
});

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

  • canvas — идентификатор HTMLCanvasElement или сам элемент
  • coordinates — географические координаты четырёх углов изображения
  • animate — флаг постоянного обновления источника

Canvas может передаваться как строковый ID DOM-элемента или как объект HTMLCanvasElement.


Географическая привязка Canvas

Canvas-источник всегда отображается как накладываемая текстура, привязанная к четырём координатам:

coordinates: [
  [west, north],
  [east, north],
  [east, south],
  [west, south]
]

Эта структура задаёт:

  • верхний левый угол
  • верхний правый угол
  • нижний правый угол
  • нижний левый угол

Таким образом формируется произвольный четырёхугольник в географическом пространстве, на который проецируется изображение canvas.

Особенности проекции

  • искажение компенсируется WebGL-шейдерами
  • Canvas растягивается в перспективе карты
  • поддерживается вращение и наклон карты
  • слой ведёт себя как геопривязанная текстура

Режим анимации

Параметр animate: true активирует постоянное обновление источника. В этом режиме MapLibre GL JS регулярно перерисовывает canvas и обновляет текстуру в GPU.

Типичный сценарий:

const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');

function draw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  ctx.fillStyle = 'rgba(255, 0, 0, 0.5)';
  ctx.beginPath();
  ctx.arc(Math.random() * canvas.width, Math.random() * canvas.height, 20, 0, Math.PI * 2);
  ctx.fill();

  requestAnimationFrame(draw);
}

draw();

При включённом animate MapLibre автоматически синхронизирует обновления canvas с рендерингом карты, без необходимости вручную вызывать обновление источника.


Обновление данных и жизненный цикл

Canvas-источник не работает как статическая текстура. Его жизненный цикл связан с DOM и состоянием карты.

Обновление содержимого

При изменении содержимого canvas возможны два режима:

  • автоматическое обновление (animate: true)
  • ручное обновление через map.getSource().load() или пересоздание источника

Пример принудительного обновления

const source = map.getSource('dynamic-canvas');
source.play(); // в зависимости от реализации может активировать цикл обновления

(в большинстве случаев достаточно включённой анимации и requestAnimationFrame внутри canvas-логики)


Использование Canvas как динамического слоя

Canvas-источник применяется для генерации визуальных данных на лету:

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

В отличие от WebGL-слоёв, логика остаётся в JavaScript Canvas API, что упрощает реализацию алгоритмов.


Производительность и ограничения

Canvas-источник имеет ряд особенностей, влияющих на производительность:

Стоимость рендеринга

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

Ограничения геометрии

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

Рекомендации по нагрузке

  • ограничение разрешения canvas до необходимого минимума
  • использование requestAnimationFrame
  • минимизация операций внутри цикла рисования
  • отключение анимации при статичных данных

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

Canvas-источник может использоваться в комбинации с другими слоями:

  • fill-layer поверх canvas для маскирования
  • line-layer для контуров поверх динамических данных
  • symbol-layer для подписей

Слои MapLibre GL JS рендерятся поверх canvas-источника в зависимости от порядка добавления и z-index.


Привязка к динамическим координатам

Canvas можно перемещать по карте путём обновления координат источника:

map.getSource('dynamic-canvas').setCoordinates([
  [lng1, lat1],
  [lng2, lat2],
  [lng3, lat3],
  [lng4, lat4]
]);

Это позволяет:

  • перемещать слой вместе с объектами карты
  • реализовывать «плавающие» визуализации
  • синхронизировать canvas с движением камеры

Практическая модель работы

Внутренняя схема работы canvas-источника:

  1. Canvas рисуется в 2D контексте
  2. Canvas передаётся как текстура WebGL
  3. MapLibre проецирует текстуру на географический квад
  4. GPU выполняет трансформацию под текущий viewport
  5. При обновлении canvas текстура инвалидируется

Частные сценарии применения

Динамические визуализации

Canvas-источник часто используется для:

  • потоков транспорта
  • анимации частиц (ветер, дым)
  • симуляций распределения плотности

Пользовательская аналитика

  • построение heatmap без серверной агрегации
  • локальная обработка данных в браузере

Интерактивные редакторы

  • рисование поверх карты
  • географические аннотации
  • пользовательские схемы маршрутов

Особенности интеграции с WebGL контекстом карты

Canvas-источник не конфликтует с WebGL-рендерингом MapLibre GL JS, однако:

  • работает как текстура в общем WebGL pipeline
  • требует синхронизации кадров при анимации
  • зависит от производительности основного thread

При высокой нагрузке возможна деградация FPS карты, поскольку CPU и GPU делят ресурсы между картой и canvas-логикой.


Поведение при масштабировании и вращении карты

Canvas-слой:

  • масштабируется вместе с картой
  • поворачивается при rotation bearing
  • искажается при tilt (pitch)
  • сохраняет географическую привязку независимо от zoom уровня

Это делает его эквивалентом геопривязанной текстуры с перспективной трансформацией.