Объекты на карте

Географическим объектам реального мира ставятся в соответствие программные объекты — геообъекты. К геообъектам относятся метки, круги, ломаные, прямоугольники, многоугольники, а также их коллекции.

Каждый геообъект описывается геометрией, которая задается геометрическим типом и географическими координатами.

Базовым классом, реализующим геообъект является GeoObject.

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

var myMap = new ymaps.Map("map", {
        center: [55.76, 37.64],
        zoom: 10
    }),
    myGeoObject = new ymaps.GeoObject({
        geometry: {
            type: "Point",// тип геометрии - точка
            coordinates: [55.8, 37.8] // координаты точки
       }
    });
myMap.geoObjects.add(myGeoObject); // Размещение геообъекта на карте.

Для каждого типа геометрии определен вспомогательный класс, предоставляющий упрощенный синтаксис для создания геообъекта.

// Вспомогательный класс, который можно использовать
// вместо GeoObject c типом геометрии «Point» (см. предыдущий пример)
var myPlacemark = new ymaps.Placemark([55.8, 37.6]);
myMap.geoObjects.add(myPlacemark);

Геометрия геообъекта

В следующей таблице приведен список геометрий, их идентификаторов, используемых в классе GeoObject и соответствующих вспомогательных классов.

Тип геометрии / Идентификатор/ Вспомогательный класс Пример

Точка / Point / Placemark

Создание метки с помощью класса GeoObject:

var myPlacemark = new ymaps.GeoObject({
    geometry: {
    type: "Point",
   coordinates: [55.76, 37.56]
}});
Создание метки c помощью вспомогательного класса Placemark:
var myPlacemark = new ymaps.Placemark([55.8, 37.6]);

Ломаная линия / LineString / Polyline

Создание ломаной с помощью класса GeoObject:

var myPolyline = new ymaps.GeoObject({
    geometry: {
        type: "LineString",
        coordinates: [[...]]
    }
});

Создание ломаной c помощью вспомогательного класса Polyline:

var myPolyline = new ymaps.Polyline(
    [[55.80, 37.30],[55.80, 37.40],[55.70, 37.30],[55.70, 37.40]]
);

Прямоугольник / Rectangle / Rectangle

Создание прямоугольника с помощью класса GeoObject:

var myRectangle = new ymaps.GeoObject({
    geometry: {
        type: "Rectangle",
        coordinates: [[...]]
    }
});

Создание прямоугольника c помощью вспомогательного класса Rectangle:

var myRectangle = new ymaps.Rectangle(
    [[55.70, 37.30],[55.80, 37.40]]
);

Многоугольник / Polygon / Polygon

Создание многоугольника с помощью класса GeoObject:

var myPolygon = new ymaps.GeoObject({
    geometry: {
        type: "Polygon",
        coordinates: [
            [[...]],
            [[...]]
        ]
    }
});

Создание многоугольника c помощью вспомогательного класса Polygon:

var myPolygon = new ymaps.Polygon(
    [
     [[55.75, 37.50],[55.75, 37.71],[55.70, 37.70]],
     [[55.73, 37.58],[55.72, 37.70],[55.70, 37.70]]
    ]
);

Круг / Circle / Circle

Создание круга с помощью класса GeoObject:

var myCircle = new ymaps.GeoObject({
    geometry: {
        type: "Circle",
        coordinates: [55.76, 37.64],
        radius: 10000
    }
});

Создание круга c помощью вспомогательного класса Circle:

var myCircle = new ymaps.Circle([[55.76, 37.64], 10000]);
Тип геометрии / Идентификатор/ Вспомогательный класс Пример

Точка / Point / Placemark

Создание метки с помощью класса GeoObject:

var myPlacemark = new ymaps.GeoObject({
    geometry: {
    type: "Point",
   coordinates: [55.76, 37.56]
}});
Создание метки c помощью вспомогательного класса Placemark:
var myPlacemark = new ymaps.Placemark([55.8, 37.6]);

Ломаная линия / LineString / Polyline

Создание ломаной с помощью класса GeoObject:

var myPolyline = new ymaps.GeoObject({
    geometry: {
        type: "LineString",
        coordinates: [[...]]
    }
});

Создание ломаной c помощью вспомогательного класса Polyline:

