Задача: в мобильном приложении, которое открывает сайт на 1С-Битрикс внутри себя, нужно определить местоположение пользователя и показать близжайшие к нему рестораны и кафе из базы данных сайта
Рестораны- это элементы инфоблока местоположение которых задано через свойство привязка к Яндекс Картам, в котором хранятся (через запятую) широта и долгота метки, в виде строки.
Выводить будем с помощью API Яндекс Карт c их же помощью стилизуем внешний вид меток. Что бы получилось что-то такое.
Само приложение работает на Apache Cordova (кстати, можете посмотреть мой новый видео-курс
Создание мобильного приложения на Apache Cordova), соответственно мы имеем полный доступ к GPS датчику и можем определить местоположение пользователя, вплоть до дома.
Определяем местоположение пользователя с датчиков телефона.
Тут все просто: устанавливаем плагин cordova-plugin-geolocation и не забываем установить плагин cordova-plugin-remote-injection, что бы можно было вызывать плагины Cordova с подключаемого сайта.
cordova plugin add cordova-plugin-geolocation
cordova plugin add cordova-plugin-remote-injection
Теперь мы можем получить данные с GPS/Глонасс датчиков телефона, тут много всякого- но нам нужны только широта и долгота (высота, скорость движения и.т.д. нам не нужны). Создаем две переменные (latitude и longitude) с нужными данными:
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
var onSuccess = function (position) {
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
};
navigator.geolocation.getCurrentPosition(onSuccess, onError);
}
Получаем список элементов со свойством "привязка к Яндекс Картам"
Теперь получим список всех ресторанов, самое главное получить свойство (в моем случае) с кодом ATT_MAP. Также получим название ресторана, что бы вывести его в метке.
Получать будем методом CIBlockElement::GetList по старинке, дабы не городить лишние запросы к свойствам элементов на D7, да и работает быстрее. Строку с широтой и долготой сразу раздробим с помощью explode (разбивает строку с помощью разделителя)
CModule::IncludeModule('iblock');
$restorants = CIBlockElement::GetList(
false,
array('IBLOCK_ID' => '4'),
false,
false,
array('NAME', 'PROPERTY_ATT_MAP')
);
while($ar_fields = $dbRestorants->Fetch()){
$mapPosition = explode(',', $ar_fields['PROPERTY_ATT_MAP_VALUE']);
?>
Ресторан <?=$ar_fields['NAME']?>
Широта: <?=$mapPosition[0]?>
Долгота: <?=$mapPosition[1]?>
<?}?>
Выводим все данные с помощью API Яндекс карт
Теперь, это все нужно скомпоновать и вывести на карту. API у Яндекс карт достатсочно обширное и подробно описанное. Я буду использовать только указание типа меток и метки буду использовать из стандартного набора.
Все комментарии внутри кода:
<?
CModule::IncludeModule('iblock');
$restorants = CIBlockElement::GetList(
false,
array('IBLOCK_ID' => '4'),
false,
false,
array('NAME', 'PROPERTY_ATT_MAP')
);
?>
<!-- Подключаем Яндекс Карты -->
<script src="https://api-maps.yandex.ru/2.1/?lang=ru_RU&apikey=ВАШ_КЛЮЧ_ОТ_API"></script>
<script>
document.addEventListener("deviceready", onDeviceReady, false);
// Все делаем по готовности устройства
function onDeviceReady() {
var onSuccess = function (position) {
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
// Инициализируем карты
ymaps.ready(init);
function init() {
var myMap = new ymaps.Map("map", {
// Центруем карту по геопозиции пользователя
center: [latitude, longitude],
// Приближение карты до улиц
zoom: 12,
// Показываем кнопки масштабирования карты
controls: ['zoomControl']
}),
myMap.geoObjects
// В центр карты (позиция пользователя) добавляем метку
// с фразой 'Вы здесь'
.add(new ymaps.Placemark([latitude, longitude], {
iconCaption: 'Вы здесь'
}, {
// Вид метки "запятая"
preset: 'islands#greenDotIconWithCaption',
// зеленого цвета
iconColor: '#0D9200'
}))
<?
// Вывод ресторанов (получаем выше CIBlockElement::GetList)
while($ar_fields = $restorants->Fetch()){
$mapPosition = explode(',', $ar_fields['PROPERTY_ATT_MAP_VALUE']);
?>
// Добавляем метку с ресторанам по его координатам
.add(new ymaps.Placemark([<?=$mapPosition[0]?>, <?=$mapPosition[1]?>], {
// При клике на метку выводится название ресторана
// тут можно использовать и ссылку, на детальное описание (CODE или DETAIL_PAGE_URL)
balloonContent: 'Ресторан: <?=$ar_fields['NAME']?>'
}, {
// Вид метки "круг" синего цвета
preset: 'islands#blueCircleDotIconWithCaption',
// Размер иконки
iconCaptionMaxWidth: '20'
}))
<?}?>
}
};
navigator.geolocation.getCurrentPosition(onSuccess, onError);
}
</script>
<!-- выводим карту, пока грузится можно сделать прелоадер как фон -->
<div id="map"></div>
В общем-то и все. Карта заполнит собой div#map - пока подгружается карта, можно задать ему фон со спиннером, аля "идет загрузка".
Самих меток и их настроек (размеры, цвета, заготовки) достаточно много. Посмотреть параметры и примеры можно в документации Яндекс Карт. Если хотим сделать собственную метку, со своей картинкой, используем такой пример:
myPlacemark = new ymaps.Placemark(myMap.getCenter(), {
hintContent: 'Заголовок метки',
balloonContent: 'Текст при клике'
}, {
// Тип картинка
iconLayout: 'default#image',
// Путь к собственной картинке
iconImageHref: 'images/ico.gif',
// Размер в пикселях
iconImageSize: [30, 42],
// Смещение в пикселях - что бы лучше выставить
iconImageOffset: [-5, -38]
}),