Разработка клиентской части

Создание менеджера и добавление в него объектов

Для создания менеджера используется класс ObjectManager:

// Создание менеджера объектов.
var objectManager = new ymaps.ObjectManager();

// После создания менеджера ему следует передать JSON-описание объектов.
objectManager.add(/* JSON-описание объектов */);

// Отобразим объекты на карте.
myMap.geoObjects.add(objectManager);

Если JSON-описание размещается на сервере, то перед добавлением в менеджер это описание следует предварительно загрузить на сторону клиента, например с помощью функции jQuery.getJSON():

jQuery.getJSON('https://my-domain.ru/data.json', function (json) {
    objectManager.add(json);  
});

Открыть пример в песочнице

Формат JSON-описания объектов

Описание объектов должно представлять собой GeoJSON-подобную структуру:

{
  "type": "FeatureCollection",
  "features": [
      ... 
  ]
}

Поле features – это массив объектов, которые нужно показать на карте. Каждый объект должен содержать поля:

Поле Тип Описание
type* String Поле должно всегда иметь значение "Feature".
id* Number Уникальный идентификатор объекта. Разработчик должен сформировать идентификаторы объектов самостоятельно.
"id": 0
geometry* Object
Геометрия объекта. Содержит поля:
  • type – тип объекта. Доступные значения: «Point» (метка), «LineString» (линия), «Cicrle» (круг), «Polygon» (многоугольник).
  • coordinates – координаты объекта. Следует задавать в той последовательности, которая указана в параметре coordorder (если параметр не задан, используется последовательность «широта, долгота»).
  • radius (только для объекта с типом «Circle») – радиус круга в метрах.
Примеры задания геометрии

Для метки:

"geometry": {
    "type": "Point",
    "coordinates": [55.780898, 37.642889]
}

Для линии:

"geometry": {
    "type": "LineString",
    "coordinates": [
        [55.780898, 37.642889],
        [55.780898, 37.642889]
    ]
}

Для многоугольника:

"geometry": { 
    "type": "Polygon",
    "coordinates": [
        [55.801280971180454, 37.552642822265625],
        [55.81285742969946, 37.518310546875],
        [55.8367712028016, 37.540283203125],
        [55.801280971180454, 37.552642822265625]
    ]
}

Для круга:

"geometry": {
    "type": "Circle",
    "coordinates": [55.780898, 37.642889],
    "radius": 1000
}

Для объекта-кластера:

"geometry": {
    "type": "Point",
    "coordinates": [55.780898, 37.642889]
}
properties Object

Свойства объекта (например, содержимое балуна или метки). Список доступных свойств описан в классе GeoObject. Также в свойствах могут быть указаны произвольные поля.

Пример:
"properties": {
    "balloonContent": "Текст балуна",
    "clusterCaption": "Метка 1",
    "hintContent": "Текст подсказки",
    "myDescription": "Произвольное описание"
}
options Object

Опции объекта (например, стиль метки или цвет линии). Список доступных опций описан в классе GeoObject.

"options": {
    "preset": "islands#yellowIcon"
}

* Обязательное поле.

Пример JSON-описания объектов
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "id": 0,
      "geometry": {
        "type": "Point",
        "coordinates": [55.831903, 37.411961]
      },
      "properties": {
        "balloonContent": "Магазин на углу",
        "data": {
          "organization": "shop",
          "open": "9am - 9pm"
        }
      }
    },
    {
      "type": "Feature",
      "id": 1,
      "geometry": {
        "type": "Point",
        "coordinates": [55.763338, 37.565466]
      },
      "properties": {
        "balloonContent": "Аптека",
         "data": {
          "organization": "pharmacy",
          "open": "8am - 10pm"
        }
      }
    }
  ]
}
Внимание. Идентификатор однозначно определяет каждый объект менеджера. По идентификатору можно получить доступ к нужному объекту и, например, изменить его свойства или опции. Идентификаторы объектов являются обязательным полем, и разработчик должен сформировать их самостоятельно.

Получение доступа к объектам менеджера

Загруженные объекты сохраняются в коллекции objectManager.ObjectCollection. Ссылка на эту коллекцию содержится в поле ObjectManager.objects.

Для получения доступа к объектам менеджера предназначены методы:

  • each() – осуществяет проход по объектам менеджера;
  • getAll() – возвращает массив объектов менеджера;
  • getById() – возвращает объект по его идентификатору;
  • getLength() – возвращает количество объектов в менеджере;
  • setObjectOptions – позволяет задать опции объектам.

