Два одновременных провайдера поиска для яндекс карты
У меня есть карта в которой я сделал поиск по своим объектам. А как сделать так, что бы при отсутствии попадания в мои результаты, поиск производился уже не по моим объектам, а по улицам, например "yandex#search". Понимаю что нужно как то добавить второго провайдера поиска, помимо своего, но как это реализовать, никаких примеров не нашел. Поиск по своим объектам реализовал по аналогии с примером https://yandex.ru/dev/maps/jsbox/2.1/custom_search
Попробовал, но что то не вышло, то ли неправильно функцию добавлял, то ли не туда и у меня то вообще поиск не работал, то даже карта не погружалась. Вот рабочий вариант (с 1 провайдером):
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<title>Многоугольник</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="https://api-maps.yandex.ru/2.1/?lang=ru_RU&apikey=3261ce08-c60a-4114-96f8-ce820abf124a" type="text/javascript"></script>
<script type="text/javascript">
ymaps.ready(init);
function init() {
// Создаем список (массив) подсказок
var podskazki = [
"ТОС «Виктория»",
"ТОС «Максимум Света»",
];
// выполняем поиск по подсказкам
var find = function (podskazki, find) {
return podskazki.filter(function (value) {
return (value + "").toLowerCase().indexOf(find.toLowerCase()) != -1;
});
};
// создаем провайдер поиска
var myProvider = {
suggest: function (request, options) {
var res = find(podskazki, request),
arrayResult = [5],
results = Math.min(options.results, res.length);
for (var i = 0; i < results; i++) {
arrayResult.push({displayName: res[i], value: res[i]})
}
return ymaps.vow.resolve(arrayResult);
}
}
// Создание подсказок в поиске
var suggestView = new ymaps.SuggestView('poisk', {
provider: myProvider,
noSuggestPanel: false,
boundedBy: [[48.61, 134.98], [48.31, 135.29]],
strictBounds: true,
results: 19
});
// поиск по выбору подсказки
suggestView.events.add('select', function () {
Search()
})
// поиск по Enter
$("#poisk").keyup(function(event){
if(event.keyCode == 13){
Search()
}
});
// поиск по нажатию "лупы"
$('.custom-search').click(() => {
if ($('#poisk').val() != undefined) {
Search()
}
});
// Непосредственно поиск в панели
function Search () {
var request = $('#poisk').val();
searchControl.search(request);
}
// Создание экземпляра карты и его привязка к контейнеру с заданным id ("map")
var myMap = new ymaps.Map('map', {
center: [48.48, 135.08],
zoom: 14,
controls: ['zoomControl', 'typeSelector', 'fullscreenControl', 'searchControl'] // "Элементы управления (Зум, слои, фулскрин, поиск)
},
{ // Ограничение области карты Хабаровск + загород
restrictMapArea: [[48.61, 134.98], [48.31, 135.29]],
// Ограничение зума
minZoom: 10,
maxZoom: 17
}) ,
// Создание полигонов и добавление их на карту.
myObjects = ymaps.geoQuery({
type: "FeatureCollection",
features: [
{
type: 'Feature',
geometry: {
type: 'Polygon',
coordinates: [[ [ 48.4872099152, 135.044750889 ], [ 48.4865858624, 135.045233687 ], [ 48.4863005786, 135.044150075 ], [ 48.4869567290, 135.043726286 ], [ 48.4872099152, 135.044750889 ] ]]
},
options: {
fillColor: '00bfbf', // Цвет заливки
fillOpacity: 0.45, // Прозрачность заливки
strokeColor: 'ff007f', // Цвет обводки
strokeWidth: 2, // Толщина обводки
strokeOpacity: 0.5, // Прозрачность обводки
fildColor: "Кировский", // Кластер объекта
filtColor: "2020" // Год объекта
},
// Содержимое балуна
properties: {
balloonContentHeader: '<a href="https://khv27.ru/projects/territorialnoe-obshchestvennoe-samoupravlenie/reestr-tos/index.php?ELEMENT_ID=106497">ТОС «Виктория»</a>', // Заголовок
balloonContent: '<b>Председатель: </b>' + 'Савинов Е.А.<br/>' + '<b>Адрес: </b>' + 'ул. Казачья гора, дом 9-7<br/>' + '<b>Район: </b>' + 'Кировский<br/>' + '<b>Дата создания: </b>' + '10 февраля 2020<br/>' + '<b>Реализованные проекты: </b>' + 'НОВЫЙ ДВОР 2021<br/>', // Содержимое
balloonContentFooter: 'Телефон: </b>' + '409144', // Футер
hintContent: "ТОС «Виктория»" // Подсказка объекта
}
},
{
type: 'Feature',
geometry: {
type: 'Polygon',
coordinates: [[ [ 48.5213356048, 135.106362622 ], [ 48.5206620838, 135.107070725 ], [ 48.5214817114, 135.108052414 ], [ 48.5216670166, 135.107526701 ], [ 48.5215850548, 135.106754225 ], [ 48.5214638935, 135.106566470 ], [ 48.5213356048, 135.106362622 ]]]
},
options: {
fillColor: '00bf00', // Цвет заливки
fillOpacity: 0.45, // Прозрачность заливки
strokeColor: 'ff007f', // Цвет обводки
strokeWidth: 2, // Толщина обводки
strokeOpacity: 0.5, // Прозрачность обводки
fildColor: "Железнодорожный", // Кластер объекта
filtColor: "2020" // Год объекта
},
// Содержимое балуна
properties: {
balloonContentHeader: '<a href="https://khv27.ru/projects/territorialnoe-obshchestvennoe-samoupravlenie/reestr-tos/index.php?ELEMENT_ID=106500">ТОС «Максимум Света»</a>', // Заголовок
balloonContent: '<b>Председатель: </b>' + 'Сергеев М.С.<br/>' + '<b>Адрес: </b>' + 'пер. Краснодарский, дом 19а<br/>' + '<b>Район: </b>' + 'Железнодорожный<br/>' + '<b>Дата создания: </b>' + '11 февраля 2020<br/>' + '<b>Реализованные проекты: </b>' + 'Спортивная площадка<br/>', // Содержимое
balloonContentFooter: 'Телефон: </b>' + '+7 (4212) 40-91-42', // Футер
hintContent: "ТОС «Максимум Света»" // Подсказка объекта
}
},
]
}).addToMap(myMap);
// Создаем коллекцию для поиска по названию объектов
myCollection = new ymaps.GeoObjectCollection(),
// Создаем массив с данными.
myPoints = [
{ coords: [48.4872099152, 135.044750889], text: 'ТОС «Виктория»' },
{ coords: [48.5213356048, 135.106362622], text: 'ТОС «Максимум Света»' },
];
// создание поисковой строки
searchControl = myMap.controls.get('searchControl');
// настройка поисковой строки Яндекса
searchControl.options.set(
{
provider: new CustomSearchProvider(myPoints),
noPlacemark: true,
placeholderContent: 'Введите адввврес ТОСа',
boundedBy: [[48.61, 134.98], [48.31, 135.29]],
strictBounds: true,
results: 10, // требуемое количество результатов
resultsPerPage: 5,
position: {
left: -400 // смещение строки поиска
}
}
);
// Проверим попадание результата поиска в один из ТОСов.
searchControl.events.add('resultshow', function (e) {
highlightResult(searchControl.getResultsArray()[e.get('index')]);
});
// Сохраняем координаты переданного объекта и находим полигон.
function highlightResult(obj) {
// Сохраняем координаты переданного объекта.
var coords = obj.geometry.getCoordinates(),
// Находим полигон, в который входят переданные координаты.
polygon = myObjects.searchContaining(coords).get(0);
if (polygon) {
polygon.options.set('fillOpacity', 0.2);
polygon.balloon.open();
}
}
// Провайдер данных осуществляет поиск геообъектов по массиву points.
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 + '',
description: text + 'description',
boundedBy: [coords, coords]
}));
}
deferred.resolve({
// Геообъекты поисковой выдачи.
geoObjects: geoObjects,
// Метаинформация ответа.
metaData: {
geocoder: {
// Строка обработанного запроса.
request: request,
// Количество найденных результатов.
found: geoObjects.getLength(),
// Количество возвращенных результатов.
results: limit,
// Начинает поиск сразу после нажатия Энтер
skip: offset
}
}
});
// Возвращаем объект-обещание.
return deferred.promise();
searchControl.events.add('load', function (event) { // Проверяем, что это событие не "дозагрузки" результатов и по запросу найден хотя бы один результат.
if (!event.get('skip') && searchControl.getResultsCount()) {
searchControl.showResult(0);
}
});
}
}
</script>
<style>
html,
body,
#map {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
</style>
</head>
<body>
<div class="search">
<input type="text" id="poisk" placeholder="Введите название ТОСа" autocomplete="off" style="margin-right: 0px;">
<div class="custom-search">
</div>
</div>
<div id="map"></div>
</body>
</html>
Я так и не понял в итоге куда именно нужно прописать условие на количество найденных результатов
Ответы (1 шт):
Получилось осуществить одновременный поиск по двум разным провайдерам, примар куска кода :
searchControl.events.add('optionschange', function (event) {
if (!event.get('count') == 0) {
earchControl.options.set('provider', 'yandex#search');
} else {
earchControl.options.set('provider', 'new CustomSearchProvider(myPoints)');
}
});
Но вот теперь как то нужно сделать так что бы еще поисковые подсказки вылазили по двум провайдерам