Событие перерисовки кастомного маркера в яндекс картах
Вопрос, вероятно, будет без кода, ибо надо просто понять, что использовать.
Ситуация следующая. На карту с помощью менеджера объектов загружаются точки. Вместо обычного маркера создается свой: ymaps.templateLayoutFactory.createClass(....).
Далее пользователь может точки выбирать и добавлять в список, а к кастомному лайауту маркера добавляется класс selected, который влияет на его визуально отображение (читай - меняет цвет маркера в стилях).
И вот тут загвоздка. При некоторых условиях макет маркера перерисосывается. Например, когда открывается баллун, то маркер скрывается, а когда баллун закрывается маркер пересоздается. Либо когда маркер уходит далеко за область отображения карты, а потом вернем карту назад то он опять тоже создается заново. В общем говоря, менеджер все в памяти не держит и порой пересоздает макеты.
Как следствие - теряется класс selected.
И вот теперь вопрос - как отловить событие, когда маркер пересоздается, чтобы проверить его наличие в списке выбранных и вернуть ему класс .selected.
Ответы (1 шт):
В общем говоря, задача свелась к более простой. Не надо из-вне управлять классами маркера, а в properties внести счетчик того, добавлен маркер в список или нет (может быт добавлен несколько раз). Далее соответственно это учесть в шаблоне маркера, добавляя (или нет) нужный класс. Таким образом, при каждом перестроении он сам подхватывает данные, когда карта его перерисовывает.
Тут правда встает вопрос о том, как принудительно перерисовать маркер при его выборе, но пока что классы добавляются внешним кодом.
Итак, если кому-то пригодится, то небольшие фрагменты кода по проблеме.
Создаем карту, загружаем данные
map = new ymaps.map(....);
mgr = new ymaps.ObjectManager(...);
$.getJSON("/path/to/points.json", function(data){
});
в загрузке определяем макет
let mark = '<div class="camera {{ properties.src }} {% if properties.selected %}selected{% endif %}" id="mm-{{ properties.sid }}">...</div>';
let markerLayout = ymaps.templateLayoutFactory.createClass(mark);
тут properties.selected это счетчик добавлений точки в список.
Далее генерим информацию по точкам и добавляем их на карту
let points = data.map(function(a, idx){
return {
type: "Feature",
id: idx,
geometry: { .... },
properties: {
.....
sid: ... ,
selected: 0, // <--- поле счетчика
},
options: {
iconLayout: markerLayout, // <---- макет
iconShape : { .... } // активная область для кликов
openBalloonOnClick: false,
}
};
});
mgr.add( { type: "FeatureCollection", features: points });
map.geoObjects.add(mgr);
Тут (к вопросу не относится, но для полноты картины) при клике в маркер открываем баллун, а если клик с контролом/шифтом, то добавляем в список
mgr.objects.events.add('click', function(e){
let oid = e.get('objectId');
let o = mgr.objects.getById(oid);
if(o.geometry.type !== 'Point') return false;
let oe = e.get('domEvent').originalEvent;
if(oe.ctrlKey || oe.shiftKey) {
model.add(o);
e.preventDefault();
}
else {
mgr.objects.balloon.open(oid);
}
return false;
});
вызов model.add(o) тут увеличивает счетчики, добавляет начальный .selected (вот тут бы дернуть перерисовку вручную, и класс бы добавился самостоятельно). Формально перерисоваться он должен при изменений не properties а options, но там нам вроде менять нечего.
function add(o){
let sid = o.properties.sid;
let target = "#mm-" + sid;
$(target).addClass('selected');
o.properties.selected++;
this.selected[sid] = true;
this.modified = true;
}
при удалении из списка делается аналогичный selected-- и removeClass() при достижении 0.