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

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

В этой заметке я хочу познакомить Вас с JavaScript-библиотекой для интерактивных карт Leaflet.

Библиотека была создана в 2011 году Владимиром Агафонкиным (Vladimir Agafonkin) с командой профессиональных разработчиков.

Последняя версия, на момент написания заметки — 0.5.1 от 6 февраля 2013 года

Перечислю основные особенности библиотеки:

— возможность работы в браузерах мобильных устройств, так и в браузерах настольных ПК;
— небольшой размер самой библиотеки — 28 кб;
— наличие хорошо документированного API (ознакомитсься с API);
— функциональность может быть расширена, за счет подключения дополнительных плагинов.

Теперь рассмотрим некоторые примеры использования Leaflet.

Для начала загружаем последнюю версию библиотеки с официального сайта http://leafletjs.com из раздела Download

Распакуем, скаченный архив.

Для работы нам будет нужно содержимое папки dist.

Копируем папку полностью на сервер, например в папку js.

И в разделе HEAD наших примеров тогда нужно прописать код:

<link rel="stylesheet" href="js/dist/leaflet.css" />
<!--[if lte IE 8]>
<link rel="stylesheet" href="js/dist/leaflet.ie.css" />
<![endif]-->
 
<script src="js/dist/leaflet.js"></script>

Также можно последний стабильный релиз библиотеки расположен на CDN

Для его использования в раздел HEAD нужно написать код следующего содержания:

<link rel="stylesheet" rel="nofollow" href="http://cdn.leafletjs.com/leaflet-0.5.1/leaflet.css" />
<!--[if lte IE 8]>
<link rel="stylesheet" rel="nofollow" href="http://cdn.leafletjs.com/leaflet-0.5.1/leaflet.ie.css" />
<![endif]-->
 
<script src="http://cdn.leafletjs.com/leaflet-0.5.1/leaflet.js"></script>

Первый пример — выводим карту OpenStreetMap

Leaflet - выводим слой OpenStreetMap

Для этого в разделе HEAD добавляем код для стилей окна с картой:

<style>
 
#map {width: 600px; height: 400px; }
 
</style>

А в раздел BODY – код:

<div id="map"></div>
 
<script type='text/javascript'>
 
//Определяем карту, координаты центра и начальный масштаб
var map = L.map('map').setView([56.326944, 44.0075], 12);
 
//Добавляем на нашу карту слой OpenStreetMap
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution: '&copy; <a rel="nofollow" href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
 
</script>

В начале, мы добавляем область для отображения карты

<div id="map"></div>

А далее идет JavaScript-код

Мы определяем новую карту, задаем координаты центра и уровень масштаба

var map = L.map('map').setView([56.326944, 44.0075], 12);

Затем добавляем слой тайлов карты OpenStreetMap

L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution: '&copy; <a rel="nofollow" href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);

Передаем два параметра:

http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png — шаблон для загрузки тайлов,

attribution — строка для описания источника слоя данных

Посмотреть пример в действии

Можно использовать и другой источник тайлов для карты, например Cloudmade.

Об этом сервисе у меня на блоге уже были заметки.

Нужно просто заменить код для источника тайлов на следующий:

L.tileLayer('http://{s}.tile.cloudmade.com/API-key/997/256/{z}/{x}/{y}.png', {
    attribution: 'Map data &copy; <a rel="nofollow" href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a rel="nofollow" href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a rel="nofollow" href="http://cloudmade.com">CloudMade</a>',
    maxZoom: 18
}).addTo(map);

В нем API-key — это ключ к API сервиса Cloudmade, для его получения необходима регистрация

Leaflet - выводим слой Cloudmade

Посмотреть пример в действии

Второй пример — добавляем маркер на нашу карту

Сделать это очень просто, для это нужно добавить код

L.marker([56.326944, 44.0075]).addTo(map);

Leaflet - добавляем маркер

Посмотреть пример в действии

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

L.marker([56.3193,44.0269]).addTo(map)
	.bindPopup("<strong>КАРО ФИЛЬМ Шоколад</strong><br />Адрес: ул. Белинского, 124").openPopup();

В параметре bindPopup мы прердаем html-код содержимого балуна, а параметр openPopup() служит для его открытия.

Leaflet - добавляем маркер с открытым балуном

Посмотреть пример в действии

Третий пример — задаем собственную иконку для обозначения маркера

Leaflet - свои иконки для маркеров

Посмотреть пример в действии

В начале мы задаем параметры для нашей иконки

var LeafIcon = L.Icon.extend({
			options: {
				shadowUrl: 'img/shadow.png',
				iconSize:     [32, 37],
				shadowSize:   [51, 37],
				iconAnchor:   [16,37],
				shadowAnchor: [16, 37],
				popupAnchor:  [0, -30]
			}
		});

