Клуб API Карт

RemoteObjectManager с серверной кластеризацией

mtao.biz
16 января, 20:13
Использую RemoteObjectManager с серверной кластеризацией с 
версией АПИ 2.1.47.

Все казалось-бы хорошо, но... Мне необходимо выполнять некоторые 
манипуляции с объектами в видимой части карты. 
И если с метками проблем нет, то с кластерами сгенерированными на 
сервере начинаются проблемы:

ymaps.geoQuery(objectManager.clusters) хоть и срабатывает 
без ошибок и даже что-то возвращает, но вызов searchIntersect() 
у GeoQueryResult приводит к ошибке. 

Оно и не мудрено, ибо объекты кластеров в GeoQueryResult по сути 
никак не изменились по сравнению с тем, как они пришли из ajax. 
В них нет никаких дополнительных методов, в отличие от Feature, 
которые преобразовываются в Placemark. 

И судя по всему GeoQueryResult тоже не готов к такому повороту событий.

Вот пример описания кластера из Ajax:
{
  type: "Cluster", 
  bbox: [[43.58473777771, 39.728579521179], [43.584780693054, 39.728622436523]],
  geometry: {type: "Point", coordinates: [43.58478, 39.728595]},
  properties: {id: "szsrbn37x", iconContent: 2}
}
В теории objectManager.clusters должен быть коллекцией содержащей 
элементы типа ClusterPlacemark, но увы, там Object полученный из json. 

Получить Overlay для кластеров так-же не удается,
objectManager.clusters.overlays выдает пустую коллекцию.

Для того, чтобы отлавливать момент окончания загрузки очередного 
тайла пришлось сделать своего наследника от RemoteObjectManager:


ymaps.modules.define('objectManager.component.ReloadOnZoomChangeControllerWithEvents', [
            'util.defineClass',
            'objectManager.component.ReloadOnZoomChangeController'
        ], function (provide, defineClass, ReloadOnZoomChangeController) {
            var ReloadOnZoomChangeControllerWithEvents = function (remoteObjectManager) {
                ReloadOnZoomChangeControllerWithEvents.superclass.constructor.call(this, remoteObjectManager);
            };

            defineClass(ReloadOnZoomChangeControllerWithEvents, ReloadOnZoomChangeController, {
                loadData: function (tilesArray) {
                    // отправляем событие начала загрузки данных
                    this.events.fire('dataloadbefore');
                    ReloadOnZoomChangeControllerWithEvents.superclass.loadData.call(this, tilesArray);
                },
                onDataLoad: function (tilesArray, data) {
                    ReloadOnZoomChangeControllerWithEvents.superclass.onDataLoad.call(this, tilesArray, data);
                    // отправляем событие окончания загрузки данных
                    this.events.fire('dataloadafter');
                }
            });

            provide(ReloadOnZoomChangeControllerWithEvents);
});

defineClass(MyRemoteObjectManager, RemoteObjectManager, {
                _setupDataLoadController: function () {
                    // т.к. на событие подписываемся уже после инициализации ReloadOnZoomChangeControllerWithEvents
                    // то первое событие dataloadbefore мы уже не успеваем поймать, поэтому вызываем его вручную
                    this._onDataLoadBefore();
                    // указываем наш новый загрузчик, который может генерировать нужные события загрузки данных
                    this._dataLoadController = new ReloadOnZoomChangeControllerWithEvents(this);
                    this._dataLoadControllerListener = this._dataLoadController.events.group()
                        .add('statechange', this._onDataLoadControllerStateChange, this)
                        .add('pixelboundschange', this._onDataLoadControllerBoundsChange, this)
                        // будем просто забирать себе эти новые события загрузки данных
                        .add('dataloadbefore', this._onDataLoadBefore, this)
                        .add('dataloadafter', this._onDataLoadAfter, this);
                },
                _onDataLoadBefore: function () {
                    // просто перегенерируем событие как свое
                    this.events.fire('dataloadbefore');
                },
                _onDataLoadAfter: function () {
                    // просто перегенерируем событие как свое
                    this.events.fire('dataloadafter');
                }
});
И все описанные выше манипуляции выполнялись в событии dataloadafter.

Существует-ли какой-то работающий метод получения списка серверных кластеров 
в видимой области карты?
0 комментариев
Подписаться на комментарии к посту