var myPolyline = new ymaps.Polyline(
    [[55.80, 37.30],[55.80, 37.40],[55.70, 37.30],[55.70, 37.40]]
);

Прямоугольник / Rectangle / Rectangle

Создание прямоугольника с помощью класса GeoObject:

var myRectangle = new ymaps.GeoObject({
    geometry: {
        type: "Rectangle",
        coordinates: [[...]]
    }
});

Создание прямоугольника c помощью вспомогательного класса Rectangle:

var myRectangle = new ymaps.Rectangle(
    [[55.70, 37.30],[55.80, 37.40]]
);

Многоугольник / Polygon / Polygon

Создание многоугольника с помощью класса GeoObject:

var myPolygon = new ymaps.GeoObject({
    geometry: {
        type: "Polygon",
        coordinates: [
            [[...]],
            [[...]]
        ]
    }
});

Создание многоугольника c помощью вспомогательного класса Polygon:

var myPolygon = new ymaps.Polygon(
    [
     [[55.75, 37.50],[55.75, 37.71],[55.70, 37.70]],
     [[55.73, 37.58],[55.72, 37.70],[55.70, 37.70]]
    ]
);

Круг / Circle / Circle

Создание круга с помощью класса GeoObject:

var myCircle = new ymaps.GeoObject({
    geometry: {
        type: "Circle",
        coordinates: [55.76, 37.64],
        radius: 10000
    }
});

Создание круга c помощью вспомогательного класса Circle:

var myCircle = new ymaps.Circle([[55.76, 37.64], 10000]);

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

var myPlacemark = new ymaps.Placemark(
        [55.754952, 37.615319],
        {},
        {
            draggable: true, // метку можно перемещать
            preset: 'twirl#whiteStretchyIcon'
        }
);
myPlacemark.events.add('dragend', function(e) {
   // Получение ссылки на объект, который был передвинут.
   var thisPlacemark = e.get('target');
   // Определение координат метки
   var coords = thisPlacemark.geometry.getCoordinates();
   // и вывод их при щелчке на метке
   thisPlacemark.properties.set('balloonContent', coords);
});

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

Визуальное редактирование

Географические свойства геообъекта могут быть изменены пользователем в визуальном режиме. Для этого API предоставляет два способа: перемещение геообъекта как целого и визуальный редактор.

За возможность перетаскивания геообъекта как целого отвечает опция draggable, которая может принимать значения true и false.

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

var myPolyline = new ymaps.Polyline(
  [[55.86, 37.84], [55.70, 37.55], [55.8, 37.4]],
  {},
  {
    strokeWidth: 6,
    strokeColor: '#0000FF',
    draggable: true
  }
);

myPolyline.editor.startEditing();
var myPolyline = new ymaps.Polyline(
  [[55.86, 37.84], [55.70, 37.55], [55.8, 37.4]],
  {},
  {
    strokeWidth: 6,
    strokeColor: '#0000FF',
    draggable: true
  }
);

myPolyline.editor.startEditing();

Задание стиля метки

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

Каждому стилю из набора ставится в соответствие уникальный ключ. Для того, чтобы установить нужный стиль, следует указать в качестве значения опции preset соответствующий ключ:

var myPlacemark = new ymaps.Placemark([55.8, 37.6], {}, {
        preset: 'twirl#redIcon'
    });
var myPlacemark = new ymaps.Placemark([55.8, 37.6], {}, {
        preset: 'twirl#redIcon'
    });
Примечание. Стилем по умолчанию является 'twirl#blueIcon'.

В качестве значка метки можно использовать также собственное изображение. Для этого необходимо в опции iconImageHref указать URL графического файла значка. При необходимости можно указать опции iconImageSize и iconImageOffset — размер изображения и его сдвиг относительно точки привязки соответственно.

var myPlacemark = new ymaps.Placemark([55.76, 37.56], {}, {
        iconImageHref: '/maps/doc/jsapi/2.0/examples/images/myIcon.gif',
        iconImageSize: [30, 42],
        iconImageOffset: [-3, -42]
    });
var myPlacemark = new ymaps.Placemark([55.76, 37.56], {}, {
        iconImageHref: '/maps/doc/jsapi/2.0/examples/images/myIcon.gif',
        iconImageSize: [30, 42],
        iconImageOffset: [-3, -42]
    });

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

