Leaflet 0.4 — новая версия открытой JS-библиотеки для интерактивных карт



    После пяти с половиной месяцев разработки с момента выхода предыдущей версии, очень рад наконец представить вам Leaflet 0.4 — новую версию легковесной JavaScript-библиотеки для интерактивных карт, которая одинаково хорошо работает и на десктопных браузерах, и на мобильных устройствах.

    Этот релиз, к которому приложило руку 33 разработчика, несёт в себе более простой, удобный API и громадное множество улучшений и исправлений вместе с масштабным обновлением документации, запуском официального блога и страничкой плагинов. Давайте рассмотрим улучшения по порядку.

    Упрощённый API


    К следующим изменениям (и многим другим) меня подтолкнула критическая рецензия на Хабре от forgotten. За что ему большое спасибо!

    Leaflet 0.4 содержит несколько улучшений API, позволяющих писать более простой и краткий код (в стиле jQuery), при этом оставаясь обратно-совместимым с предыдущим подходом (так что можно смешивать оба стиля):

    L.marker([51.5, -0.09])
        .addTo(map)
        .bindPopup('Hello world!')
        .openPopup();

    Во-первых, методы теперь принимают объекты LatLng, LatLngBounds, Point и Bounds в форме простых массивов — теперь нет необходимости создавать их явно:

    map.panTo([50, 30]); // то же самое, что:
    map.panTo(new L.LatLng(50, 30));

    Во-вторых, такие методы класса Map, как addLayer, addControl и openPopup, получили свои аналоги с другой стороны:

    marker.addTo(map);  // аналогично map.addLayer(marker)
    control.addTo(map); // map.addControl(control)
    popup.openOn(map);  // map.openPopup(popup)

    Учитывая то, что в Leaflet все методы, которые не возвращают какое-то явное значение, возвращают сам объект (this), это позволяет более удобно вызывать методы «по цепочке».

    В-третьих, каждый класс в Leaflet теперь имеет свой class factory (с таким же именем, но начинающийся с маленькой буквы), что позволяет создавать объекты без оператора new (что делает код с множеством цепных вызовов более красивым).

    L.map('map').fitWorld(); // то же самое, что:
    (new L.Map('map')).fitWorld();

    Новые возможности


    Улучшенная zoom-анимация

    Маркеры, popup'ы, векторные объекты и слои из изображений в предыдущей версии прятались во время zoom'а, но теперь красиво и плавно анимируются вместе с тайлами. Если же у вас на карте много сотен маркеров и анимация происходит не очень плавно (скажем, больше 1000 в случае Chrome), ее можно отключить опцией карты markerZoomAnimation, хотя в таком случае было бы более целесообразно использовать плагин кластеризации маркеров.

    Управление с помощью клавиатуры

    Доступность Leaflet-карт заметно улучшилась благодаря новой возможности управления с помощью клавиатуры, включённой по умолчанию. Она позволяет управлять картой, нажимая клавиши стрелок и +/-. Очень удобно, кстати говоря — попробуйте!

    Эффект инерции

    Таскать карту мышкой или пальцами теперь тоже стало приятнее засчёт эффекта инерции, при котором карта продолжает плавно замедляться в том же направлении, в которое вы ее дёрнули. Этот эффект достаточно гибко настраивается — можно контролировать максимальную начальную скорость, замедление и порог чувствительности, при котором инерция срабатывает.

    Масштабирование пальцами на Android 4

    В предыдущей версии Leaflet жест для приближения/удаления на карте работал только на iOS, пользователям Android же приходилось довольствоваться кнопками. Теперь жестами можно изменять масштаб карты на Android 4+, при чём не только во встроенном браузере, но и на Chrome и Firefox для Android.

    Индикатор масштаба

    Простой индикатор текущего масштаба в метрический и/или имперской системах измерения. Как обычно, внешний вид можно полностью изменить с помощью CSS.

    Редактирование ломаных линий и полигонов

    Позволяет редактировать ломаные линии и полигоны с помощью простого, интуитивно понятного интерфейса. Правда, эта возможность в будущих версиях скорей всего будет перенесена в отдельный плагин для рисования фигур Leaflet.draw.

    Легковесные div-иконки для маркеров

    В добавок к традиционным иконкам для маркеров из изображений, теперь можно использовать легковесные иконки, представляющие собой обычный div c определённым HTML внутри, стилизованный внешним CSS. К примеру, сейчас они используются при редактировании (квадратики в вершинах) и в плагине для кластеризации (цветные кластеры).

    L.marker([50.505, 30.57], {
        icon: L.divIcon({className: 'my-div-icon'})
    }).addTo(map);

    Прямоугольник

    Простой способ создавать прямоугольные области на карте. То же самое можно было делать раньше с помощью полигонов, но так удобнее:

    L.rectangle([[51.505, -0.03], [51.5, -0.045]]).addTo(map);

    Улучшения API


    GeoJSON API

    API для отображения GeoJSON-слоёв был существенно улучшен, чтобы сделать его более гибким и простым в использовании. С обновлённым API можно ознакомиться с помощью учебной статьи на сайте. Правда, изменения эти не обратно-совместимы, поэтому придётся обновить свой старый код.

    Icon API

    API для иконок был улучшен и упрощён, правда, изменения тоже не обратно-совместимы. Как он выглядит теперь, можно посмотреть в соотетствующей учебной статье, либо сразу в документации.

    Control API

    Собственные управляющие элементы теперь создавать намного проще — пример можно увидеть в документации.

    Улучшенная работа с событиями

    Методы для работы с событиями on и off теперь могут принимать несколько типов событий в одной строке (с пробелами между типами):

    map.on('click dblclick moveend', doStuff);

    Еще в них теперь можно передавать объекты с парами событий/слушателей:

    marker.on({
        click: onMarkerClick,
        dragend: onMarkerDragEnd
    });

    Кроме этого, теперь, если ничего не передавать в метод off кроме названия события, объект отпишет всех слушателей, которые были подписаны на данное событие:

    map.off('click');

    Другие улучшения

    Leaflet 0.4 содержит более 30 новых методов, опций и событий в разных классах, делающие библиотеку более полной и мощной. Можете ознакомиться с полным списком.

    Улучшения производительности и удобства пользования


    В новой версии содержится несколько улучшений, делающих Leaflet еще быстрее:

    • Скорость перетаскивания карты (и изменения ее размеров) была улучшена (о некоторых трюках, которые лежат в основе этого, хотелось бы написать в отдельной статье на Хабре)
    • Добавление и обновление векторных слоёв, отрисованных Canvas'ом (например, в случае Android 2) стало работать намного быстрее (большая пачка независимых изменений теперь вызывает только одну перерисовку экрана)
    • Тени на управляющих элементах для мобильных устройств были заменены на обычные border'ы для улучшения производительности
    • Векторные слои теперь не мерцают после перетаскивания карты на iOS

    В добавок, было несколько улучшений usability:

    • Перетаскивание карты теперь работает даже тогда, когда курсор находится над маркером (помогает на картах с большим количеством маркеров)
    • Улучшен вид popup'а
    • У тайловых слоёв теперь есть опция detectRetina, которая удваивает разрешение тайлов на ретине (реализовано небезызвестным на Хабре Mithgol'ом)

    Исправления


    Leaflet 0.4 содержит около 45 исправлений, делающих библиотеку более стабильной и надёжной среди всех поддерживаемых браузеров и платформ. Исправления, которые хочется особо отметить: стрёмный глюк на iOS, который в некоторых редких случаях приводил к пропаданию карты после зума; неработающий зум на IE10; ломающиеся карты в том случае, когда страница отдаётся со строгим XHTML content-type'ом в заголовках; неправильно работающий зум на картах внутри элемента с position: fixed. Вот полный список исправлений.

    Обновление с предыдущей версии


    Кроме упомянутых выше изменений в GeoJSON и Icon, при обновлении с предыдущей версии до 0.4 стоит ознакомиться с кратким списком потенциально несовместимых изменений (правда, исправление старого кода вряд ли займёт больше нескольких минут).

    Скачать новую версию, получить ссылки на библиотеку в CDN, или почитать инструкции для собственной сборки из исходного кода можно на странице скачивания.

    Статистика кода


    Я по прежнему привержен тому, чтобы сохранять библиотеку как можно более легковесной. Вот немного статистики по новой версии:

    • JavaScript: 26.7 КБ в сжатом виде (102 КБ в минифицированном и 176 КБ в исходном, 7578 строк кода)
    • CSS: 1.8 КБ в сжатом виде (8 КБ в исходном, 377 строк кода)
    • Изображения: 10 КБ (5 png-картинок)

    Обновление документации


    До этих пор, документация Leaflet была неполной и не всегда содержалась в полностью актуальном состоянии. Для этого релиза, очень много усилий ушло на то, чтобы довести документацию до состояния полной и актуальной на 100%. Все оставшиеся классы, методы, свойства, опции и события были тщательно задокументированы и сопровождены большим количеством примеров кода. С этого момента, документация будет содержаться в идеальном состоянии.

    Кроме этого, дизайн страницы документации был серьёзно улучшен, — расцветка, шрифт, отступы, переносы, даже ширина колонок, — было проработано множество деталей, чтобы сделать страницу лёгкой и приятной для чтения.

    Страница плагинов


    На сайте Leaflet наконец-то появилась страница со списком сторонних плагинов, которые могут расширить библиотеку множеством интересных функций и помочь интеграции со сторонним сервисами.

    Один плагин хотелось бы отметить отдельно — это Leaflet.markercluster, на данный момент лучший плагин для кластеризации маркеров, который я когда-либо видел из решений для всевозможных API карт. Он красивый, быстрый, с плавными анимациями для кластеров, включает умное решение для скоплений маркеров на последнем уровне масштаба (в стиле Google Earth), умеет подсвечивать область, покрытую определённым кластеров, по наведению мышью, хорошо работает на мобильных устройствах, и гибко настраивается. Обязательно посмотрите!

    Другой плагин, достойный внимания — Leaflet.draw, добавляющий возвожность создавать разные фигуры, такие, как ломаные линии, полигоны, круги, прямоугольники и точки, с помощью удобного и понятно интерфейса с иконками и подсказками. В будущем, весь код, связанный с редактированием векторных слоёв, скорей всего, перекочует в этот плагин.

    Еще, благодаря плагину Proj4Leaflet, который интегрирует Leaflet с библиотекой для географический проекций Proj4js, теперь Leaflet можно использовать с множеством нестандартных проекций.

    Кроме этого, обязательно посмотрите на OSM Buildings, JS-библиотеку, позволяющую визуализировать OpenStreetMap-данные высотности домов в перспективной 3D-проекции на Leaflet-картах. Выглядит очень здорово.

    Большие компании, использующие Leaflet


    С момента предущего релиза Leaflet начали использовать множество замечательных компаний, но отдельно хотелось бы гордо отметить три — Flickr, foursquare и Wikimedia Foundation. Несколько других именитых пользователей красуются теперь на главной странице сайта.

    Спасибо


    Хотелось бы сказать большое спасибо всем, кто помог развитию библиотеки — всем, кто присылал патчи на GitHub, сообщал об ошибках, использовал Leaflet на своих вебсайтах, рассказывал о ней коллегам и упоминал на конференциях. Очень рад, что вокруг созданной мной библиотеки собралось такое замечательное сообщество.

    Спасибо за внимание! Буду рад любым отзывам.

    P.S.: Эта статья — немного изменённый русскоязычный вариант моего же официального анонса на сайте Leaflet, но поскольку я сам являюсь автором, решил, что она всё-таки не относится к переводам. Поправьте меня, если что.

    Similar posts

    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 30

      +4
      Либа — супер, как раз искал нечто подобное для своего проекта.
        0
        Что- на сайте не нашел. А есть возможность переключатся между OSM, Google Maps, Yandex maps?
          +2
          Для поддержки Google и Yandex Паша Шрамов сделал специальный плагин.
          Что касается самого переключения — есть встроенный контрол для этого.
            0
            Плагин это хорошо, но разве это не противоречит лицензиям Гугла и Яндекса?
              0
              Эти плагины используют соответствующие JS API, а не напрямую тайлы запрашивают. Такой подход применяется во многих библиотеках (OpenLayers, Mapstraction) и от Гугла пока никаких претензий не поступало.
          0
          А про какие трюки с петаскиванием идет речь?
            0
            Использование request/cancelAnimationFrame при обновлении позиции карты.
            +2
            За Leaflet.markercluster и вам, и автору отдельное спасибо. Пробовал использовать leaflet-clusterer, но ему на больших значениях (те самые злосчастные 50 000) становится плохо.
              +1
              Замечательные улучшения в API!
              Имхо, можно было не бояться и сделать самовызывающиеся конструкторы без new для привычного имени класса, дабы вызовы L.Map() и new L.Map() приводили к одному результату. К чему хитрить с регистром?

              Не всегда получается запустить карту в инерционный полет при использовании. Что-то там нужно дотюнить.

              В плагине с 3D-проекциями съезжает слой с ними же при инерции (маленький фидбэк).
                0
                Я и на фабрики решился с трудом. :) Не очень мне нравится подход с самовызывающимися конструкторами. Мне как-то спокойнее, когда это происходит явно — так проще понять код, меньше магии.

                За запуск инерционности отвечает опция inertiaThreshold. Просто мышь не очень хорошо подходит для таких штук — если установить порог больше, то инерция будет иногда происходит, когда ее не ждёшь, с заметной паузой между движением пользователя и инерционным.

                Насчёт плагина — знаем про эту проблему, пока не придумали, как это лучше решить. Наверное в таком случае лучше отключать инерцию.
                +1
                Подскажите, а возможности прокладывания маршрута есть?
                  +3
                  Leaflet — всего лишь JS-библиотека. Для прокладывания маршрутов нужен веб-сервис, к примеру, есть HTTP-сервис маршрутов от CloudMade, который можно достаточно просто интегрировать вручную.
                  –1
                  А маршруты планируются?
                  +1
                  Очень-очень приятно выглядит проект, поздравляю с именитыми компаниями и наилучшего развития!
                  Надеюсь и мне пригодится, хотелось бы попробовать с ним поработать)
                    0
                    Библиотека супер! Было бы еще классно, если сделать сборку для nuget.
                      +1
                      Да, мне даже кто-то писал об этом, спрашивал, стоит ли ему сделать такую сборку. Я согласился, конечно, а человек пропал куда-то и не сделал. :)
                      0
                      Подскажите пожалуйста, как можно создать свой tile server? Нужно сделать интерактивную карту для одного проекта, но карта будет из определённого изображения, а на изображении карта из игры.
                        +1
                        Прям обязательно сервер с тайлами, генерирующимися налету?
                        Может достаточно будет нарисовать карту, присвоить ей фейковые координаты, скормить MapTiler и получить TMS-источник (тайлы разных масштабов, разложенные по каталогам), а в качестве бонуса — html-страничку со смотрелкой этих тайлов на основе google maps api или openlayers (которую после вдумчивого чтения документации можно будет доделать до желаемого вида)?
                        0
                        Справедливости ради, пятидесятитысячный пример Leaflet.markercluster у меня потребовал таки трижды нажать Continue в алерте «Script not responding...». FF 14.0.1 win32.
                          0
                          Раз уж зашёл разговор… у меня с 50 тысячами на одном слое в итоге так и не получилось работать. Если же разбить на слои хотя бы по 10 тысяч, то уже как-то можно жить, хотя тоже не очень шустро. Да и кластеры, к сожалению, при этом могут накладываться друг на друга.

                          В общем, тут спасёт либо серверная кластеризация, либо отказ от вывода всех точек сразу.
                            0
                            То, что кластеры накладываются, это баг, который будет пофикшен, ну и оптимизировать тоже еще будем. Так что есть шанс, что всё-таки будет работать как надо с 50000. :)
                              0
                              Ну, это не совсем баг, слои-то разные.
                              А с 50К зависает очень даже, вряд ли оптимизация поможет. Может вам ввести несколько алгоритмов кластеризации, по типу «этот красивее, а этот быстрее»?
                                0
                                Оптимизация таки помогла. :) В FF у меня выигрышь в 17 раз, окошек насчёт «Script not responding» в примере с 50к уже не выскакивает.
                                  0
                                  Раз уж мы заговорили про кластеризацию, то ещё одно пожелание: сейчас центр кластера считается как центр bounds'а, что очень раздражает, когда тысяча точек рядом, а одну куда-нибудь унесло. При зуме всё жутко скачет. Хочется, чтобы координаты центра считались как среднее арифметическое.

                                  Я пробовал переписать, но выходит недостаточно быстро. Если будет хороший результат, кину pull request, но, наверно, у вас получится лучше.
                          0
                          0
                          Подскажите пожалуйста, можно ли с помощью данной технологии проложить на карте путь из точки А в точку Б, а так же пометить нужные остановки? Если ДА, то пожалуйста киньте ссылку на конкретное место в документации или примеры.
                          Спасибо.

                        Only users with full accounts can post comments. Log in, please.