Leaflet 1.x.x vs Openlayers 4.x.x. Часть 2. Как рисуются карты
В прошлой статье обещал, что эта будет про сообщества и плагины, но потом решил, что правильней будет сначала рассказать о том, как в данных фреймворках рисуются карты. Начну с Openlayers, потом Leaflet, потом его плагины.
Сначала общее и банальное: оба фреймворка при действиях пользователя изменяют внутренне состояние карты ( или внутреннее состояние изменятся само от callback или по таймеру ), а оно уже даёт команду на перерисовку.
Как рисует openlayers
Openlayers использует два варианта рисования — Canvas и WebGL ( DOM рендер для тайлов и изображений был удален из современной 3-й версии). Компонент map создает div, в котором и трудятся два этих рендера. Сильно упрощенная последовательность вызовов примерно такая:
- В компоненте карты вызывается функция renderFrame
- Определяются слои, которые видимы на данном масштабе
- Каждый из видимых слоев рисует своим рендером изображение. Помимо разделения на по типам драйверов (canvas и webgl), далее рендеры делятся еще и по типам слоев (ol.renderer.canvas.TileLayer, ol.renderer.canvas.VectorLayer и тд).
- К полученным изображениям слоев добавляется прозрачность, трансформации и вырезание ( clip, если есть) и они все рисуются в общем контексте карты.
Оба рендера работают неплохо, однако, если переключитесь на webgl, то стоит помнить, что ресурсы (например картинки тайлов) нужно будет пускать через прокси, иначе получите:
Uncaught DOMException: Failed to execute 'texImage2D' on 'WebGLRenderingContext': The cross-origin image at may not be loaded.
Если сервер поддерживает cross-origin, а ошибку все равно выдает поставьте в настройках источника изображения crossOrigin: 'anonymous'
Как рисует Leaflet
Для начала, вот хорошая схема классов, которая отображается опять же через leaflet.
Leaflet для рисования карт создает несколько панелей (Pane), которые являются DOM элементами (div), с которыми уже работают слои.
Название | Описание | zIndex |
---|---|---|
mapPane | основная панель содержит в себе все остальные | auto |
tilePane | панель для тайловых слоев | 200 |
overlayPane | панель для векторный слоев | 400 |
shadowPane | панель для теней | 500 |
markerPane | панель для маркеров | 600 |
tooltipPane | панель для подсказок | 650 |
popupPane | панель для появляющихся данных по объектам | 700 |
И тут кроется первая интересная деталь, если в Openlayers нумерация по zIndex сквозная для всех слоев по умолчанию, то в Leaflet, слои получаются сгруппированными. Если вы вдруг хотите, чтобы ваш тайловый слой когда-нибудь был «над» векторным, вам надо или принудительно указывать у конкретного тайлового слоя в options pane: overlay, или если сквозная нумерация нужна у всех слоев, то складывать их все в один. Кстати, можно создавать свой pane и необязательно он должен быть внутри mapPane.
А дальше начинается самое интересное, если в Openlayers для всех слоев, используется одинаковый набор рендеров, то Leaflet, каждый из слоев сам выбирает как и чем ему рисоваться. Например тайловые слои и ImageOverlay рисуются только DOM-элементами (хотя в плагинах есть вариации на тему рисования тайлов с использованием WebGl и Canvas). Для векторных слоев слоев используется SVG или Canvas, если оба поддерживаются браузером, по умолчанию используется SVG.
Особенности рисования в разных плагинах Leaflet
Как я уже сказал, несмотря на то, что из коробки у Leaflet нет webgl рендера, некоторые плагины используют эту технологию. Leaflet.TileLayer.GL, например, создает вместо изображения тайла canvas, в который рисует рендер Webgl. С помощью данного плагина можно с GPUшной производительностью поиграть с пикселями в тайлах. Вот пример раскраски пикселей в тайлах по широте:
Или вот от того же автора Leaflet.GLMarkers позволяет рисовать большие объемы точек на карте (маркеры могут быть анимированы), хотя выглядит кривовато, особенно нерабочая анимация зумирования напрягает.
Бывают тяжелые случаи и у плагинов, которые обслуживаются серьезными компаниями. Например, esri-leaflet в DynamicMapLayer при каждом рефреше создает новый слой ImageOverlay, причем создает его когда загрузилась соответствующая картинка, т.е. порядок слоев на карте постоянно перемешивается, работать с z-index невозможно. Вашему покорному слуге даже пришлось делать улучшенный вариант данного слоя, также там есть переход через 180 меридиан, которого нет в оригинальном плагине.
Еще одна частая проблема: разная поддержка плагинами 2х основных версий leaflet — 0.7 и 1.0. Между ними очень много критических изменений, и плагины могут не работать в конкретной версии. Бывает еще так: один плагин работает только в версии 1.0, а другой нужный нам плагин автор еще не обновил или совсем забил на его обслуживание ( хотя сейчас таких все меньше) и он работает только под старой.
Короче говоря, основная проблема рисования leaflet, то что каждый плагин делает все как ему заблагорассудится, кто-то создает html img, кто-то рисует в canvas, кто-то webgl'ом рисует в canvas в тайл и тд. И дальнейшая работа с этим в комплексе становится проблематичной.
P.S.: Следующая статья будет про источники картографических данных и возможности работы с ними в каждом из фреймворков, а так же финальные выводы о том, какой фреймворк выбрать именно в вашем случае.