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

Общие сведения

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

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

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

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

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

// Размещение геообъекта на карте.
myMap.geoObjects.add(myGeoObject); 

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

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

Список вспомогательных классов приведен ниже.

Типы геобъектов

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

Геообъект

Пример

Метка (тип геометрии: «Point»)

Создание метки с помощью класса 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»)

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

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

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

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

Прямоугольник (тип геометрии: «Rectangle»)

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

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

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

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

Многоугольник (тип геометрии: «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»)

Создание круга с помощью класса 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: 'islands#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();

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

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

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

var myPlacemark = new ymaps.Placemark([55.8, 37.6], {}, {
    preset: 'islands#redIcon'
});

Примечание

Стилем по умолчанию является 'islands#blueIcon'.

Задание собственного изображения для метки

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

  • iconLayout — значение 'default#image' или 'default#imageWithContent' для меток соответственно без текста и с текстом поверх картинки;
  • iconImageHref — URL графического файла значка;
  • iconImageSize — размер значка в пикселах;
  • iconImageOffset — сдвиг значка в пикселах относительно точки привязки (задается, если "ножка" значка не находится в левом верхнем углу изображения);
  • iconContentOffset — для меток с текстом сдвиг текста относительно точки привязки метки.


var myPlacemark = new ymaps.Placemark([55.76, 37.56], {}, {
    iconLayout: 'default#image',
    iconImageHref: '/maps/d../../jsapi/doc/2.1/examples/_images/myIcon.gif',
    iconImageSize: [30, 42],
    iconImageOffset: [-3, -42]
});

Использование CSS-спрайтов

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

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

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

  • iconLayout — макет иконки. Для опции должно быть установлено значение 'default#image';
  • iconImageCliptRect — позиция нужного изображения в спрайте. Определяется пиксельными координатами левого верхнего и правого нижнего углов прямоугольника, в котором размещается изображение;
  • iconImageHref — URL спрайта;
  • iconImageSize — размер значка в пикселах;
  • iconImageOffset — сдвиг значка в пикселах относительно точки привязки (задается, если "ножка" значка не находится в левом верхнем углу изображения).


var myPlacemark1 = new ymaps.Placemark([55.85, 60.64], {}, {
    iconLayout: 'default#image',
    iconImageClipRect: [[0,0], [26, 46]],
    iconImageHref: '_images/sprite.png',
    iconImageSize: [15, 27],
    iconImageOffset: [-15, -27]
});

var myPlacemark2 = new ymaps.Placemark([55.85, 32.64], {}, {
    iconLayout: 'default#image',
    iconImageClipRect: [[34,0], [62, 46]],
    iconImageHref: '_images/sprite.png',
    iconImageSize: [26, 46],
    iconImageOffset: [-26, -46]
});

var myPlacemark3 = new ymaps.Placemark([55.85, 1.0], {}, {
    iconLayout: 'default#image',
    iconImageClipRect: [[69,0], [97, 46]],
    iconImageHref: '_images/sprite.png',
    iconImageSize: [35, 63],
    iconImageOffset: [-35, -63]
});

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

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

Метки с пиктограммами

API позволяет добавлять на карту метки с пиктограммами (Glyphicons).

Внимание

Для использования пиктограмм необходимо подключить CSS-стили Bootstrap:

 <link rel="stylesheet" type="text/css" href="https://yastatic.net/bootstrap/3.3.4/css/bootstrap.min.css">

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

  • preset — тип метки. Указывается с префиксом 'glyph'. Например, 'islands#glyphCircleIcon' (метка в виде круга) или 'islands#glyphIcon' (метка с хвостиком). Также через данную опцию можно задать цвет метки. Например, 'islands#redGlyphIcon'.
  • iconGlyph — название пиктограммы. Список доступных пиктограмм приведены на странице Glyphicons. Обратите внимание, что название задается без префикса 'glyph'. Например, 'asterisk' или 'plus'.
  • iconGlyphColor (необязательная опция) — цвет пиктограммы. Цвет может быть задан тремя способами: с помощью ключевого слова и в форматах Hex и RGB. Если опция не задана, по умолчанию используется пиктограмма черного цвета.
  • iconColor (необязательная опция) — цвет метки. Цвет может быть задан тремя способами: с помощью ключевого слова и в форматах Hex и RGB. По умолчанию используется метка голубого цвета.

Ниже показан пример создания меток с пиктограммами:


var glyphIcon1 = new ymaps.Placemark([55.684, 37.738], {}, {
    preset: 'islands#redGlyphIcon',            
    iconGlyph: 'music',
    iconGlyphColor: 'red'
});

