Часто на сайтах, в особенности посвященных всевозможным объявлениям, можно увидеть карту, на которой отображаются объекты. Обычно на таких сайтах присутствует поиск по объектам, с помощью которого можно найти интересующую информацию. В таких случаях перед разработчиком может возникнуть задача поиска объектов по выделенной области.
Безусловно, существует масса готовых решений для этой задачи, но возникает вопрос, как выделить именно произвольную область на карте? В распоряжении разработчика имеются стандартные методы предусмотренные API Google или Yandex картами, но их минус в том, что они ограничиваются выделением на карте с помощью стандартных геометрических фигур, таких как окружность или полигон.
В случае с окружностью отсутствует гибкость выделяемой области. При использовании полигона тяжело выделить нужную область, так как необходимо каждую точку полигона выбирать отдельно. Выделение же области простым движением мышки более понятно пользователю, а также позволит сократить время на манипуляции с картой.

Далее представлена простая реализация для начинающих подобного функционала:
- Дополнительные библиотеки:
- Jquery;
- simplify.js (http://mourner.github.io/simplify-js/) (git: https://github.com/mourner/simplify-js).
- HTML код:
<div id="wrapper-map" style="position: relative; width: 100%; height: 400px;">
<div id="select_button" class="mdl-button mdl-js-button" style="z-index: 2000; top: 10px; left: 10px; position: absolute;" data-flag="fl">Выделить</div>
<canvas id="canv" style="z-index: 1000; top: 0; left: 0; position: absolute; display:none;"></canvas>
<div id="map" style="width: 100%; height: 100%; overflow: hidden; padding: 0; margin: 0; position: absolute;"></div>
</div>
На канве рисуется произвольная линия, которая превращается в полигон средствами simplify.js. Для рисования необходимо поверх карты отобразить канву, но при этом не будет работать навигация карты, поэтому после того, как выделение области завершено и полигон добавлен на карту, необходимо скрывать блок с канвой.
Основные этапы JS кода:
$(document).ready(function(){
//инициализация карты
var Map = (function() {
ymaps.load(init);
function init () {
// ...
//добавляем точки на карту (addItemPoints некая функция, возвращающая массив точек)
points = addItemPoints();
//добавляем нулевой полигон
addPolygon()
}
// ...
//добавление выделенной области на карту
function addPolygon(coord) {
var myGeoObject = new ymaps.GeoObject({
geometry: {
type: "Polygon",
coordinates: [coord],
}
});
myMap.geoObjects.add(myGeoObject);
return myGeoObject;
}
return {
addPolygon: addPolygon,
convert: convert
};
})();
//инициализируем необходимые переменные (канва, карта, линия)
// …
// обработка начала выделения области (по нажатию мыши)
function mouseDown(e) {
// …
line = [];
line.push({
// …
});
}
// обработка выделения (по движению мыши)
function mouseMove(e) {
// …
line.push({
// …
});
}
// обработка завершения выделения (по отпусканию кнопки мыши)
function mouseUp() {
// убираем нажатие кнопки выделения, тем самым позволяя управлять картой
// …
// убираем прослушку событий по действиям мыши
// …
// проводим аппроксимацию нарисованной линии, а также добавляем получившийся полигон на карту
aproximate();
// рассчитываем точки, входящие в выделенный полигон
var myCollection = new ymaps.GeoObjectCollection();
myMap.geoObjects.remove(myCollection);
var placemarks = [];
myCollection = new ymaps.GeoObjectCollection();
// пробегаем по всем точкам points, и если они попадают в polygon.geometry.contains, то создаем
// myPlacemark и кладем ее в myCollection. Также весь список найденных точек кладем в points_select
for (i in points) {
if (polygon.geometry.contains([points[i].CoordX, points[i].CoordY])){
points_select.push(points[i]);
var myPlacemark = new ymaps.GeoObject({
// …
});
placemarks.push(myPlacemark);
myCollection.add(myPlacemark);
}
}
myMap.geoObjects.add(myCollection);
/*updateItemList некая функция, которая позволяет передать выбранные точки на сервер или обработать каким-либо образом (допустим можно ajax отправить на сервер выделенные точки, там отфильтровать по каким-либо дополнительным параметрам и вернуть отфильтрованный результат.) */
updateItemList(points_select);
}
// функция, аппроксимирующая нарисованную линию в полигон и добавляющая ее на карту
function aproximate() {
// …
}
canv.addEventListener('mousedown', mouseDown);
});
Основные шаги:
- Инициализация карты с добавлением нулевого полигона.
- Добавление в массив всех существующих точек (addItemPoints).
- Определение событий мыши для рисования на канве (mouseDown, mouseMove, mouseUp).
- По завершении выделения области аппроксимация нарисованной линии в полигон и добавление его на карту (с помощью simplify.js).
- Определение точек, которые попадают в созданный полигон.
- Обработка выбранных точек (updateItemList).

Приведенный код требует доработки в виде определения функций добавляющей точки и обрабатывающей возвращенный список точек. Также возможно необходимо будет подкорректировать под поставленную задачу условие, проверяющее вхождение точек в область (polygon.geometry.contains) (это будет нужно, если формат передаваемых точек будет отличаться от тех, что использованы в примере).
Особенность представленного решения заключается в возможности выделить абсолютно произвольную область на карте без использования сложных полигонов предоставляемых API. Также в данном решении не используются громоздкие библиотеки, что позволяет легко использовать данный код в любых проектах.