Список всех методов приведен в справочнике.

Обратите внимание, объекты добавляются в менеджер в асинхронном режиме. Это означает, что на момент вызова этих методов объекты могут быть еще не добавлены в коллекцию. Для избежания ошибок рекомендуется отслеживать события на объектах менеджера и вызывать нужные методы в обработчиках этих событий. Например:

function onObjectClick (e) {
   // objectId – идентификатор объекта, на котором произошло событие.
   var objectId = e.get('objectId'),  
       object = objectManager.objects.getById(objectId);
   // Выведем информацию об объекте.
   console.log('Тип объекта: ' + object.geometry.type);
   console.log('Координаты объекта: ' + object.geometry.coordinates);
}

// Подписываемся на событие клика по объекту.
objectManager.objects.events.add(['click'], onObjectClick);

Кластеризация объектов

ObjectManager позволяет кластеризовать метки. Чтобы включить кластеризацию, конструктору менеджера следует передать опцию clusterize: true.

Объекты-кластеры менеджер размещает в коллекции objectManager.ClusterCollection. Ссылка на коллекцию содержится в поле ObjectManager.clusters.

Внимание. Коллекция кластеров доступна только на чтение. Менеджер не позволяет самостоятельно добавлять или удалять кластеры из коллекции.

Структура объекта-кластера

Объект-кластер представляет собой JSON-структуру с полями:

  • id – идентификатор кластера. Генерируется менеджером.
  • number – количество меток в кластере.
  • geometry – геометрия. Представляет собой объект с полями: type и coordinates.
  • properties – описание данных кластера. В поле properties.geoObjects содержится массив меток, входящих в кластер.
  • options – опции кластера. Необязательное поле.

Операции с коллекцией кластеров

Для работы с коллекцией кластеров доступны методы:

  • each() – проход по объектам-кластерам;
  • getAll() – возвращает список всех объектов-кластеров в коллекции;
  • getById() – возвращает объект-кластер по идентификатору (идентификаторы кластеров генерирует менеджер);
  • getLength() – количество объектов-кластеров в коллекции;
  • setClusterOptions() – задает опции для объекта-кластера.

Список всех методов см. в справочнике.

Объекты-кластеры создаются в асинхронном режиме. Это означает, что на момент вызова указанных методов объекты-кластеры могут быть еще не созданы (то есть не добавлены в коллекцию). Для избежания ошибок рекомендуется отслеживать события на коллекции кластеров и вызывать нужные методы в обработчиках этих событий. Например:
// Создадим менеджер и включим использование кластеризации.
var objectManager = new ymaps.ObjectManager({
        clusterize: true
    });

// Загрузим JSON-описание и добавим его в менеджер.
jQuery.getJSON('https://my-domain.ru/data.json', function (json) {
    objectManager.add(json);  
});

// Добавим менеджер на карту.
myMap.geoObjects.add(objectManager);

// Выведем количество объектов-кластеров.
console.log(objectManager.clusters.getLength()); // --> 0, так как
                                                 // объекты-кластеры еще не были созданы.

// На этот раз выведем количество объектов-кластеров внутри обработчика события. 
function onAddCluster (e) {
    console.log(objectManager.clusters.getLength()); // --> 1, 2, 3..
}

// Подпишемся на событие добавления кластера в коллекцию.
objectManager.clusters.events.add(['add'], onAddCluster);

Поиск объектов

В примере ниже осуществляется поиск тех объектов менеджера, для которых не задано содержимое балуна (поле properties.balloonContent):

function onObjectCollectionAdd (e) {
    // object – объект, который был добавлен в коллекцию.
    var object = e.get('child');
    if ((!object.properties) || (!object.properties.balloonContent)) {
        console.log("Для объекта с идентификатором " + object.id + " не задано содержимое балуна.");
    }
}

// Подписываемся на событие добавления объекта в менеджер.
objectManager.objects.events.add(['add'], onObjectCollectionAdd);
Открыть другой пример в песочнице

Фильтрация объектов

ObjectManager позволяет использовать фильтрацию объектов по различным признакам. Например, можно отобразить только объекты красного цвета или только те объекты, идентификатор которых больше 10.

Для фильтрации объектов предназначен метод setFilter(). В качестве параметра ему необходимо передать строку, содержащую условие отбора объектов, либо функцию-фильтр, которая должна возвращать true или false.

// Пропустить объекты, id которых меньше 100.
objectManager.setFilter('id > 100');

