Выборка геообъектов
В процессе разработки интерактивной карты с геообъектами можно производить различные действия. Например, добавлять на карту, изменять свойства или опции, назначать обработчика события и т.д. Такие операции являются базовыми, и для выполнения каждой из них в API определена соответствующая функция.
Однако иногда при работе с геообъектами перед разработчиком возникают более сложные задачи. Например, необходимо найти такие геообъекты, которые располагаются севернее какой-нибудь географической области (дома, улицы и т.д.). Или проверить, попадает ли один геообъект в геометрическую область другого. Реализация таких задач с использованием стандартных функций API может привести к значительному разрастанию программного кода.
Для упрощения реализации подобных задач в API встроен набор вспомогательных методов. Данные методы являются обертками над стандартными функциями API. При использовании вспомогательных методов не нужно вручную реализовывать такие операции, как поиск по геообъектам, определение их положения относительно друг друга и многие другие.
В качестве примера в приведенной ниже таблице продемонстрировано два варианта реализации одной и той же задачи.
Задача: геообъекты, которые попадают в перетаскиваемый круг, сделать красными. А все остальные геообъекты окрасить в синий (посмотреть пример в песочнице).
Стандартная реализация | Реализация с помощью вспомогательных методов |
---|---|
| |
Стандартная реализация | Реализация с помощью вспомогательных методов |
---|---|
| |
Как видно из примера, вспомогательные методы позволяют значительно упростить программный код.
Вспомогательные методы определены в классе GeoQueryResult. Объект GeoQueryResult
называется выборкой геообъектов и представляет собой хранилище данных со специальной структурой. В него предварительно нужно добавить геообъекты, с которыми будут производиться какие-либо действия. Это могут быть геообъекты любого типа: метки, круги, прямоугольники, их коллекции и т.д. При этом их размещение на карте необязательно.
Для создания выборки GeoQueryResult
используется функция geoQuery. В нее передается источник данных — геообъекты, на основе которых будет сформирована выборка.
var circle = new ymaps.Circle([[30, 42 ], 5000]);
//Добавление круга на карту.
myMap.geoObjects.add(circle);
// Формирование источника данных.
var objects = [
new ymaps.Placemark([34, 56]),
new ymaps.Rectangle([[34, 56], [36, 57]]),
circle
],
// Формирование выборки.
storage = ymaps.geoQuery(objects);
// В качестве источника данных в выборку передаются все геообъекты карты
var storage = ymaps.geoQuery(myMap.geoObjects);
Функция geoQuery
также может формировать выборку геообъектов на основе асинхронного источника данных. Например, в качестве источника можно указать данные, которые будут получены в результате обращения к серверу. Так как обработка запроса и ответа занимает какое-то время, то перед формированием выборки geoQuery
будет ожидать готовности источника:
// Когда сервер вернет результат, geoQuery обработает данные и построит на их основе выборку.
ymaps.geoQuery(ymaps.geocode('Санкт-Петербург'));
Функция geoQuery
возвращает сформированную выборку GeoQueryResult
. Теперь с ее геообъектами при помощи вспомогательных методов можно производить различные действия: добавлять на карту, задавать свойства или опции и т.д. Также, применяя к данной выборке различные фильтры, на ее основе можно формировать новые выборки.
Ниже представлен набор доступных методов, позволяющих осуществлять различные операции с выборкой и ее геообъектами:
- 1. Методы, производящие операции над выборкой
-
Выборка представляет собой упорядоченное множество геообъектов, отобранных по какому-либо критерию. Как и с обычными массивами, с выборкой можно производить различные действия, например, добавлять или удалять объекты, сортировать, представлять ее элементы в обратном порядке и т.д. Для работы с множеством отобранных объектов предназначены следующие методы:
addДобавляет новые объекты в выборку. Не изменяет исходную выборку
GeoQueryResult
, а создает новую, содержащую результирующий набор геообъектов.var placemark = new ymaps.Placemark([34, 56]); myGeoQueryResult.add(placemark);
Подробнее о методе см. в справочнике.
getLengthВозвращает количество элементов выборки.
var result = ymaps.geoQuery(myMap.geoObject).searchIntersect(myPolygon); alert('Количество геообъектов, пересекающих многоугольник: ' + result.getLength());
Подробнее о методе см. в справочнике.
removeУдаляет объекты из выборки. Не изменяет исходную выборку, а создает новую, содержащую результирующий набор геообъектов.
var objects = [ new ymaps.Placemark([34, 56]), new ymaps.Rectangle([[34, 56], [36, 57]]) ], result = ymaps.geoQuery(objects); // Обратите внимание, что в результате будет получен другой объет GeoQueryResult, а старый останется без изменений. var newResult = result.remove(objects[1]);
Подробнее о методе см. в справочнике.
reverseПереставляет элементы выборки в обратном порядке. Возвращает новую выборку.
var result = ymaps.geoQuery(myMap.geoObjects).sort('x'), reversedResult = result.reverse();
Подробнее о методе см. в справочнике.
sliceВозвращает срез выборки.
var result = ymaps.geoQuery(map.geoObjects).slice(0, 10); alert('Количество элементов в новой выборке:', result.getLength());
Подробнее о методе см. в справочнике.
sortСортирует выборку по заданному параметру.
var result = ymaps.geoQuery(myMap.geoObjects); result.sort('lat').sort('x');
Подробнее о методе см. в справочнике.
sortByDistanceСоздает новую выборку, элементы которой отсортированы по расстоянию от указанного объекта.
var result = ymaps.geoQuery(objects).addToMap(myMap), polyline = new ymaps.Polyline([[35, 65], [35, 66], [34, 62], [34, 63]]); myMap.geoObjects.add(polyline); var sortedByPolyline = result.sortByDistance(polyline);
Подробнее о методе см. в справочнике.
- 2. Методы для получения доступа к элементу выборки
- Для получения доступа к нужному элементу выборки предназначены методы:
- 3. Методы для обработки асинхронных операций
-
Операции с выборками могут производиться в асинхронном режиме. Как правило, асинхронность возникает, когда в какой-либо функции происходит обмен данными с сервером. Поскольку для получения данных требуется какое-то время, все последующие функции, работающие с выборкой, должны дожидаться готовности результатов.
Асинхронное взаимодействие реализовано с помощью обещаний (объектов-promise). Принцип такого взаимодействия проиллюстрирован на рисунке.
Все функции в цепочке вызываются синхронно. Это означает, что интерпретатор вызывает их последовательно, в одном потоке. Асинхронным является процесс заполнения выборок. Если в момент вызова какой-либо функции данные для формирования выборки еще не готовы, то эта функция создает пустой объект
GeoQueryResult
. В его конструктор передается объект-promise
, который был передан предыдущей вызванной функцией. Выполнение объекта-promise
означает, что данные готовы, и можно формировать выборку.На рисунке функция
geocode
, ожидающая ответа от сервера, создает объект-обещание (promise1
), который выполнится тогда, когда сервер вернет данные. Следующая функцияgeoQuery
подписывается наpromise1
и начнет заполнять выборку только тогда, когда этот объект-обещание будет выполнен. Аналогично создается новый объектpromise3
, на который подписывается уже следующая функцияadd
.Внимание. Функции, не возвращающие объектGeoQueryResult
(например,getLength()
), выполняются синхронно, то есть перед началом работы не дожидаются готовности данных:
Для того чтобы такие функции выполнялись асинхронно, необходимо передать их вызов функцииvar result = ymaps.geoQuery(ymaps.geocode('река Лена')).getLength(); alert(result); // result = 0
then
в качествеcallback
:var result = ymaps.geoQuery(ymaps.geocode('река Лена')); result.then(function () { alert('Количество найденных объектов: ' + result.getLength()); }, function () { alert('Произошла ошибка.'); });
Подробнее о методе см. в справочнике.
Для отладки асинхронной операции предназначен метод
isReady()
, возвращающий признак готовности результата:var result = ymaps.geoQuery(ymaps.geocode('Иваново')); if (!result.isReady()) { result.then(function () { // Обработка данных. }); } else { // Обработка данных. }
Подробнее о методе см. в справочнике.
- 4. Методы для групповой обработки элементов выборки
- С геообъектами, которые вошли в выборку, можно производить различные действия: добавлять на карту, изменять свойства, опции и т.п. Ниже приведен список методов для работы с группой геообъектов:addEvents
Назначает обработчики событий на все элементы выборки.
ymaps.geoQuery(map.geoObjects).search('geometry.type="Circle"').addEvents('click', function () { alert('Вы кликнули по кругу!'); });
Подробнее о методе см. в справочнике.
addToДобавляет элементы выборки в заданную коллекцию геообъектов.
// Покажем на карте объекты северного полушария. var result1 = ymaps.geoQuery(placemarks).search('lat > 0').addTo(myMap.geoObjects);
Подробнее о методе см. в справочнике.
addToMapДобавляет объекты выборки на карту.
// Покажем на карте объекты северного полушария. var result1 = ymaps.geoQuery(placemarks).search('lat > 0').addToMap(myMap);
Подробнее о методе см. в справочнике.
clusterizeСоздает кластеризатор и добавляет в него объекты из выборки. В случае, если данные выборки еще не готовы, они будут добавлены в кластеризатор сразу после обработки, а возвращенный кластеризатор изначально будет пуст.
// Выберем только точечные объекты и добавим их в кластеризатор. var clusterer = ymaps.geoQuery(objects).search('geometry.type="Point"').clusterize(); myMap.geoObjects.add(clusterer);
Подробнее о методе см. в справочнике.
removeEventsУдаляет подписку на событие с объектов.
Внимание. Для корректной отписки передаваемые аргументы должны быть точно такие же, как при подписке через методaddEvents
.var callback = function () { alert('Вы кликнули по кругу!'); }; ymaps.geoQuery(map.geoObjects).search('geometry.type="Circle"').addEvents('click', callback); // ... ymaps.geoQuery(map.geoObjects).search('geometry.type="Circle"').removeEvents('click', callback);
Подробнее о методе см. в справочнике.
removeFromУдаляет объекты выборки из заданной коллекции геообъектов.
// Покажем на карте все объекты. var result1 = ymaps.geoQuery(placemarks).addTo(myMap.geoObjects), // А затем скроем объекты из северного полушария. result2 = result1.search('lat > 0').removeFrom(myMap.geoObjects);
Подробнее о методе см. в справочнике.
removeFromMapУдаляет объекты выборки с карты.
// Покажем на карте все объекты. var result1 = ymaps.geoQuery(placemarks).addToMap(myMap), // А затем скроем объекты из северного полушария. result2 = result1.search('lat > 0').removeFromMap(myMap);
Подробнее о методе см. в справочнике.
setOptionsЗадает значение опций всем объектам выборки.
var result = ymaps.geoQuery(placemarks); // Сделаем видимыми элементы, попадающие в прямоугольную область. result.searchIntersect(myBounds).setOptions('visible', true);.
Подробнее о методе см. в справочнике.
setPropertiesЗадает значение поля
properties
всем объектам выборки.var result = ymaps.geoQuery(objects); // Пометим элементы, попадающие в области. result.searchIntersect(myBounds1).setProperties('intersectBounds', true); result.searchIntersect(myBounds2).setProperties('intersectBounds', true); // ... result.search('properties.intersectBounds = true').addToMap(myMap);
Подробнее о методе см. в справочнике.
unsetOptionsОбнуляет значение опций всем объектам выборки.
result.unsetOptions('visible');
Подробнее о методе см. в справочнике.
unsetPropertiesОбнуляет значение поля
properties
у всех элементов выборки.var result = ymaps.geoQuery(objects); // Пометим элементы, попадающие в первую область, но не попадающие во вторую. result.searchIntersect(myBounds1).setProperties('intersectBounds', true); result.searchIntersect(myBounds2).unsetProperties('intersectBounds', true); // ... result.search('properties.intersectBounds = true').addToMap(myMap);
Подробнее о методе см. в справочнике.
- 5. Методы, осуществляющие поиск по выборке
- intersect
Создает новую выборку, содержащую общие элементы для двух других выборок.
var result = ymaps.geoQuery(placemarks), greenObjects = result.search('properties.color=green'), roundObjects = result.search('properties.shape=round'), greenRoundObjects = greenObjects.intersect(roundObjects); alert('Количество круглых зеленых объектов: ' + greenRoundObjects.getLength());
Подробнее о методе см. в справочнике.
searchПоиск объектов выборки, удовлетворяющих заданным условиям.
var result = ymaps.geoQuery(myMap.geoObjects); // Поиск объектов с определенным типом геометрии. Значение поля указано в кавычках, так как это строка. result.search('geometry.type = "Point"') // Поиск по координате. .search('geometry.coordinates.0 > 100')
Подробнее о методе см. в справочнике.
searchContainingCоздает новую выборку из объектов, содержащих указанный геообъект.
Внимание. Для корректных расчетов все геообъекты необходимо добавить на карту. Если геообъекты не нужно отображать, то необходимо выставить значение их опцииvisible: false
.var result = ymaps.geoQuery(objects).addToMap(myMap), polygon = new ymaps.Polygon([[[35, 65], [35, 66], [34, 62], [34, 63], [35, 65]]]); myMap.geoObjects.add(polygon); var objectsContainingPolygon = result.searchContaining(polygon);
Подробнее о методе см. в справочнике.
searchInsideСоздает новую выборку из объектов, целиком входящих в указанный объект.
Внимание. Для корректных расчетов геообъекты необходимо добавить на карту. Если геообъекты не нужно отображать, то необходимо выставить значение их опцииvisible: false
.var result = ymaps.geoQuery(objects).addToMap(myMap), polygon = new ymaps.Polygon([[[35, 65], [35, 66], [34, 62], [34, 63], [35, 65]]]); myMap.geoObjects.add(polygon); var objectsInsidePolygon = result.searchInside(polygon);
Подробнее о методе см. в справочнике.
searchIntersectСоздает новую выборку из объектов выборки, пересекающих указанный геобъект.
Внимание. Для корректных расчетов геообъекты необходимо добавить на карту. Если геообъекты не нужно отображать, то необходимо выставить значение их опцииvisible: false
.var result = ymaps.geoQuery(objects).addToMap(myMap), polygon = new ymaps.Polygon([[[35, 65], [35, 66], [34, 62], [34, 63], [35, 65]]]); myMap.geoObjects.add(polygon); var objectsIntersectPolygon = result.searchIntersect(polygon);
Подробнее о методе см. в справочнике.
- 6. Методы для получения геометрических параметров выборки
- applyBoundsToMapПозволяет установить видимую область карты так, чтобы видны были все объекты из выборки.
var result = ymaps.geoQuery(objects).applyBoundsToMap(myMap); alert('Видимая область карты изменена.');
Подробнее о методе см. в справочнике.
getBoundsВозвращает географические координаты области, охватывающей объекты результата.// Устанавливаем центр и масштаб карты так, чтобы отобразить весь результат целиком. myMap.setBounds(myResult.getBounds());
getCenterВозвращает координаты центра области, охватывающей объекты.// Сместим центр карты в центр области, охватывающей объекты. myMap.setCenter(ymaps.geoQuery(objects).getCenter());
getCentralObjectВозвращает геообъект, который наиболее близко расположен к центру видимой области карты.// Откроем балун у геообъекта, ближайшего к центру видимой области карты. ymaps.geoQuery(objects).getCentralObject(myMap).balloon.open();
getClosestToВозвращает объект выборки, ближайший к указанному. Если на вход подается объект, уже находящийся в выборке, то вернется другой объект выборки, ближайший к указанному.Внимание. Для корректных расчетов геообъекты необходимо добавить на карту. Если геообъекты не нужно отображать, то необходимо выставить значение их опцииvisible: false
.var result = ymaps.geoQuery(objects).addToMap(myMap), polyline = new ymaps.Polyline([[35, 65], [35, 66], [34, 62], [34, 63]]); myMap.geoObjects.add(polyline); var closestObject = result.getClosestTo(polyline);
Подробнее о методе см. в справочнике.
getExtremeВозвращает максимальные и минимальные значения координат среди координат объектов выборки.alert('Самая северная координата: ', ymaps.geoQuery(myMap.geoObjects).getExtreme('top'));
Подробнее о методе см. в справочнике.
getExtremeObjectВозвращает объект с минимальной или максимальной координатой среди координат объектов выборки.// Откроем балун на самом северном объекте. var topObject = ymaps.geoQuery(myMap.geoObjects).getExtremeObject('top'); topObject.balloon.open();
Подробнее о методе см. в справочнике.
getGlobalPixelBoundsВозвращает глобальные пиксельные координаты области, охватывающей объекты выборки (для текущего значения коэффициента масштабирования карты).var result = ymaps.geoQuery(placemarks).search('properties.type="shop"').getGlobalPixelBounds(myMap); if (Math.abs(result[0][0] - result[1][0]) > myMap.container.getSize()[0]) { alert('Объекты не поместятся на карту по ширине!'); }
Подробнее о методе см. в справочнике.
getGlobalPixelCenterДля текущего коэффициента масштабирования возвращает глобальные пиксельные координаты центра области, охватывающей объекты выборки.// Посчитаем номер тайла, на который приходится центр области, охватывающей результат. var globalPixelCenter = ymaps.geoQuery(objects).getGlobalPixelCenter(myMap), tileNumber = [ Math.floor(globalPixelCenter[0] / 256), Math.floor(globalPixelCenter[1] / 256) ]; alert('Номер центрального тайла: ' + tileNumber[0] + ' ' + tileNumber[1]);
Подробнее о методе см. в справочнике.