shadowUrl — файл с изображением для тени иконки;
iconSize — размер иконки;
shadowSize — размер тени иконки;
iconAnchor — отступ от точки привязки для иконки изображения;
shadowAnchor — отступ от точки привязки для тени иконки;
popupAnchor — — отступ от точки привязки для балуна

Затем определяем файл с изображением для каждого из видов иконок

var coffeeIcon = new LeafIcon({iconUrl: 'img/coffee-red.png'}),
cinemaIcon = new LeafIcon({iconUrl: 'img/cinema.png'}),
restaurantIcon = new LeafIcon({iconUrl: 'img/restaurant.png'});

После этого добавляем иконки на нашу карту

L.marker([56.3271,44.0074], {icon: coffeeIcon}).bindPopup("<strong>Шоколадница, сеть кофеен</strong><br />Адрес: Минина и Пожарского площадь, 11").addTo(map);
L.marker([56.3193,44.0269], {icon: cinemaIcon}).bindPopup("<strong>КАРО ФИЛЬМ Шоколад</strong><br />Адрес: ул. Белинского, 124").addTo(map);
L.marker([56.3247,44.0092], {icon: restaurantIcon}).bindPopup("<strong>Бирмания, пивной ресторан</strong><br />Адрес: ул. Варварская, 8").addTo(map);

Кроме маркеров, мы можем размещать на карте различные геометрические фигуры: полилинии, полигоны, прямоугольники, окружности, использовать окружности в виде маркеров.

Рассмотрим пример добавления полилинии.

Для этого нам необходимо к коду самого первого примера добавить следующий код:

var polyline = L.polyline([[56.3271,44.0074],[56.3193,44.0269],[56.3247,44.0092]],
{color: 'red',
weight: 3,
opacity: 0.5,
smoothFactor: 1}).addTo(map);

Здесь в начале мы передаем массив координат вершит полилинии.

Затем определяем ее свойсва:

color: ‘red’ — цвет (красный);
weight: 3 — толщину;
opacity: 0.5 — степень прозрачности (задается от 0 до 1);
smoothFactor: 1 — задает степень упрощения отображения на каждом уровне масштаба ( чем больше — означает лучшую производительность и гладкий вид, и меньше — более точное представление.)

Для того, чтобы наша полилиния полностью показывалась на карте, нужно добавить еще одну строку кода

map.fitBounds(polyline.getBounds());

Leaflet - добавляем полилинию

Посмотреть пример в действии

Еще один пример, добавление на карту данных в формате GeoJSON