// На карте будут отображаться только объекты с заданными типами.
objectManager.setFilter('properties.type == "кафе" || properties.type == "аптека"');

// Можно задавать функцию-фильтр.
objectManager.setFilter(function (object) {
  return object.properties.name != 'Тот, кого нельзя показывать.';
});

Открыть другой пример в песочнице

Задание опций объектам

API позволяет динамически задавать опции объектам менеджера. Например, можно изменить цвет меток или толщину линий.

Опции можно задавать как для одиночного объекта менеджера, так и сразу для всей коллекции объектов.

Задание опций для одиночного объекта

Чтобы задать опции одиночным объектам менеджера, нужно использовать метод setObjectOptions(). Методу нужно передать два аргумента: идентификатор объекта и нужные опции. Список опций, которые можно задавать для объектов менеджера, приведены в классе GeoObject.

// Задаем стиль для объекта с идентификатором 4.
objectManager.objects.setObjectOptions(4, {
    preset: 'islands#greenDotIcon'
});
Внимание. Менеджер объектов не учитывает опцию геообъектов visible. При задании этой опции она будет проигнорирована.

Если нужно задать опцию для объекта-кластера, используется метод setClusterOptions(). Методу также нужно передать идентификатор кластера и нужные опции. Обратите внимание, что идентификаторы кластеров генерируются менеджером. Узнать идентификатор нужного кластера можно из объекта-события, подписавшись на события коллекции кластеров.

function onClusterCollectionAdd (e) {
   var cluster = e.get('child');
   // Для кластеров, в состав которых входит больше 10 меток,
   // зададим значок красного цвета.
   if (cluster.numbers > 10) {
       objectManager.clusters.setClusterOptions(cluster.id, {
           preset: 'islands#redClusterIcons'
       });
   }
}
// Подписываемся на событие добавления кластера в коллекцию.
objectManager.clusters.events.add(['add'], onClusterCollectionAdd);

Подробнее о событиях менеджера

Задание опций всей коллекции объектов

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

Для задания опций коллекции используется метод set(). В качестве параметров методу нужно передать объект с опциями:

// Задаем опции для коллекции одиночных объектов (опция применится для меток).
objectManager.objects.options.set({ preset: 'islands#yellowIcon' });

// Задаем опции для объектов-кластеров.
objectManager.clusters.options.set({ preset: 'islands#yellowClusterIcons' });
Внимание. Менеджер объектов не учитывает опцию visible. При задании этой опции она будет проигнорирована.

Обработка событий на объектах

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

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

Пример 1. Отслеживание событий на одиночных объектах:

// При клике на метке изменяем цвет ее иконки на желтый.
function onObjectEvent (e) {
  var objectId = e.get('objectId'),
      objectGeometry = objectManager.objects.getById(objectId).geometry.type;
  // Если событие произошло на метке, изменяем цвет ее иконки.
  if (objectGeometry === 'Point') {
    objectManager.objects.setObjectOptions(objectId, {
      preset: 'islands#yellowIcon'
    });
  }
}

// Назначаем обработчик событий на коллекцию объектов менеджера.   
objectManager.objects.events.add(['click'], onObjectEvent);

Пример 2. Отслеживание событий на объектах-кластерах:

// При наведении указателя мыши на метки их иконки окрашиваются в желтый.
// При покидании указателя цвет иконок окрашивается в голубой.
function onClusterEvent (e) {
  var objectId = e.get('objectId');
  if (e.get('type') === 'mouseenter') {
    objectManager.clusters.setObjectOptions(objectId, {
      preset: 'islands#yellowIcon'
    });
  } else {
    objectManager.clusters.setObjectOptions(objectId, {
      preset: 'islands#blueIcon'
    });
  }  
}

// Назначаем обработчик событий для коллекции объектов-кластеров менеджера.
objectManager.clusters.events.add(['mouseenter', 'mouseleave'], onClusterEvent);
Открыть пример в песочнице

Удаление обработчиков события

Для удаления обработчиков используется метод remove(). Первым аргументом необходимо передать тип события (или список типов), вторым аргументом — ссылку на функцию-обработчик, которую необходимо удалить.

// Подпишемся на несколько событий объектов-кластеров.
objectManager.clusters.events.add(['mouseenter', 'click', 'mouseleave'], onClusterEvent);
// Удалим две подписки.
objectManager.clusters.events.remove(['click', 'mouseleave'], onClusterEvent);