Ниже приведен пример спрайта, содержащего три изображения:

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

  • iconImageCliptRect — позиция нужного изображения в спрайте. Определяется пиксельными координатами левого верхнего и правого нижнего углов прямоугольника, в котором размещается изображение.
  • iconImageHref — URL спрайта;

При необходимости можно указать опции iconImageSize и iconImageOffset.

var myPlacemark1 = new ymaps.Placemark([55.85, 60.64], {}, {
        iconImageClipRect: [[0,0], [26, 46]],
        iconImageHref: '/maps/doc/jsapi/2.0/dg/images/sprite.png',
        iconImageSize: [15, 27],
        iconImageOffset: [-15, -27]
    });

var myPlacemark2 = new ymaps.Placemark([55.85, 32.64], {}, {
        iconImageClipRect: [[34,0], [62, 46]],
        iconImageHref: '/maps/doc/jsapi/2.0/dg/images/sprite.png',
        iconImageSize: [26, 46],
        iconImageOffset: [-26, -46]
    });

var myPlacemark3 = new ymaps.Placemark([55.85, 1.0], {}, {
        iconImageClipRect: [[69,0], [97, 46]],
        iconImageHref: '/maps/doc/jsapi/2.0/dg/images/sprite.png',
        iconImageSize: [35, 63],
        iconImageOffset: [-35, -63]
    });
var myPlacemark1 = new ymaps.Placemark([55.85, 60.64], {}, {
        iconImageClipRect: [[0,0], [26, 46]],
        iconImageHref: '/maps/doc/jsapi/2.0/dg/images/sprite.png',
        iconImageSize: [15, 27],
        iconImageOffset: [-15, -27]
    });

var myPlacemark2 = new ymaps.Placemark([55.85, 32.64], {}, {
        iconImageClipRect: [[34,0], [62, 46]],
        iconImageHref: '/maps/doc/jsapi/2.0/dg/images/sprite.png',
        iconImageSize: [26, 46],
        iconImageOffset: [-26, -46]
    });

var myPlacemark3 = new ymaps.Placemark([55.85, 1.0], {}, {
        iconImageClipRect: [[69,0], [97, 46]],
        iconImageHref: '/maps/doc/jsapi/2.0/dg/images/sprite.png',
        iconImageSize: [35, 63],
        iconImageOffset: [-35, -63]
    });
Примечание. С помощью спрайтов можно задавать изображения также и для других объектов, добавляемых на карту (например, для кластеров или элементов управления).

Использование технологии спрайтов позволяет сократить число HTTP-запросов к серверу, так как вместо большого числа изображений загружается только одно.

Подробнее о задании стиля для иконок меток см. в примере.

Коллекции геообъектов

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

В API Яндекс.Карт реализовано два вида коллекций: упорядоченные (GeoObjectArray) и неупорядоченные (GeoObjectCollection). Первые реализованы на основе массивов, вторые — на основе двусвязных списков.

Геообъект может принадлежать только одной коллекции. При добавлении геообъекта, принадлежащего одной коллекции, в другую коллекцию, он будет удален из первой.

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

var coords = [
    [55.75, 37.50],[55.75, 37.71],[55.70, 37.70]
],
    myCollection = new ymaps.GeoObjectCollection({}, {
       preset: 'twirl#redIcon', //все метки красные
       draggable: true // и их можно перемещать
    });
// или myCollection = new ymaps.GeoObjectArray(...);

for (var i = 0; i < coords.length; i++) {
    myCollection.add(new ymaps.Placemark(coords[i]));
}

myMap.geoObjects.add(myCollection);

// При клике на карту все метки будут удалены.
myCollection.getMap().events.add('click', function() {
    myCollection.removeAll();
});
var coords = [
    [55.75, 37.50],[55.75, 37.71],[55.70, 37.70]
],
    myCollection = new ymaps.GeoObjectCollection({}, {
       preset: 'twirl#redIcon', //все метки красные
       draggable: true // и их можно перемещать
    });
// или myCollection = new ymaps.GeoObjectArray(...);

for (var i = 0; i < coords.length; i++) {
    myCollection.add(new ymaps.Placemark(coords[i]));
}

myMap.geoObjects.add(myCollection);

// При клике на карту все метки будут удалены.
myCollection.getMap().events.add('click', function() {
    myCollection.removeAll();
});

