Мне всегда нравился код Openlayers 2, он был максимально академично написан и документирован, разобраться в его коде и стать соавтором или написать плагин было достаточно легко.
Код 3-й версии и последующих также хорошо написан и документирован, но есть одно «но» — написан с использованием Google Closure Compiler и без использования ES6. Это весьма занятная штука, вот, например, размер самих библиотек:
Фреймворк | Сборка | Исходные файлы |
---|---|---|
Leaflet 1.0.3 | 144 кб | 410 кб (90 файлов) |
Openlayers 4.1.1 | 511 кб | 3.1 мб (300 файлов) |
Видно, что Сlosure Сompiler в 2+ раза эффективней сжимает исходные файлы, чем механизм Leaflet. Также предоставляет удобный механизм использования пространств имен при разработке, а не «эти ваши» import ‘../../../../src’ в ES6.
На этом все преимущества Google Closure заканчиваются (мое субъективное мнение). Дальше начинаются некоторые страдания, связаны они в основном с тем, что в сборках имена всех членов класса кроме публичных «оптимизируются» до 1-2 букв. Например, вам нужно написать потомок класса ol.source.Image под ваш источник данных, и вы можете работать только с публичными свойствами и методами. Достучаться до приватных членов класса, как и до абстрактных классов родителей, будет проблематично. Есть только один внятный вариант — делать свои сборки Openlayers (авторы OL предлагают использовать именно этот вариант), а делать плагины «рядом», не влезая в основную библиотеку, получится не очень удобно. Однако, внутри сборки Openlayers есть почти все что нужно для создания гис, даже сторонние провайдеры векторных и растровых данных (Esri например), и вероятность написания чего-либо самому или поиск плагина для большинства систем достаточно мала.
Leaflet изначально задумывался по другому принципу. В самой библиотеке есть необходимый минимум, для всего остального — плагины. Код следует этому принципу. В начале он был правда не очень документирован, комментариев не было совсем, потом появились заглавия в каждом классе, сейчас уже для всех публичных методов и свойств класса есть образцово-показательные описания и примеры использования. Код написан с использованием ES6 (пока используется только модульная система). Соответсвенно максимально удобно как создавать свои сборки Leaflet, так и писать расширения для него, авторы рекомендуют последнее.
В статье хотел показать простой пример доработки одного и второго фреймоворка на примере создания тайлового слоя с нестандартной тайловой сеткой, точка отсчета тайлов не в левом-верхнем углу, а посередине сетки (да, и такое встречается). Для Leaflet плагин выглядел примерно бы так:
export var CenterOriginTileLayer = TileLayer.extend({
getTileUrl: function (coords) {
// здесь идут простые математические действия по сдвигу координат тайла в центр сетки
// и возвращание URL для данного тайла
}
});
Но тут я внезапно понял, что для тайлового источника (ol.source.XYZ) в Openlayers есть свойство типа ol.tilegrid.TileGrid, в котором, в свою очередь, есть свойство origin — те самые координаты центра сетки. Короче говоря, в Openlayers есть все, и кодить даже не пришлось бы.
Итак, если оценивать с точки зрения кода, при прочих равных, что выбрать? Если вы понимаете, что и в Openlayers и в Leaflet (+плагины) нет готового, нужного вам функционала и придется засучив рукава писать дополнения или даже делать кастомную сборку — выбирайте Leaflet. Он проще и его легче интегрировать в ваш проект. Если функционала и там и там вам хватает, то в вопросе выбора надо руководствоваться другими условиями.
В следующей статье разберу сообщества разработчиков и расширения для данных фреймворков.
Комментарии (16)
prostofilya
29.06.2017 12:34+2Только разогнался и статья закончилась, эх. Можно было и побольше, зачем делить на столь мелкие.
SergeyVoyteshonok
29.06.2017 14:14Согласен с вами, но последующие 2 статьи про плагины, фишки и выводы будут объемней, а моя лень затянет написание такой длинной статьи на бесконечное время. Поэтому решил подробить. Сейчас думаю: может еще рассказать как рендеры у них работают.
dom1n1k
29.06.2017 14:00+2Лично я не вижу для себя весомых преимуществ в «академичности» OL. Это совершенно абстрактное достоинство, которое на практике выливается в банальную многословность. На каждый чих у них объект, каждый объект нужно конструировать.
Для иллюстрации приведу минимальный код, который нужен чтобы просто показать карту. Ничего с ней не делать — просто создать и показать один тайловый слой. Почувствуйте разницу, как говорится.
Код// Leaflet var map1 = L.map('map1', { center: [55.8, 37.6], zoom: 12, }); L.tileLayer('http://sometileserver.com/{z}/{x}/{y}.png', { attribution: '© <a href="http://sometileserver.com">sometileserver.com</a>', }) .addTo(map1); // OpenLayers var map2 = new ol.Map({ target: 'map2', layers: [ new ol.layer.Tile({ source: new ol.source.XYZ({ url: 'http://sometileserver.com/{z}/{x}/{y}.png', attributions: new ol.Attribution({ html: '© <a href="http://sometileserver.com">sometileserver.com</a>', }), }), }) ], view: new ol.View({ center: ol.proj.fromLonLat([37.6, 55.8]), zoom: 12, }), });
SergeyVoyteshonok
29.06.2017 14:19+1Ну это пока вы в «мейнстриме» держитесь, а как только шаг вправо, шаг влево, начинаются нюансы. Возьмите коническую проекцию, да разных плагинов, которые друг с другом не работают, вот тут Леафлет бибикая уезжает в кювет, но об этом в следующий раз. Так что, не все так однозначно.
fiskus_boulder
Очень странное желание. Приватные члены сделаны приватными, потому что они в будущем могут измениться, и полагаться на них нельзя.
SergeyVoyteshonok
В рамках обычных ООП-шных языков вы будете правы. Но в JS технически все члены класса публичные, и разделение их на приватные, защищенные и публичные условно. В OL у некоторых свойств ( в комментах к ним для jsdoc) стоит модификатор protected — т.е. доступ из потомков предполагается. Я не говорю здесь про доступ из других классов к приватным методам и свойствам, я говорю про доступ из потомков.
fiskus_boulder
Мне кажется, что если разработчик использует нотацию приватных членов (в Closure или в Typescript), то он воспринимает отсутсвие в js приватных свойств, как недостаток и решает его с помощью компилятора/транспайлера. Скрытие данных или реализации с помощью приватных свойств и методов даёт разработчику преимущество не думать об обратной совместимости, когда он захочет их поменять.
Насчёт
@protected
не понял, там в коде есть@protected
и@private
у одних и тех же свойств? Я думаю, что это ошибка.SergeyVoyteshonok
Из потомков нельзя достучаться даже до членов классов которые помечены как protected, т.е. предполагается доступ к ним.
fiskus_boulder
Я код OpenLayers не модифицировал, но с Closure Compiler/Library работал плотно, и у меня этой проблемы не было. Возможно, есть какие-то особенности, про которые я не знаю.
SergeyVoyteshonok
Вот вы-то мне и нужны ))) Может быть я что-то не понимаю, вам вопрос: могу ли я нормально наследоваться с доступом к членам protected и абстрактным классам, если код уже собран? и работаю я с ним уже после Closure Compiler.
fiskus_boulder
Я все такие телодвижения делал до сборки, так что не смогу помочь, к сожалению. И использовал Closure как программист-пользователь, т.е. не настраивал окружение.
Если вы это будете делать средствами javascripta, то, думаю, сможете. Ведь собранный код — это javascript, и там нет
@protected
,@abstract
,@private
и т.д.Лично я на вашем месте попробовал бы typescript, с ним должно стать всё намного проще (например, https://stackoverflow.com/a/40732068/8159386)
poxvuibr
Во-первых, если из-за технических ограничений разработчик не может сделать настоящий приватный член, и поэтому просто помечает его, как приватный, он как раз и имеет в виду, что полагаться на него нельзя и вообще трогать его нельзя. Так что желание достучаться до приватных членов класса — всё ещё странное.
Во-вторых в JS технически нет проблем с тем, чтобы сделать приватные члены класса. И добраться до них, в отличии от какой-нибудь джавы, будет вообще нереально.
SergeyVoyteshonok
Под словом «приватные», я больше имел ввиду не публичные.
Простой пример по коду Leaflet.
Есть класс Layer, у него есть свойство _map, судя по "_" оно не публичное.
Есть класс наследник — LayerGroup, он использует свойство this._map от потомка. Т.е. по сути своей оно защищенное (protected), объявлено как приватное, но фактически оно публичное, т.к. к нему можно обратится извне.
poxvuibr
Так и есть.
Что вы имеете в виду, когда говорите, что оно объявлено, как приватное? Что у него underscore перед именем?
Я хотел отметить, что в js нет проблем с тем, чтобы сделать его приватным фактически.