var glyphIcon2 = new ymaps.Placemark([55.684, 37.7383], {}, {
    preset: 'islands#glyphIcon', 
    iconGlyph: 'home',
    iconGlyphColor: 'blue'
}); 

var glyphIcon3 = new ymaps.Placemark([55.684, 37.7383], {}, {
    preset: 'islands#yellowGlyphCircleIcon',
    iconGlyph: 'glass',
});

myMap.geoObjects
  .add(glyphIcon1)
  .add(glyphIcon2)
  .add(glyphIcon3);

Метки-диаграммы

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

Примечание

Диаграммы рисуются с использованием технологии Canvas, поэтому они не будут отображаться в браузерах, которые не поддерживают Canvas (в частности, IE8).

Как задать диаграмму для значка метки

Чтобы установить диаграмму для значка метки, этой метке нужно задать опцию iconLayout со значением 'default#pieChart'. Кроме того, метке нужно задать свойство data ― на основе его содержимого будет формироваться диаграмма. Это свойство должно содержать описание секторов диаграммы. Каждый сектор описывается JSON-объектом с полями:

  • weight — вес сектора диаграммы. Может принимать произвольное значение. Например, '120'.
  • color — цвет сектора. Цвет указывается в шестнадцатеричном коде (например, '#FFFFFF') или с помощью названия, поддерживаемого в CSS (например, 'red').

Пример:

data: [
    // Вес красного сектора.
    { weight: 52, color: 'red' },
    // Вес зеленого сектора.
    { weight: 42, color: '#880011' },
    // Вес желтого сектора.
    { weight: 23, color: '#035201' },
    // Вес синего сектора.
    { weight: 12, color: '#002f55' }
]

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

Пример задания диаграммы для значка метки:


var myPlacemark = new ymaps.Placemark([-25.702, 133.527], {
    // На основе этих данных будет
    // сформирована диаграмма.
    data: [
        { weight: 52, color: '#FFA002' },
        { weight: 42, color: '#880011' },
        { weight: 23, color: '#035201' },
        { weight: 12, color: '#002f55' }
    ]
}, {
    // Устанавливаем для значка метки
    // макет диаграммы.
    iconLayout: 'default#pieChart',
});

myMap.geoObjects.add(myPlacemark);

Внимание

Если для метки не указано свойство data, то возникнет ошибка и метка не будет отображена на карте.

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


var myPlacemark = new ymaps.Placemark([-25.702, 133.527], {
    data: [
        { weight: 720, color: '#FFA002' },
        { weight: 420, color: '#880011' },
        { weight: 230, color: '#035201' },
        { weight: 120, color: '#002f55' }
    ],
    balloonContent: 'Разновидность животных:</br>'+
        'оранжевый – птицы, ' +
        'красный – пресмыкающиеся, ' +
        'зеленый – млекопитающие, ' +
        'синий – земноводные.',
    // Подпись к диаграмме.
    iconCaption: 'Животный мир Австралии',
    // Оставляем центр диаграммы пустым.
    iconContent: ''
}, {
    // Устанавливаем для значка метки
    // макет диаграммы.
    iconLayout: 'default#pieChart',
    // Радиус диаграммы.
    iconPieChartRadius: 25,
    // Радиус центрального сектора диаграммы.
    iconPieChartCoreRadius: 10
});

myMap.geoObjects.add(myPlacemark);

При клике на диаграмме откроется балун с заданным содержимым.

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

Как установить диаграмму для значка кластера

Диаграмму можно установить также и для значка кластера. В этом случае диаграмма будет строиться на основе цветов меток, входящих в состав этого кластера. Такая диаграмма отображает распределение меток в кластере по цветам.

Чтобы установить диаграмму для кластера, ему нужно задать опцию clusterIconLayout со значением 'default#pieChart'. Обратите внимание, что свойство data задавать не нужно. Оно будет игнорироваться.


// Создаем метки, которые будут
// входить в состав кластера.

// Метка голубого цвета.
var myPlacemark1 = new ymaps.Placemark([55.85, 60.64]);
// Метка розового цвета.    
var myPlacemark2 = new ymaps.Placemark([55.85, 32.64], {}, {
    preset: 'islands#pinkCircleIcon'
});
// Желтая метка.    
var myPlacemark3 = new ymaps.Placemark([55.85, 1.0], {}, {
    preset: 'islands#yellowIcon'
});
    
