Есть у карт Рамблера одно интересное дизайнерское решение, отсутствующее в других картах. Это контрол центра карты, благодаря которому показывается на что направлен текущий центр карты. Именно на примере этой функциональности я бы хотел рассказать вам о том, как сделать свой контрол для карт на своем сайте.
Создание контрола разделим на нескольких этапов.
Шаг 1. Лейаут.
Лейаут, он же макет. Эта сущность отвечает за внешний вид элемента на карте. В нашем случае это крестик, при наведении на который будут показываться координаты центра карты. Создавать макет мы будем с помощью специальной фабрики templateLayoutFactory.
var CrossCenterLayout = ymaps.templateLayoutFactory.createClass('<div id="cross-center" style="left:$[options.position.left]px;top:$[options.position.top]px;">+</div>', {
build: function() {
CrossCenterLayout.superclass.build.call(this);
this._controlListeners = this.events.group().add('mouseenter', this.onCenterEnter, this).add('mouseleave', this.onCenterLeave, this);
// запоминаем ссылку на карту, в которую добавлен контрол
this._map = this.getData().map;
},
clear: function() {
this._controlListeners.removeAll();
CrossCenterLayout.superclass.clear.call(this);
},
onCenterEnter: function() {
var center = this._map.getCenter();
var lat = center[0].toFixed(2);
var lng = center[1].toFixed(2);
// показываем в центре карты хинт с координатами центра карты
this._map.hint.show(center, {
content: lat + ', ' + lng
});
},
onCenterLeave: function() {
// скрываем хинт
this._map.hint.hide();
}
});
Рассмотрим код подробно. Фабрика templateLayoutFactory принимает на вход 2 параметра, шаблон будущего макета и список методов создаваемого лейаута, которые могут переопределять методы родительского класса.
В нашем случае мы переопределяем методы build и clear, а так же добавляем свои методы onCenterEnter и onCenterLeave. В методе build добавляем в контейнер менеджера событий подписки на mouseleave и mouseenter.
В методе clear мы от этих подписок избавляемся.
Шаг 2. Класс контрола.
var CrossCenter = function() {
this.events = new ymaps.event.Manager();
this.options = new ymaps.option.Manager();
this.state = new ymaps.data.Manager();
};
CrossCenter.prototype = {
setParent: function(parent) {
this.parent = parent;
if (parent) {
var map = parent.getMap();
this.layout = new CrossCenterLayout({
// передаем в лейаут данные о карте, на которую добавлен контрол и о его опциях
map: map,
options: this.options
});
// контрол будет добавляться в pane контролов
this.layout.setParentElement(map.panes.get('controls').getElement());
} else {
this.layout.setParentElement(null);
}
},
getParent: function() {
return this.parent;
}
};
Это, пожалуй, самая трудная часть кода. Тут мы реализуем интерфейс IControl. Сначала задаем обязательные поля, с помощью соответствующих менеджеров event, optionи data. Затем реализуем методы setParent и getParent. Первый был подсмотрен в исходных кодах апи, благодаря режиму debug, а второй, я думаю, вопросов не вызывает.
Шаг 3. Добавление на карту
С учетом стиля
#cross-center{
font-size: 20px;
cursor: pointer;
position: absolute;
z-index: 800;
}
и контейнера карты
<div id="map" style="height: 300px; width: 420px;"></div>
создаем контрол и добавляем его в центр карты
var crossCenter = new CrossCenter();
map.controls.add(crossCenter, {
top: 140,
left: 200
});
P.S. Чтобы было совсем как у Рамблера, в метод onCenterEnter можно добавить обратное геокодирование, изменяя параметр kind в зависимости от текущего зума карты.
Автор: d0lfin