GeoJSON (http://www.geojson.org/) — формат представления различных структур географических данных. Объект GeoJSON может быть представлен геометрией (geometry), объектом (feature) или коллекцией объектов (feature collection). GeoJSON поддерживает следующие геометрические типы: Point (точка), LineString (ломаная), Polygon (полигон), MultiPoint (мультиточка), MultiLineString (мультиломаная), MultiPolygon (мультиполигон) и GeometryCollection (коллекция геометрий). Объект (feature) в GeoJSON состоит из геометрии и дополнительных свойств, коллекция объектов (feature collection) – из набора объектов (feature).

Подробнее с описанием формата GeoJSON можно познакомиться здесь.

И так у нас есть файл в фрмате GeoJSON с описанием некоторых географических данных (районов Нижегородской области) — noblast.js

Код файла noblast.js

Выведем его на карту.

Для этого в раздел HEAD добавляем строку

<script src="noblast.js" type="text/javascript"></script>

Присоединяем наш файл с данными.

А после добавления источника тайлов карты код

function onEachFeature(feature, layer) {
		var popupContent = "<p>I started out as a GeoJSON " +
		feature.geometry.type + ", but now I'm a Leaflet vector!</p>";
 
			if (feature.properties && feature.properties.popupContent) {
				popupContent += feature.properties.popupContent;
			}
 
			layer.bindPopup(popupContent);
		}
 
		var testLayer = L.geoJson(test, {
 
			pointToLayer: function (feature, latlng) {
				return L.marker(latlng, {icon: baseballIcon});
			},
 
			onEachFeature: onEachFeature
		}).addTo(map);
 
		L.control.scale().addTo(map);

Leaflet - выводим GeoJSON

Посмотреть пример в действии

Рассмотрим несколько примеров использования плагинов для расширения функционала библиотеки Leaflet.

Со списком плагинов можно познакомиться здесь и здесь.

Давайте рассмотрим использование плагина Leaflet.markercluster для кластеризации маркеров на карте.

Загрузить его можно с GitHab по адресу https://github.com/Leaflet/Leaflet.markercluster

В месте с плагином идут и примеры использования в папке example

За основу берем код из первого примера.

В разделе HEAD после подключения файлов самой библиотеки Leaflet, подключаем файлы плагина

<link rel="stylesheet" href="js/MarkerCluster.css" />
<link rel="stylesheet" href="js/MarkerCluster.Default.css" />
<!--[if lte IE 8]><link rel="stylesheet" href="js/MarkerCluster.Default.ie.css" /><![endif]-->
<script src="js/leaflet.markercluster-src.js"></script>

А затем файл с данными для кластеризации qiwi-nn.js

<script src="qiwi-nn.js"></script>

Код файла qiwi-nn.js

За вывод данных на карту отвечает следующий код:

var markers = new L.MarkerClusterGroup();
 
		for (var i = 0; i < addressPoints.length; i++) {
			var a = addressPoints[i];
			var title = a[2];
			var marker = new L.Marker(new L.LatLng(a[0], a[1]), { title: title });
			marker.bindPopup(title);
			markers.addLayer(marker);
		}
 
		map.addLayer(markers);

map.addLayer(markers);

Добавляем его в раздел BODY, сразу после подключения источника тайлов слоя OpenStreetMap

Leaflet - MarkerCluster

Посмотреть пример в действии

С помощью плагина Leaflet.GeoSearch (https://github.com/smeijer/L.GeoSearch), мы можем добавить на нашу карту форму для поиска по адресу.

Плагин поддерживает возможность поиска от трех поставщиков данных: Esri, Google и OpenStreetMap.

При желании Вы можете организовать поддержку своего типа геопоиска.

Рассмотрим пример с использованием поиска OpenStreetMap.

Leaflet - выводим слой OpenStreetMap и Leaflet.GeoSearch - OSM Provider

Посмотреть пример в действии

Код примера

В нем с начала мы подключаем сам плагин и стили для него, а также скрипт для поддержки http-геокодирования в OpenStreetMap:

<script src="l_geosearch_master/js/l.control.geosearch.js"></script>
<script src="l_geosearch_master/js/l.geosearch.provider.openstreetmap.js"></script>
<link rel="stylesheet" href="l_geosearch_master/css/l.geosearch.css" />

А для добавления возможности поиска после подключения слоя OpenStreetMap пишем следующий код:

new L.Control.GeoSearch({
            provider: new L.GeoSearch.Provider.OpenStreetMap()
        }).addTo(map);

Как видите все достаточно просто.

В конце заметки о библиотеке Leaflet приведу еще несколько примеров ее использования:

Отображение KML-файла

Leaflet - выводим KML

Посмотреть пример в действии

Отображение GPX-файла

Leaflet - выводим GPX

Посмотреть пример в действии

Пример отображения слоев Google Maps и Яндекс.Карт

Посмотреть пример в действии

В данном примере в правом верхнем углу карты расположен элемент управления слоями.

Нажав на который мы можем переключать различные типы карт для отображения (OSM, Yandex, Google).

Вывод OpenStreetMap

Вывод Яндекс.Карты

Вывод Яндекс.Карты

Вывод Google Maps

Вывод Google Maps

Загрузить архив с файлами примеров

  • Гость: Доброго времени суток. Задам вопрос здесь, если можно. Мне нужно подцепить на гугл(яндекс) карту свой слой. это границы объектов. как лучше реализовать? знаю что можно на карте по координатам добавлять многоугольники и надписи. а можно ли сделать дополнительный пиксельный прозрачный слой с нужными элементами? есть ли инструменты для создания таких слоев? буду признателен за информацию.
  • Гость: Вот тут вроде цепляют google подложку + слой Росреестра http://russian-face.ru/cadastre/cadastreCalc.html?bl=google
  • Гость: А можно подробнее про KML? какую библиотеку подключаете?
  • Гость: не работает отображение gpx трека
  • Александр Лаптев: Доброе время суток! Можно вопрос, творой день бьюсь. Как можно поменять картинку маркера на лету, т.е. выставлено три маркера с дефолтной картинкой и по событию надо изменить картинку одного маркера, как это можно сделать?
  • Гость: Спасибо! Благодаря этой статье я понял как запустить эту карту.
  • Гость: Спасибо за статью. Если знаете подскажите, как по клику на маркере KML слоя запросить данные из PHP+MySQL. Спасибо.
  • Гость: Добрый день! Хотелось бы более подробно раскрыть тему вывода маршрутов общественного транспорта на карте, информации по остановкам.Также часто встречаю темы про движение транспорта в реальном режиме времени. Откуда берутся эти данные и т.д. спасибо
  • Гость: Добрый день. Как можно объединить два примера: свои маркеры и кластеры, т.е. как в примере с кластерами сделать свои иконки?
  • Zhan Omar: Автор, нука подскажи, есть ли возмога добавить две точки например А и Б путем ввода адреса. И потом еще показать или выдать в каком полигоне находится точка А и в каком полигоне точка Б?... Да и кстати... Сам поиск с автозаполнением бы...
  • Anton Tenyakov: Здравствуйте, можно ли средствами Leaflet открывать балун с html страницей?