Canvas source представляет собой тип источника данных, который использует HTMLCanvasElement как динамическую текстуру для отображения на карте. В отличие от растровых тайлов или векторных данных, canvas source позволяет интегрировать произвольную 2D-графику, генерируемую в реальном времени, непосредственно в систему рендеринга карты.
Ключевая особенность заключается в том, что содержимое canvas не фиксировано и может обновляться на каждом кадре или по событию, что делает этот тип источника удобным для визуализаций, симуляций и пользовательских графических слоёв.
Canvas source интегрируется в систему стилей Mapbox GL JS как обычный источник данных и может использоваться совместно с любыми слоями, поддерживающими растровое отображение.
Источник типа canvas задаётся через map.addSource:
map.addSource('dynamic-canvas', {
type: 'canvas',
canvas: 'myCanvasId',
coordinates: [
[-80.425, 46.437],
[-71.516, 46.437],
[-71.516, 37.936],
[-80.425, 37.936]
],
animate: true
});
Параметры:
"canvas"<canvas>
или его идентификаторCanvas source отображается как текстура, растянутая на четырёхугольник, заданный координатами. Порядок координат строго фиксирован:
Эта схема определяет проекцию canvas на карту и позволяет точно контролировать его географическое положение.
coordinates: [
[lon1, lat1],
[lon2, lat2],
[lon3, lat3],
[lon4, lat4]
]
Неправильный порядок координат приводит к искажению изображения или его зеркальному отображению.
Canvas может быть создан вручную или получен из DOM:
const canvas = document.createElement('canvas');
canvas.width = 512;
canvas.height = 512;
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, 512, 512);
После создания он передаётся в источник:
map.addSource('rect-canvas', {
type: 'canvas',
canvas: canvas,
coordinates: [...]
});
Canvas остаётся обычным HTML-элементом, поэтому любые операции 2D API автоматически отражаются на карте при обновлении источника.
Флаг animate: true включает режим постоянного
перерисовывания. В этом режиме Mapbox GL JS повторно считывает
содержимое canvas и обновляет текстуру на каждом кадре рендера.
map.addSource('animated', {
type: 'canvas',
canvas: canvas,
coordinates: [...],
animate: true
});
Применение:
Без animate обновление происходит только при явном
изменении источника или вызове обновления слоя.
Mapbox GL JS не управляет содержимым canvas напрямую. Обновление осуществляется через стандартный 2D контекст:
const ctx = canvas.getContext('2d');
function render() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'blue';
ctx.fillRect(Math.random() * 512, 100, 50, 50);
requestAnimationFrame(render);
}
render();
При включённом animate изменения автоматически
отражаются на карте.
Canvas source обычно используется через слой типа
raster:
map.addLayer({
id: 'canvas-layer',
type: 'raster',
source: 'dynamic-canvas'
});
Слой raster интерпретирует canvas как текстуру и отображает её без дополнительных преобразований.
Canvas source требует строго четыре координаты. Это означает:
При необходимости сложных форм требуется либо пересоздание источника, либо использование других типов (например, geojson + fill-extrusion).
Для изменения положения canvas используется
setCoordinates:
const source = map.getSource('dynamic-canvas');
source.setCoordinates([
[-81, 47],
[-70, 47],
[-70, 37],
[-81, 37]
]);
Это позволяет перемещать текстуру без пересоздания canvas.
Canvas source является ресурсозатратным элементом при активной анимации. Основные факторы влияния:
Высокое разрешение canvas увеличивает детализацию, но напрямую влияет на GPU и память.
Рекомендуется:
requestAnimationFrame вместо
setIntervalCanvas source не автоматически адаптируется к devicePixelRatio. При высоких DPI экранах может наблюдаться размытость.
Решение:
const dpr = window.devicePixelRatio;
canvas.width = 512 * dpr;
canvas.height = 512 * dpr;
ctx.scale(dpr, dpr);
Это обеспечивает чёткое отображение на Retina-экранах.
Canvas source жёстко привязан к географическим координатам. При изменении:
текстура трансформируется вместе с картой, сохраняя географическую привязку.
Однако сам canvas не «знает» о камере и не адаптирует своё содержимое под перспективу.
Canvas source применяется в задачах, где требуется динамическая визуализация поверх карты:
Несмотря на гибкость, canvas source имеет ряд архитектурных ограничений:
Canvas source является по сути «чёрным ящиком», который WebGL интерпретирует как текстуру.
Canvas source часто сравнивается с другими типами источников:
Главное отличие заключается в том, что canvas source остаётся программно управляемым объектом, а не статическим ресурсом.
Внутри Mapbox GL JS canvas source преобразуется в WebGL-текстуру. При каждом обновлении выполняется:
Это делает canvas source мостом между 2D Canvas API и WebGL рендерингом карты.
При построении сложных систем важно учитывать:
Оптимальная стратегия — создание одного canvas source и обновление его содержимого без удаления источника из карты.
Удаление выполняется стандартно:
map.removeSource('dynamic-canvas');
После удаления связь с canvas разрывается, но сам DOM-элемент остаётся доступным и может быть переиспользован.