Тайлификация данных (tiling) — процесс разбиения пространственной информации на множество небольших фрагментов, называемых тайлами (tiles), которые загружаются и отображаются по мере необходимости. В основе большинства современных веб-карт, включая решения на базе Mapbox GL JS, лежит именно тайловая архитектура.
При работе с крупными наборами геоданных отображение всего массива объектов одновременно приводит к значительным затратам памяти, увеличению времени загрузки и снижению производительности браузера. Тайлификация позволяет передавать только ту часть данных, которая соответствует текущей области просмотра карты.
Вместо единого файла с миллионами объектов карта получает десятки или сотни небольших блоков данных, каждый из которых отвечает за конкретный участок территории и уровень масштабирования.
Основные задачи тайлификации:
Например, если карта содержит информацию обо всех дорогах мира, нет необходимости загружать данные Африки при просмотре территории Японии. Благодаря тайлам клиент получает только нужный набор данных.
В Mapbox GL JS используется система координат Web Mercator, в которой поверхность Земли проецируется на квадратную плоскость.
Эта плоскость последовательно делится на квадраты.
На нулевом уровне масштабирования существует только один тайл:
z=0
+---------+
| 0 |
+---------+
На первом уровне масштабирования карта делится на четыре части:
z=1
+----+----+
|0,0 |1,0 |
+----+----+
|0,1 |1,1 |
+----+----+
На втором уровне масштабирования количество тайлов увеличивается до шестнадцати:
z=2
4 × 4 тайла
Общее количество тайлов вычисляется по формуле:
2^z ^z = 4^z
где:
z — уровень масштабирования;2^z;2^z.Например:
| Zoom | Количество тайлов |
|---|---|
| 0 | 1 |
| 1 | 4 |
| 2 | 16 |
| 3 | 64 |
| 10 | 1 048 576 |
По мере увеличения масштаба количество тайлов растёт экспоненциально.
Каждый тайл имеет три координаты:
z/x/y
где:
z — уровень масштабирования;x — положение по горизонтали;y — положение по вертикали.Пример:
12/2154/1348
Это означает:
Такая схема применяется практически во всех картографических сервисах.
Mapbox GL JS способен работать с двумя основными типами тайлов.
Растровый тайл представляет собой готовое изображение.
Обычно используются форматы:
Подобный тайл уже содержит отрисованную карту.
map.addSource('satellite', {
type: 'raster',
tiles: [
'https://server.com/{z}/{x}/{y}.png'
],
tileSize: 256
});
Преимущества:
Недостатки:
Векторный тайл содержит не изображение, а геометрические объекты:
Отрисовка выполняется непосредственно в браузере средствами WebGL.
map.addSource('roads', {
type: 'vector',
url: 'mapbox://examples.roads'
});
Преимущества:
Недостатки:
Стандарт Mapbox Vector Tile (MVT) является основой большинства проектов на Mapbox GL JS.
Внутри одного тайла могут находиться:
Tile
├─ roads
├─ buildings
├─ water
├─ landuse
└─ places
Каждый слой содержит набор геометрий и атрибутов.
Пример структуры:
{
"id": 1,
"type": "Feature",
"properties": {
"name": "Main Street",
"class": "primary"
}
}
При загрузке тайла браузер получает бинарный protobuf-файл и преобразует его в графические примитивы.
Существует два наиболее распространённых размера:
256 × 256 пикселей
512 × 512 пикселей
Mapbox по умолчанию использует:
512 × 512
Пример настройки:
map.addSource('raster-source', {
type: 'raster',
tiles: [
'https://server.com/{z}/{x}/{y}.png'
],
tileSize: 512
});
Увеличенный размер тайла уменьшает количество запросов к серверу, однако каждый отдельный файл становится тяжелее.
Геометрия объектов часто пересекает границы тайлов.
Например:
+-----+-----+
| | |
|=====|=====|
| | |
+-----+-----+
Если дорога проходит через два соседних тайла, при отсутствии дополнительных данных на границе могут возникать разрывы.
Для решения проблемы используется буфер (buffer).
Во время генерации векторного тайла в него включаются объекты, выходящие за пределы основной области.
Tile Area
+-------------+
| Buffer |
| +---------+ |
| | Content | |
| +---------+ |
| |
+-------------+
Благодаря этому линии и полигоны отображаются непрерывно.
Одни и те же данные обычно существуют в нескольких вариантах детализации.
Для мелких масштабов:
Мир
└─ только основные объекты
Для крупных масштабов:
Город
├─ улицы
├─ дома
├─ дорожные знаки
├─ POI
└─ адреса
Процесс упрощения геометрии называется генерализацией.
Например, сложный полигон с тысячами вершин может быть преобразован в упрощённую форму для отображения на небольших масштабах.
Это существенно уменьшает размер тайлов.
GeoJSON представляет собой единый набор данных.
Пример:
map.addSource('cities', {
type: 'geojson',
data: 'cities.geojson'
});
При небольшом количестве объектов этого достаточно.
Однако крупный файл может содержать:
В таких случаях GeoJSON становится неэффективным.
Типичный путь оптимизации:
GeoJSON
↓
Tile Generator
↓
MVT Tiles
↓
Mapbox GL JS
После тайлификации карта начинает загружать только необходимые участки данных.
Mapbox GL JS способен самостоятельно разбивать GeoJSON на внутренние тайлы.
map.addSource('earthquakes', {
type: 'geojson',
data: earthquakesData
});
После загрузки источник проходит несколько этапов:
Такой подход удобен для небольших и средних наборов данных.
Для больших объёмов данных чаще применяется предварительная генерация тайлов на сервере.
Схема выглядит следующим образом:
PostGIS
↓
Tippecanoe
↓
MVT
↓
CDN
↓
Mapbox GL JS
Преимущества:
Одним из самых популярных инструментов является Tippecanoe.
Пример создания набора тайлов:
tippecanoe \
-o cities.mbtiles \
-z14 \
-Z0 \
cities.geojson
Параметры:
-o — выходной файл;-z — максимальный zoom;-Z — минимальный zoom.Результатом становится база MBTiles, содержащая набор векторных тайлов.
Подключение векторных тайлов:
map.addSource('cities', {
type: 'vector',
tiles: [
'https://tiles.example.com/cities/{z}/{x}/{y}.pbf'
]
});
Добавление слоя:
map.addLayer({
id: 'cities-layer',
type: 'circle',
source: 'cities',
'source-layer': 'cities',
paint: {
'circle-radius': 4,
'circle-color': '#ff0000'
}
});
Здесь:
После загрузки тайлы сохраняются в памяти браузера.
Повторный просмотр области карты обычно не требует повторной загрузки данных.
Сценарий работы:
Пользователь перемещает карту
↓
Тайл загружается
↓
Тайл сохраняется в кэше
↓
Повторный просмотр
↓
Использование локальной копии
Кэширование существенно уменьшает сетевой трафик и ускоряет навигацию.
Вся система тайлификации образует древовидную структуру.
z=0
|
+-- z=1
|
+-- z=2
|
+-- z=3
Каждый тайл верхнего уровня имеет четыре дочерних тайла следующего масштаба.
Такую структуру называют пирамидой тайлов (Tile Pyramid).
Она позволяет быстро определять, какие данные необходимо загрузить для конкретного масштаба и области просмотра.
Грамотно организованная тайловая структура обеспечивает:
Именно тайлификация делает возможным отображение огромных геопространственных массивов в браузере в режиме реального времени, сохраняя высокую производительность Mapbox GL JS даже при работе со сложными векторными слоями и многомиллионными коллекциями объектов.