// Создаем кластер.
var clusterer = new ymaps.Clusterer({
   /*
    Задаем для значка кластера макет диаграммы.
    Обратите внимание, что тут могут быть
    заданы только опции диаграммы — радуис,
    толщина линий и др.
    Чтобы задать подпись к диаграмме
    или изменить текст в центре, нужно
    переопределить функцию createCluster.
    */
    clusterIconLayout: 'default#pieChart'
});

// Добавляем метки в кластер.
clusterer.add(myPlacemark1)
    .add(myPlacemark2)
    .add(myPlacemark3); 

myMap.geoObjects.add(clusterer);

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

Внимание

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

При клике на диаграмме увеличится масштаб карты и кластер разобьется на одиночные метки, входящие в состав этого кластера. Чтобы отключить это поведение, следует выставить опцию clusterDisableClickZoom в true. В этом случае при клике на диаграмме будет открываться балун.

Если в составе кластера есть метки с собственными изображениями, то на диаграмме эти метки будут принадлежать сектору голубого цвета. Чтобы изменить цвет сектора для таких меток, им следует задать опцию iconColor с нужным цветом.

Как построить диаграмму для кластера на основе произвольных данных

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

Ниже показано, как создать диаграмму для кластера на основе произвольных данных:

var myMap = new ymaps.Map('map', {
    center: [-10.702218, 57.527526],
    zoom: 0,
    controls: []
});
    
// Создаем кластер.
var clusterer = new ymaps.Clusterer({});
    
// Метки, входящие в состав кластера.
var myPlacemark1 = new ymaps.Placemark([55.85, 32.64], {
    // Задаем содержимое балуна метки.
    // Это содержимое будет отображаться при клике по кластеру.
    balloonContentHeader: 'Метка № 1',
    balloonContentBody: 'Не мысля гордый свет забавить,</br>' +
        'Вниманье дружбы возлюбя,</br>' +
        'Хотел бы я тебе представить</br>' +
        'Залог достойнее тебя,'
});
    
var myPlacemark2 = new ymaps.Placemark([55.15, 32.14], {
    balloonContentHeader: 'Метка № 2',
    balloonContentBody: 'Достойнее души прекрасной,</br>' +
        'Святой исполненной мечты,</br>' +
        'Поэзии живой и ясной,</br>' +
        'Высоких дум и простоты;'
});
    
// Переопределяем функцию создания кластера.
clusterer.createCluster = function (center, geoObjects) {
    // Наследуем все поля класса.
    var clusterPlacemark = ymaps.Clusterer.prototype.createCluster.call(this, center, geoObjects);
    // Устанавливаем свойства кластера.
    clusterPlacemark.properties.set({
        // Данные для построения диаграммы.
        data: [
            { weight: 4, color: '#408022' },
            { weight: 4, color: '#802240' }
        ],
        // Подпись к диаграмме.
        iconCaption: 'Диаграмма кластера',
     });
  
    // Задаем опции кластера.
    clusterPlacemark.options.set('iconLayout', 'default#pieChart');
    clusterPlacemark.options.set('balloonContentLayout', 'cluster#balloonTwoColumns');
    clusterPlacemark.options.set('balloonPanelContentLayout', 'cluster#balloonTwoColumns');
    clusterPlacemark.options.set('disableClickZoom', true);
    clusterPlacemark.options.set('openBalloonOnClick', true);
    clusterPlacemark.options.set('balloonLeftColumnWidth', 60);
    clusterPlacemark.options.set('balloonPanelMaxMapArea', 0);
    clusterPlacemark.options.set('balloonContentLayoutHeight', 200);
    clusterPlacemark.options.set('balloonContentLayoutWidth', 300);
    clusterPlacemark.options.set('balloonItemContentLayout', 'cluster#balloonTwoColumnsItemContent');
    return clusterPlacemark;
};

clusterer.add(myPlacemark1)
    .add(myPlacemark2);
myMap.geoObjects.add(clusterer);

Результат:

Обратите внимание, что в центре диаграммы отображается не суммарный вес секторов, а число меток, входящих в состав кластера. Чтобы показать суммарный вес, необходимо пройтись по всем полям weight и сумму весов указать в опции iconContent.

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

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

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


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

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);

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

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

Для кластеризации объектов в 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);

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

При щелчке на иконке кластера может произойти либо увеличение коэффициента масштабирования либо открытие балуна, в котором будет отображен список геообъектов кластера. Это поведение контролируется с помощью опции 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);

Примечание

Если при отображении кластера коэффициент масштабирования карты является максимальным, то кластер не будет распадаться на отдельные метки при щелчке на его маркере. В этом случае независимо от значения параметра clusterDisableClickZoom всегда будет открываться балун.

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

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

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