Tile-сервер (сервер тайлов) — это сервер, предоставляющий картографические изображения небольшими квадратными фрагментами фиксированного размера. Вместо загрузки всей карты целиком браузер получает только те части, которые необходимы для отображения текущей области просмотра.
В экосистеме Leaflet тайлы являются основным источником визуального представления карты. После создания объекта карты обычно подключается слой тайлов, который становится базовой подложкой:
const map = L.map('map').setView([55.751244, 37.618423], 10);
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
В результате карта начинает запрашивать изображения у tile-сервера и отображать их в соответствующих местах.
Тайл представляет собой квадратное изображение, обычно размером:
Каждый тайл имеет собственные координаты:
Типичный URL тайла выглядит следующим образом:
https://tile.openstreetmap.org/10/618/320.png
Где:
10 → zoom
618 → x
320 → y
Leaflet автоматически вычисляет необходимые координаты и формирует запросы к серверу.
В основе большинства современных веб-карт лежит схема разбиения мира на сетку тайлов.
На нулевом масштабе весь мир представлен одним тайлом:
Zoom 0
+-----+
| |
| |
+-----+
На первом масштабе карта разбивается на четыре части:
Zoom 1
+---+---+
| | |
+---+---+
| | |
+---+---+
На втором масштабе количество тайлов увеличивается до шестнадцати:
Zoom 2
4 × 4 = 16 тайлов
Общее количество тайлов вычисляется по формуле:
2^z × 2^z
Например:
| Zoom | Тайлов по оси | Всего тайлов |
|---|---|---|
| 0 | 1 | 1 |
| 1 | 2 | 4 |
| 2 | 4 | 16 |
| 3 | 8 | 64 |
| 10 | 1024 | 1 048 576 |
| 18 | 262 144 | 68 719 476 736 |
Поэтому хранение карты в виде отдельных фрагментов значительно эффективнее загрузки огромных изображений.
В Leaflet за работу с тайлами отвечает класс
L.TileLayer.
Базовый синтаксис:
L.tileLayer(urlTemplate, options)
Пример:
L.tileLayer(
'https://tile.openstreetmap.org/{z}/{x}/{y}.png'
);
Плейсхолдеры:
| Переменная | Назначение |
|---|---|
{z} |
Масштаб |
{x} |
Координата X |
{y} |
Координата Y |
Leaflet заменяет их реальными значениями при каждом запросе.
Самый распространённый источник картографических тайлов:
L.tileLayer(
'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
{
attribution:
'© OpenStreetMap contributors'
}
).addTo(map);
Особенности:
Атрибуция обязательна, поскольку данные предоставляются сообществом OpenStreetMap.
Большинство поставщиков карт требуют отображения информации об авторстве.
Пример:
L.tileLayer(url, {
attribution:
'© OpenStreetMap contributors'
});
Несколько источников:
L.tileLayer(url, {
attribution:
'© OpenStreetMap contributors | Tiles by ExampleMaps'
});
Атрибуция автоматически отображается в правом нижнем углу карты.
Современные браузеры блокируют смешанный контент.
Неправильно:
http://tile.server.com/{z}/{x}/{y}.png
Если сайт открыт через HTTPS, карта может не загрузиться.
Правильно:
https://tile.server.com/{z}/{x}/{y}.png
Использование защищённого соединения стало стандартом для всех современных tile-серверов.
Минимальный масштаб:
L.tileLayer(url, {
minZoom: 5
});
Ниже пятого уровня тайлы не будут запрашиваться.
Максимальный масштаб:
L.tileLayer(url, {
maxZoom: 19
});
При достижении максимального уровня увеличение прекращается.
Размер одного тайла:
L.tileLayer(url, {
tileSize: 256
});
или
L.tileLayer(url, {
tileSize: 512
});
Значение должно соответствовать настройкам сервера.
Прозрачность слоя:
L.tileLayer(url, {
opacity: 0.6
});
Диапазон:
0.0 — полностью прозрачный
1.0 — полностью непрозрачный
Порядок наложения:
L.tileLayer(url, {
zIndex: 100
});
Чем больше значение, тем выше слой располагается относительно других слоёв.
Ограничение области действия тайлов:
L.tileLayer(url, {
bounds: [
[40, -20],
[70, 40]
]
});
Тайлы будут отображаться только внутри указанных координат.
Многие tile-серверы используют несколько поддоменов:
a.tile.server.com
b.tile.server.com
c.tile.server.com
В Leaflet:
L.tileLayer(
'https://{s}.tile.server.com/{z}/{x}/{y}.png',
{
subdomains: ['a', 'b', 'c']
}
);
Или сокращённая запись:
subdomains: 'abc'
Браузер распределяет запросы между серверами, что ускоряет загрузку большого количества тайлов.
Устройства с высокой плотностью пикселей требуют более детализированных изображений.
Leaflet позволяет автоматически использовать Retina-тайлы:
L.tileLayer(url, {
detectRetina: true
});
При наличии соответствующей поддержки сервер может выдавать тайлы повышенного разрешения.
Преимущества:
Часто требуется выбор различных картографических стилей.
Создание нескольких слоёв:
const osm = L.tileLayer(
'https://tile.openstreetmap.org/{z}/{x}/{y}.png'
);
const satellite = L.tileLayer(
'https://server.com/satellite/{z}/{x}/{y}.jpg'
);
osm.addTo(map);
Добавление переключателя:
L.control.layers({
"OpenStreetMap": osm,
"Satellite": satellite
}).addTo(map);
Пользователь сможет менять подложку без перезагрузки страницы.
Различные tile-серверы могут предоставлять разные визуальные оформления:
Пример подключения тёмного стиля:
L.tileLayer(
'https://tiles.example.com/dark/{z}/{x}/{y}.png'
);
С точки зрения Leaflet работа с любым стилем происходит одинаково — меняется только URL.
Tile-серверы обычно имеют ограничения:
Плохая практика:
for(let i = 0; i < 100; i++) {
L.map(`map${i}`);
}
Такой код способен создать огромное количество запросов.
Хорошая практика:
После загрузки тайл сохраняется браузером.
Преимущества:
При перемещении карты Leaflet повторно использует уже загруженные изображения, если они присутствуют в кэше.
Если тайл не удалось загрузить, возможно отображение специального изображения.
L.tileLayer(url, {
errorTileUrl: 'images/error.png'
});
Причины ошибок:
Начало загрузки тайла:
tileLayer.on('tileloadstart', function(e) {
console.log('Загрузка');
});
Тайл успешно загружен:
tileLayer.on('tileload', function(e) {
console.log('Готово');
});
Ошибка загрузки:
tileLayer.on('tileerror', function(e) {
console.log('Ошибка');
});
Загружены все необходимые тайлы:
tileLayer.on('load', function() {
console.log('Карта готова');
});
Такие события часто используются для индикаторов загрузки.
В крупных проектах нередко разворачивается собственная инфраструктура.
Причины:
URL собственного сервера выглядит аналогично:
L.tileLayer(
'https://maps.company.com/{z}/{x}/{y}.png'
);
Для Leaflet источник тайлов не имеет значения, если сервер поддерживает стандартную схему координат.
Существует два популярных формата адресации тайлов.
Используется большинством современных сервисов:
/{z}/{x}/{y}.png
Координата y увеличивается сверху вниз.
Использует обратную нумерацию по оси Y:
/{z}/{x}/{y}.png
Визуально URL одинаков, но система координат отличается.
Для TMS в Leaflet:
L.tileLayer(url, {
tms: true
});
Leaflet автоматически преобразует координаты.
По умолчанию карта может бесконечно повторяться по горизонтали.
Это достигается за счёт циклического отображения тайлов.
Отключение:
L.tileLayer(url, {
noWrap: true
});
Теперь карта не будет повторяться за пределами мировых границ.
Дополнительно можно запретить перемещение за пределы определённой области:
const bounds = [
[85, -180],
[-85, 180]
];
map.setMaxBounds(bounds);
Это особенно полезно для карт отдельных государств, регионов или корпоративных проектов.
На быстродействие карты влияют:
Наиболее распространённые рекомендации:
Процесс отображения карты состоит из нескольких этапов:
1. Изменение масштаба или положения карты
↓
2. Вычисление координат x/y/z
↓
3. Формирование URL
↓
4. Запрос к tile-серверу
↓
5. Получение изображения
↓
6. Кэширование
↓
7. Отображение на карте
Понимание этого механизма необходимо для диагностики проблем, настройки производительности и построения собственных картографических решений на основе Leaflet.