Поиск по своим объектам

Open in CodeSandbox

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

А что делать, если необходимо организовать поиск по собственным объектам и интегрировать его с API Яндекс.Карт? Написать собственный провайдер поиска, который можно использовать в функции geocode и элементе управления Поиск по карте.

Провайдер поиска должен реализовывать интерфейс IGeocodeProvider. Данный пример показывает, как написать собственный провайдер и подключить его стандартному элементу управления Поиск по карте.

Обсуждение этого примера можно посмотреть в клубе.

<!DOCTYPE html>
<html>
    <head>
        <title>Поиск по своим объектам</title>
        <meta
            http-equiv="Content-Type"
            content="text/html; charset=utf-8"
        />
        <!--
        Укажите свой API-ключ. Тестовый ключ НЕ БУДЕТ работать на других сайтах.
        Получить ключ можно в Кабинете разработчика: https://developer.tech.yandex.ru/keys/
    -->
        <script
            src="https://api-maps.yandex.ru/2.1/?lang=ru_RU&amp;apikey=<ваш API-ключ>"
            type="text/javascript"
        ></script>
        <script src="custom_search.js" type="text/javascript"></script>
        <style>
            html,
            body,
            #map {
                width: 100%;
                height: 100%;
                padding: 0;
                margin: 0;
            }
        </style>
    </head>
    <body>
        <div id="map"></div>
    </body>
</html>
function init() {
    var myMap = new ymaps.Map("map", {
            center: [55.7, 37.5],
            zoom: 9,
            controls: ["zoomControl"],
        }),
        // Создаем коллекцию.
        myCollection = new ymaps.GeoObjectCollection(),
        // Создаем массив с данными.
        myPoints = [
            { coords: [55.77, 37.46], text: "Трактир" },
            { coords: [55.66, 37.48], text: "Кафе" },
            { coords: [55.65, 37.42], text: "Ресторан" },
            { coords: [55.64, 37.54], text: "Музей" },
            { coords: [55.54, 37.52], text: "Библиотека" },
            { coords: [55.53, 37.56], text: "Школа" },
            { coords: [55.61, 37.61], text: "Аптека" },
            { coords: [55.8, 37.58], text: "Бар" },
            { coords: [55.71, 37.35], text: "Институт" },
            { coords: [55.74, 37.57], text: "Университет" },
            { coords: [55.58, 37.69], text: "Больница" },
            { coords: [55.57, 37.7], text: "Цирк" },
            { coords: [55.55, 37.64], text: "Магазин" },
            { coords: [55.5, 37.75], text: "Булочная" },
            { coords: [55.81, 37.73], text: "Полиция" },
            { coords: [55.73, 37.68], text: "Салон красоты" },
            { coords: [55.86, 37.76], text: "Баня" },
            { coords: [55.38, 37.69], text: "Гараж" },
            { coords: [55.91, 37.5], text: "Дом" },
            { coords: [55.62, 37.32], text: "Прачечная" },
            { coords: [55.85, 37.41], text: "Стадион" },
            { coords: [55.67, 37.24], text: "Вокзал" },
        ];

    // Заполняем коллекцию данными.
    for (var i = 0, l = myPoints.length; i < l; i++) {
        var point = myPoints[i];
        myCollection.add(
            new ymaps.Placemark(point.coords, {
                balloonContentBody: point.text,
            })
        );
    }

    // Добавляем коллекцию меток на карту.
    myMap.geoObjects.add(myCollection);

    // Создаем экземпляр класса ymaps.control.SearchControl
    var mySearchControl = new ymaps.control.SearchControl({
        options: {
            // Заменяем стандартный провайдер данных (геокодер) нашим собственным.
            provider: new CustomSearchProvider(myPoints),
            // Не будем показывать еще одну метку при выборе результата поиска,
            // т.к. метки коллекции myCollection уже добавлены на карту.
            noPlacemark: true,
            resultsPerPage: 5,
        },
    });

    // Добавляем контрол в верхний правый угол,
    myMap.controls.add(mySearchControl, { float: "right" });
}

// Провайдер данных для элемента управления ymaps.control.SearchControl.
// Осуществляет поиск геообъектов в по массиву points.
// Реализует интерфейс IGeocodeProvider.
function CustomSearchProvider(points) {
    this.points = points;
}

// Провайдер ищет по полю text стандартным методом String.ptototype.indexOf.
CustomSearchProvider.prototype.geocode = function (request, options) {
    var deferred = new ymaps.vow.defer(),
        geoObjects = new ymaps.GeoObjectCollection(),
        // Сколько результатов нужно пропустить.
        offset = options.skip || 0,
        // Количество возвращаемых результатов.
        limit = options.results || 20;

    var points = [];
    // Ищем в свойстве text каждого элемента массива.
    for (var i = 0, l = this.points.length; i < l; i++) {
        var point = this.points[i];
        if (point.text.toLowerCase().indexOf(request.toLowerCase()) != -1) {
            points.push(point);
        }
    }
    // При формировании ответа можно учитывать offset и limit.
    points = points.splice(offset, limit);
    // Добавляем точки в результирующую коллекцию.
    for (var i = 0, l = points.length; i < l; i++) {
        var point = points[i],
            coords = point.coords,
            text = point.text;

        geoObjects.add(
            new ymaps.Placemark(coords, {
                name: text + " name",
                description: text + " description",
                balloonContentBody: "<p>" + text + "</p>",
                boundedBy: [coords, coords],
            })
        );
    }

    deferred.resolve({
        // Геообъекты поисковой выдачи.
        geoObjects: geoObjects,
        // Метаинформация ответа.
        metaData: {
            geocoder: {
                // Строка обработанного запроса.
                request: request,
                // Количество найденных результатов.
                found: geoObjects.getLength(),
                // Количество возвращенных результатов.
                results: limit,
                // Количество пропущенных результатов.
                skip: offset,
            },
        },
    });

    // Возвращаем объект-обещание.
    return deferred.promise();
};

ymaps.ready(init);