Клуб API Карт

Не открывается балун кластера

robotgo
12 апреля 2016, 13:21

Добрый день.

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

function focusOnGeoobject(id) {
        //Находим объект по id, который получаем при клике по элементу списка
        var object = loadingObjectManager.objects.getById(id);
        var coords = object.geometry.coordinates;
        var objectState = loadingObjectManager.getObjectState(id);
         
        myMap.setCenter(coords);

        myMap.zoomRange.get(coords).then(function (zoomRange) {
            //Масштабируем карту до тех пор, пока объект не выйдет из кластера или не будет достигнут максимальный зум
            while (objectState.isClustered && myMap.getZoom() !== zoomRange[1]) {
                myMap.setZoom(myMap.getZoom() + 1);
            }
            if (objectState.isClustered) {
                loadingObjectManager.clusters.state.set('activeObject', object);
                loadingObjectManager.clusters.balloon.open(objectState.cluster.id);
            } else {
                loadingObjectManager.objects.setObjectProperties(id, { preset: 'islands#redStretchyIcon' });
            }
        });
    }

5 комментариев
//Масштабируем карту до тех пор, пока объект не выйдет из кластера или не будет достигнут максимальный зум
while (objectState.isClustered && myMap.getZoom() !== zoomRange[1]) {
myMap.setZoom(myMap.getZoom() + 1);
}

Тут написана глупость. Смена масштаба как и перестроение кластеров – асинхронный процесс.
Спасибо! Действительно невнимательно читал документацию.
В итоге сделал так, вроде все отрабатывает так как и хотелось.
<pre class="prettyprint">
function focusOnGeoobject(id) {
var object = loadingObjectManager.objects.getById(id);
var coords = object.geometry.coordinates;

myMap.setCenter(coords).then(function() {
myMap.zoomRange.get(coords).then(function (zoomRange) {
setZoom(zoomRange[1], id);
var objectState = loadingObjectManager.getObjectState(id);
if (objectState.isClustered) {
loadingObjectManager.clusters.state.set('activeObject', object);
loadingObjectManager.clusters.balloon.open(objectState.cluster.id);
} else {
loadingObjectManager.objects.setObjectOptions(id, { preset: 'islands#redIcon' });
}
});
});
}

function setZoom(maxZoom,id) {
var objSt = loadingObjectManager.getObjectState(id);
if (objSt.isClustered && myMap.getZoom() !== maxZoom) {
myMap.setZoom(myMap.getZoom() + 1).then(setZoom(maxZoom, id));
}
}
</pre>
robotgo,
Ад какой-то
Не нужно тут это все. Триггерните клик на оверлее кластера, это решает задачу масштабирования на объекты, которые он содержит

objectManager.clusters.overlays.events.fire('click', {
objectId: objectManager.getObjectState(id).cluster.id
});
У меня может быть несколько точек на абсолютно идентичных координатах. То есть может потребоваться триггернуть клик несколько раз вплоть до достижения максимального зума, при котором кластер уже будет неделимым и хотелось бы тогда открыть балун с выбранным событием. Эмуляция клика на кластере делает практически то же самое, что и функция setZoom, при этом может понадобиться меньше итераций, что хорошо. Но у меня пока проблема с рекурсивным выполнением этого триггера, не понимаю, как дождаться окончания события click на оверлее кластере для того чтобы проверить, достигнут ли максимальный зум.

function setZoom(maxZoom, id) {
var objSt = loadingObjectManager.getObjectState(id);
var clusterId = objSt.cluster.id;
if (objSt.isClustered && myMap.getZoom() !== maxZoom) {
loadingObjectManager.clusters.overlays.events.fire('click', {
objectId: clusterId
});
setZoom(maxZoom, id);
}
}