Клуб API Карт

Использование готовых layout'ов балуна кластера для отображения информации о точках

mabpppp
20 января 2015, 12:32

Здравствуйте. Возникла следующая ситуация: сейчас в проекте есть большое количество геообъектов, кластеризация которых осуществляется без использования api яндекс карт. Объекты, попадающие в отображаемую область карты просто запрашиваются с базы и выводятся как обычные метки без использования кластеризатора яндекс карт. Среди объектов есть объекты типа List, суть которых заключается в том, что это одна единственная метка на карте, содержащая в себе информацию о нескольких геообъектах. Причем, эта метка не включается ни в какой из кластеров и отображается отдельно (например, при максимальном приближении карты). На карту она добавляется как обычный ymaps.GeoObject, при щелчке по которому осуществлятся запрос полных данных о всех геообъектах, относящихся к этой метке. Для вывода информации об этих геообъектах хотелось бы использовать layout 'cluster#balloonTwoColumns' с дополнительной кастомизацией. Кластеры с одним элементом для отображения здесь не используются из-за того, что при изменении bounds на карту добавляются только новые объекты, попадающие в зону видимости. При маленьких значениях zoom кластер не меняется (в него уже собраны все возможные значения и он остается тем же) и из-за этого начинаются проблемы с отображением его на карте - он начинает пропадать, хотя содержится в geoObjects карты и его необходимо перерисовывать.

В обработчике callback'а запроса данных о геообъектах использую следующий код:

 



function getMarkerObjectsCallback(data, status, placemark) {
  if (HandleAjaxResponse(data)) {
    ...
    var geoObjects = $.map(data.result, function(geoObject) {
      return new ymaps.GeoObject({
        geometry: {
          type: "Point",
          coordinates: [geoObject.Latitude, geoObject.longitude]
        },
        properties: {
          balloonContentHeader: geoObject.TypeName,
          balloonContentBody: geoObject.Address,
          balloonContentFooter: 'footer'
        }
      });
    });
    placemark.properties.set('geoObjects', geoObjects);
    placemark.options.set('balloonLeftColumnLayout', 'cluster#balloonLeftColumn');
    placemark.options.set('balloonContentLayout', 'cluster#balloonTwoColumns');
  }

}

, где placemark - ссылка на метку на карте, по которой был произведен клик. 

Вопросы в следующем:

  1) Макет отображается нормально, но левая колонка, задаваемая как 'cluster#balloonLeftColumn' пустая. То есть, там есть итемы, при щелчке по которым меняется информация в правой части, но названий у этих итемов нет. Откуда берутся названия этих итемов? Можно ли как то здать их в properties или в options? 

  2) Можно ли вообще использовать такой подход при работе с метками - то есть, использовать для меток layout'ы, созданные не для меток и генерируя поля, на которые эти layout'ы ссылаются? 

5 комментариев
Подписаться на комментарии к посту
2. Можно, но вполне возможно, что не все сразу заработает. Макеты разных сущностей используют разные поля данных.
1. Названия элементов берутся из дочерних геообъектов кластера. Так как эти поля - это не поля кластера, а поля дочерних элементов, то для доступа к ним в кластере используется специальный DataManager. Чтобы решить вашу задачу и вывести собственные названия, я могу порекомендовать или создать полностью собственный макет балуна, как показано в примере
https://tech.yandex.ru/maps/jsbox/2.1/cluster_custom_balloon_content_layout_21
но это может быть сложно. Или использовать пока недокументированную опцию (2.1 недокументированную, в будущих версиях ее планируем раскрыть. В 2.0 эта опция есть) - "leftColumnLayout" - это макет левой колонки. В макете по клику на элемент списка нужно менять значение "activeObject" у состояния. В стандартном макете это выглядит так:
this.getData().state.set('activeObject', geoObjects[index]);

Спасибо за ответ. Если не сложно, можете немного уточнить насчет недокументированной особенности? Мне кажется, что Вы не совсем верно меня поняли. Моя проблема в том, что сгенерированные итемы пусты - обработка клика по ним происходит вполне стандартно - информация в правой части балуна меняется, выбранный итем выделяется цветом. Разметка итемов: 

 ClusterLayout ClusterLayout2

То есть, все работает, только нет подписей у элементов leftColumnLayout. Подписи при работе с кластеризатором генерируются на основе properties.balloonContentHeader каждого из геообъектов в кластере. В моем сценарии эти поля задаются, но генерации подписей не происходит. Можно ли как-то заставить генерирвоаться эти подписи без написания своего собственно макета для leftColumnLayout?

 

Комментарий удалён
В метке-кластере используется специальный DataManager, который позволяет макету через его данные достучаться до данных геообъекта. То есть по сути вызывать clusterPlacemark.properties.get('geoObjects')[n].properties.get('***')... По этому при использовании обычного геообъекта это и не работает. Положить данные геообъекта в ввиде массива хэша и передавать в собственный макет. Но это сложно.

Может быть для вашей задачи подойдет технология RemoteObjectManager? Эта технология сама решает вашу задачу. Получает от сервера информацию о кластерах, а после клика производит загрузку данных для текущей области видимости.

http://dimik.github.io/ymaps/examples/2.1/remote-object-manager/
https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/RemoteObjectManager-docpage/
https://tech.yandex.ru/maps/doc/jsapi/2.1/dg/concepts/remote-object-manager/about-docpage/

Спасибо за ответ. Разобрался с кастомным layout'ом и причинами ошибок. Если объекты, приходящие с сервера не преобразовывать в GeoObject'ы, а использовать из них значения напрямую, то все отлично генерируются. Первую версию сделаю с просто с кастомных layout'ом, потом попробую реализовать то же самое с помощью RemoteObjectManager. 

upd: Попробовал написать свой собственный макет на основе приведенного примера. ...

Предудщий ответ содержит в себе указание на причину ошибки. Спасибо еще раз.