Клуб API Карт

Отображение большого количества меток

Пост в архиве.

Добрый день.

Дано:API 2.1, множество обьектов на карте(в пределах видимых границ на 10-м зуме около 30 тыс. обьектов)

Проблема: При изменении зума появляются тормоза при прорисовке placemark-ов

 

Вот собственно карта http://bit.ly/VmXRRf.

Тормоза начинаются на 15 зуме, когда нужно прорисовывать найбольшее количество обьектов.

Использовать кластеризацию на клиенте я не рискнул:-). Кластеры приходят с сервера, из-за этого при каждом зуме в новую область приходится перерисовывать все объекты в видимой области.

Вопрос: Как можно в этом случае обойтись без перерисовки или хотябы добиться того чтобы не все элементы перерисовывались?


p.s. в процессе обнаружилось что метод each у коллекции каким-то неведомым способом пропускает некотрые элеметны коллекции. К примеру код

myCollection.each(function(object){ myCollection.remove(object)}); не удаляет все элементы.

9 комментариев

Сначала по поводу each - он не работает, потому что вы по ходу дела изменяете исходную коллекцию.

Вы можете хранить идентификаторы объектов, добавленных на карту. При загрузке очередной порции объектов сверяйте эти идентификаторы и если объект при зуме остался на месте, не перерисовывайте его.

Спасибо, а каким образом производить сверку идентификаторов? Я так и хотел сделать, но через each не получается.

Я добился того что имею новые обьекты, которые нужно нарисовать и старые, которые нужно удалить и те которые останутся без изменения. Но тут возникает проблема как удлаить ненужные обьекты? Пробовал через myCollection.remove(oldObject); но всё равно обьект отсаётся на карте, но в коллекции его нет.

А что такое myCollection? Из map.geoObjects удаляете?

А в каком из ваших исходников можно найти код, который удаляет элементы из коллекции?

Как вы добавляете объекты на карту? Если вы добавляете объект в коллекцию, а потом этот объект отдельно добавляете на карту, то он автоматически пропадет из коллекции.

В самом начале после инициализации карты создаю коллекцию

var yandexMap = new ymaps.Map(.....;
geoObjectsCollection = new ymaps.GeoObjectCollection();
yandexMap.geoObjects.add(geoObjectsCollection); 
Дальше идет аякс запрос на получение элементов, после успешного результата запроса произвожу следующие манипуляции(метод установки элементов на карту()):
this.setObjectsCollection = function (tiles, zoom) {
        if (options.zoom != zoom) {
            geoObjectsCollection.removeAll();// Вот тут не знаю как сделать, чтобы вместо удаления всех элементов, пройтись по существующим  оставить нужные и удалить ненужные
            options.zoom = zoom;
            geoIdsCache[zoom] = {};
            if (typeof (geoObjectsCache[zoom]) != 'undefined') {
                tiles = $.extend(true, geoObjectsCache[zoom], tiles);
            }
        }

        $.each(tiles, function (i, tile) {
            self.issetAndCreate(geoObjectsCache, tile['z'], {});
            geoObjectsCache[tile['z']][i] = tile;
            self.issetAndCreate(geoIdsCache, tile['z'], {});

            $.each(tile['objects'], function (i, object) {
                if (!self.issetKey(geoIdsCache[zoom], i)) {
                    geoObjectsCollection.add(self.createPlacemark(object, i));
                    geoIdsCache[tile['z']][i] = object['nb'];
                }
            });
        });
    }

var objectsToDelete = [];

geoObjectCollection.each(function (obj) {

    if (needToDelete(obj)) {

        objectsToDelete.push(obj);

    }

});

for (var i = 0, l = objectsToDelete; i < l; i++) {

    geoObjectCollection.remove(objectsToDelete[i]);

}

Спасибо огоромное. Только взглянув на ваш код я понял смысл слов

"Сначала по поводу each - он не работает, потому что вы по ходу дела изменяете исходную коллекцию."

 Как я могу вас отблагодарить?

Никак) Рада, что удалось помочь)

У вас там еще "стандартная" проблема

если увеличить зум, а потом уменьшить - будет смерть.

В общем случае данные полученые на более крупых зумах не надо показывать на более высоких, кроме случаев когда они "опять" прийдут к сервера.

Это особо хорошо работает когда вы сами с сервера кластера присылаете, хотя.. и клиенсткая кластеризация тут лишней не будет.