Класс коллекции, которая может быть размещена на карте, должен реализовывать интерфейс IMapObjectCollection. Все упомянутые коллекции реализуют этот интерфейс и могут быть отображены на карте.

Кластеры

Точечные геообъекты могут находиться настолько близко друг другу, что на каком-то масштабе их метки начинают накладываться друг на друга. В этом случае пользователю приходится тщательно «прицеливаться», чтобы попасть курсором мыши на видимый фрагмент нужной метки. Существует даже специальный термин, описывающий эффекты такого рода — pixel hunting (пиксель-хантинг).

var coords = [
    [56.023, 36.988],
    [56.025, 36.981],
    [56.020, 36.981],
    [56.021, 36.983],
    [56.027, 36.987]
];

var myCollection = new ymaps.GeoObjectCollection();

for (var i = 0; i<coords.length; i++) {
    myCollection.add(new ymaps.Placemark(coords[i]));
}

myMap.geoObjects.add(myCollection);
var coords = [
    [56.023, 36.988],
    [56.025, 36.981],
    [56.020, 36.981],
    [56.021, 36.983],
    [56.027, 36.987]
];

var myCollection = new ymaps.GeoObjectCollection();

for (var i = 0; i<coords.length; i++) {
    myCollection.add(new ymaps.Placemark(coords[i]));
}

myMap.geoObjects.add(myCollection);

Если метки находятся в одной точке и размеры их иконок совпадают, то наведение на перекрытые метки невозможно в принципе.

Стандартным способом решения проблемы является объединение близко расположенных объектов в группу (кластер) и использование для группы специальной кластерной иконки. Часто на иконке кластера указывается число содержащихся в нем элементов.

Для кластеризации объектов в API Яндекс.Карт используется класс Clusterer.

var myGeoObjects = [];

for (var i = 0; i<coords.length; i++) {
  myGeoObjects[i] = new ymaps.GeoObject({
    geometry: {
      type: "Point",
      coordinates: coords[i]
    }
  });
}

var myClusterer = new ymaps.Clusterer();
myClusterer.add(myGeoObjects);
myMap.geoObjects.add(myClusterer);
var myGeoObjects = [];

for (var i = 0; i<coords.length; i++) {
  myGeoObjects[i] = new ymaps.GeoObject({
    geometry: {
      type: "Point",
      coordinates: coords[i]
    }
  });
}

var myClusterer = new ymaps.Clusterer();
myClusterer.add(myGeoObjects);
myMap.geoObjects.add(myClusterer);

При увеличении масштаба кластер визуально распадается на отдельные метки и/или другие кластеры.

При щелчке на иконке кластера может произойти либо увеличение коэффициента масштабирования либо открытие балуна, в котором будет отображен список геообъектов кластера. Это поведение контролируется с помощью опции clusterDisableClickZoom (true/false).

var myGeoObjects = [];

for (var i = 0; i < coords.length; i++) {
  myGeoObjects[i] = new ymaps.GeoObject({
    geometry: {
      type: "Point",
      coordinates: coords[i]
    },
    properties: {
      clusterCaption: 'Геообъект № '+(i+1),
      balloonContentBody: 'Текст балуна № '+(i+1)
    }
  });
}

var myClusterer = new ymaps.Clusterer(
  {clusterDisableClickZoom: true}
);
myClusterer.add(myGeoObjects);
myMap.geoObjects.add(myClusterer);
var myGeoObjects = [];

for (var i = 0; i < coords.length; i++) {
  myGeoObjects[i] = new ymaps.GeoObject({
    geometry: {
      type: "Point",
      coordinates: coords[i]
    },
    properties: {
      clusterCaption: 'Геообъект № '+(i+1),
      balloonContentBody: 'Текст балуна № '+(i+1)
    }
  });
}

var myClusterer = new ymaps.Clusterer(
  {clusterDisableClickZoom: true}
);
myClusterer.add(myGeoObjects);
myMap.geoObjects.add(myClusterer);
Примечание. Если при отображении кластера коэффициент масштабирования карты является максимальным, то кластер не будет распадаться на отдельные метки при щелчке на его маркере. В этом случае независимо от значения параметра clusterDisableClickZoom всегда будет открываться балун.

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

Использование кластеризатора позволяет значительно увеличить производительность при отображении большого количества геообъектов в браузере.

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