Генерация слоя активных областей из YMapsML
Приложение, предложенное разработчиком twirl, позволяет из YMapsML-файла получить набор тайлов, необходимых для создания слоя активных областей.
Скачать приложение можно по адресу: http://github.com/twirl/hsTiler.
Подготовка YMapsML-документа
Допустим, у нас есть список точек разных типов, которые мы хотим показать на карте в виде значка, используя технологию активных областей. Для примера возьмем список городов-героев:
[
{ "name": "Ленинград", "location": [30.313497,59.938531] },
{ "name": "Сталинград", "location": [44.514208,48.708898] },
{ "name": "Севастополь", "location": [33.558616,44.585098] },
{ "name": "Одесса", "location": [30.712384,46.468691] },
{ "name": "Киев", "location": [30.531113,50.402398] },
{ "name": "Москва", "location": [37.609218,55.753559] },
{ "name": "Брестская крепость", "location": [23.654573,52.086152] },
{ "name": "Новороссийск", "location": [37.7767,44.720479] },
{ "name": "Керчь", "location": [36.464342,45.30667] },
{ "name": "Минск", "location": [27.567338,53.898087] },
{ "name": "Тула", "location": [37.617384,54.193212] },
{ "name": "Мурманск", "location": [33.077819,68.963322] },
{ "name": "Смоленск", "location": [31.999095,54.7798] }
]
Сформируем по этому списку YMapsML-документ (см. описание формата YMapsML):
<?xml version="1.0" encoding="UTF-8"?>
<ymaps xmlns="http://maps.yandex.ru/ymaps/1.x" xmlns:gml="http://www.opengis.net/gml">
<Representation xmlns="http://maps.yandex.ru/representation/1.x"></Representation>
<GeoObjectCollection>
<gml:featureMembers>
<GeoObject>
<gml:name>Ленинград</gml:name>
<gml:Point>
<gml:pos>30.313497 59.938531</gml:pos>
</gml:Point>
</GeoObject>
<GeoObject>
<gml:name>Сталинград</gml:name>
<gml:Point>
<gml:pos>44.514208 48.708898</gml:pos>
</gml:Point>
</GeoObject>
<!-- Перечисление остальных 10 городов опущено -->
</gml:featureMembers>
</GeoObjectCollection>
</ymaps>
Зададим значок, которым будут отмечены города. Для этого опишем в теге Representation
стиль метки:
<Representation xmlns="http://maps.yandex.ru/representation/1.x">
<Style gml:id="hero">
<iconStyle>
<href>icons/hero.png</href>
<size x="27" y="26"/>
<offset x="-11" y="-28"/>
</iconStyle>
</Style>
</Representation>
А для объекта GeoObjectCollection
укажем стиль коллекции:
<GeoObjectCollection>
<style>#hero</style>
<gml:featureMembers>
<!-- Перечисление городов опущено -->
</gml:featureMembers>
</GeoObjectCollection>
Коллекции могут быть вложенными, то есть возможно задать разные значки группам объектов. Например, выделим Брестскую крепость в отдельную коллекцию и назначим этой коллекции друой значок:
<?xml version="1.0" encoding="UTF-8"?>
<ymaps xmlns="http://maps.yandex.ru/ymaps/1.x" xmlns:gml="http://www.opengis.net/gml">
<Representation xmlns="http://maps.yandex.ru/representation/1.x">
<Style gml:id="hero">
<iconStyle>
<href>icons/hero.png</href>
<size x="27" y="26"/>
<offset x="-11" y="-28"/>
</iconStyle>
</Style>
<Style gml:id="hero-keep">
<iconStyle>
<href>icons/hero-keep.png</href>
<size x="14" y="13"/>
<offset x="-5" y="-14"/>
</iconStyle>
</Style>
</Representation>
<GeoObjectCollection>
<gml:featureMembers>
<GeoObjectCollection>
<style>#hero</style>
<gml:featureMembers>
<GeoObject>
<gml:name>Ленинград</gml:name>
<gml:Point>
<gml:pos>30.313497 59.938531</gml:pos>
</gml:Point>
</GeoObject>
<!-- Перечисление остальных 10 городов опущено -->
</gml:featureMembers>
</GeoObjectCollection>
<GeoObjectCollection>
<style>#hero-keep</style>
<gml:featureMembers>
<GeoObject>
<gml:name>Брестская крепость</gml:name>
<gml:Point>
<gml:pos>23.654573 52.086152</gml:pos>
</gml:Point>
</GeoObject>
</gml:featureMembers>
</GeoObjectCollection>
</gml:featureMembers>
</GeoObjectCollection>
</ymaps>
Стиль при необходимости можно назначить и отдельным геообъектам. Объектам также можно назначить приоритет (z-index). Для этого в теге GeoObject необходимо указать его численное значение:
<gml:metaDataProperty>
<AnyMetaData>
<priority>10</priority>
</AnyMetaData>
</gml:metaDataProperty>
В теге AnyMetaData
можно указывать любые данные, они будут преобразованы в JSON и доступны из JavaScript.
Подготовка слоев тайлов
Специальный скрипт (см. http://github.com/twirl/hsTiler) позволяет по YMapsML-документу подготовить два слоя тайлов – с картинками и js-описаниями. Для его использования необходимо:
-
Выложить скрипты на сервер.
-
В файле
index.php
указать:- путь к YMapsML-файлу;
- путь для сохранения файлов;
- шаблоны имени файлов;
- диапазон масштабов
-
Запустить
index.php
из браузера или из командной строки.
Если на сервере разрешен allow_url_fopen
, то во всех путях можно указывать URL.
Скрипт подготовит два слоя тайлов, которые после этого нужно выложить в публичный доступ по http.
Отображение слоев активных областей на карте
При подготовке тайлов автоматически создается html-файл с примером подключения слоя активных областей. Этот код выглядит примерно так:
// Вспомогательная функция обработки шаблонов
// Обрабатывает подстановки вида %x, %y, %z
function processTemplate (template, tile, zoom) {
return template.replace(/%x/ig, tile.getX()).replace(/%y/ig, tile.getY()).replace(/%z/ig, zoom);
}
// Источник тайлов с изображениями
var ds = new YMaps.TileDataSource('шаблон имени png-тайла', 1, 0);
ds.getTileUrl = function (tileNumber, zoom) {
return processTemplate(
YMaps.TileDataSource.prototype.getTileUrl.call(this, tileNumber, zoom),
tileNumber,
zoom
);
};
// Добавляет "картиночный" слой на карту
map.addLayer(new YMaps.Layer(ds));
// Источник тайлов с описаниями активных областей
var os = new YMaps.Hotspots.ObjectSource('шаблон имени js-тайла', 'шаблон ключа');
os.getTileUrl = function (tileNumber, zoom) {
return processTemplate(
YMaps.Hotspots.ObjectSource.prototype.getTileUrl.call(this, tileNumber, zoom),
tileNumber,
zoom
);
};
os.getKey = function (tileNumber, zoom) {
return processTemplate(
YMaps.Hotspots.ObjectSource.prototype.getKey.call(this, tileNumber, zoom),
tileNumber,
zoom
);
};
// Добавляет слой активных областей на карту
var hLayer = new YMaps.Hotspots.Layer(os);
map.addLayer(hLayer);
Слой активных областей обсчитывает действия пользователя и генерирует следующие события: MouseEnter
, MouseMove
, MouseLeave
, MouseUp
, MouseDown
, Click
, DblClick
. В обработчик каждого из этих событий приходит следующая информация:
- Ссылка на сам слой.
- Геообъект на котором произошло событие.
- Событие мыши – экземпляр класса YMaps.MouseEvent.
- Геометрическая фигура, над которой произошло событие (в нашем случае – пиксельные координаты значка на текущем масштабе).
Обрабатывать события можно стандартными средствами API Яндекс.Карт (см. События).
YMaps.Events.observe(hLayer, hLayer.Events.Click, function () {
alert('Щёлк!');
});
По умолчанию слой активных областей ведет себя следующим образом:
- При наведении курсора на значок меняет тип курсора на
pointer
. - При наведении на значок показывает всплывающую подсказку. По умолчанию текст всплывающей подсказки берется из тега <name> соответствующего GeoObject.
- При щелчке мыши по значку показывает балун (хвостик балуна находится в точке щелчка). Текст балуна по умолчанию следующий:
<h3>$[name]</h3><p>$[description]</p>
, где$[name]
и$[description]
берутся из тегов<name>
и<description>
соответствующего геообъекта.
Поведение по умолчанию можно переопределить. Изменим его следующим образом: пусть балун открывается не в месте щелчка мышью, а по координатам города, а внутри балуна показывается фрейм со страницей Википедии об этом городе.
Для этого потребуется:
-
Определить пользовательский тип объекта-активной области. Каждому GeoObject из YMapsML в JavaScript соответствует экземпляр класса YMaps.Hotspots.Object. Унаследуемся от этого класса:
// Функция наследования var extend = function (child, parent) { var c = function () {}; c.prototype = parent.prototype; c.prototype.constructor = parent; return child.prototype = new c; }; var myObject = function () { YMaps.Hotspots.Object.apply(this, arguments); } extend (myObject, YMaps.Hotspots.Object);
-
Определить функцию requestBalloonData в пользовательском классе myObject
myObject.prototype.requestBalloonData = function (callback) { // Функции callback требуется передать текст балуна и точку его привязки к карте // Данные геообъекта доступны через функцию getData() var data = '<iframe style="width: 850px; height: 550px;" src="http://ru.wikipedia.org/wiki/' + this.getData().name + '"/>', parts = this.getData().Point.pos.split(' '), position = new YMaps.GeoPoint(parts[0], parts[1]); // Передает функции-обработчику содержимое балуна и точку его привязки callback(data, position); }
-
Указать источнику данных пользовательский класс объектов вместо стандартного:
// os - экземпляр класса YMaps.Hotspots.ObjectSource os.createObject = function (layer, data, shapes, priority) { return new myObject(layer, data, shapes, priority); };