Разработчики мобильных приложений на платформе 1С часто сталкиваются с необходимостью использовать географические карты. Например, сети магазинов отображают в мобильном приложении точки продаж, а для такси или каршеринга карты являются базовым функционалом.
В статье разберемся, как настроить использование карт в мобильном приложении. В качестве примера будет реализовано несложное приложение, с отображением на карте магазинов из соответствующего справочника. Добавлена возможность проложить маршрут до конкретного магазина. Отображение маршрута выполнено в двух вариантах: внутри приложения и с помощью открытия внешнего мобильного приложения с картами. В качестве поставщика API служат карты компании Яндекс.
Оглавление
Подготовка конфигурации
Создание конфигурации
При создании пустой конфигурации в свойствах указывается назначение использования — приложение для мобильной платформы. В свойстве «Используемая функциональность мобильного приложения» устанавливается флаг напротив пункта «Геопозиционирование». Без этого свойства мобильное приложение не сможет получать данные о местоположении пользователя. Создается справочник «Магазины», имеющий всего три реквизита: «Адрес», «Широта» и «Долгота». Все реквизиты имеют тип «строка», для широты и долготы устанавливается длина строки в 20 символов, для адреса — 250.
Создание необходимых общих модулей
В дальнейшем понадобится два общих модуля: клиентский модуль «ГеопозиционированиеКлиент» и клиент-серверный «РаботаСКартойКлиентСервер». Общий модуль «ГеопозиционированиеКлиент» используется для получения координат местоположения пользователя, а общий модуль «РаботаСКартойКлиентСервер» — для процедур и функций, связанных с формированием карты.
Добавление общей формы
В конфигурацию добавляется общая форма, на которой будет располагаться географическая карта. На созданной форме будет только один реквизит типа «строка» с неограниченной длиной. Реквизит можно назвать «КартаHTML».
Реквизит нужно перенести в дерево элементов и указать для элемента следующие свойства:
- Вид — Поле HTML документа.
- Положение заголовка — Нет.
Добавление обработчика нажатия на карту
Нужно подготовить обработчик нажатия на карту. В событии «ПриНажатии» у добавленного элемента создается обработчик события на клиенте. В данном обработчике указывается следующий код:
&НаКлиенте Процедура КартаHTMLПриНажатии(Элемент, ДанныеСобытия, СтандартнаяОбработка) СтандартнаяОбработка = Ложь; ПолучитьИОбработатьДанные(ДанныеСобытия.href); КонецПроцедуры
В этой процедуре отменяется стандартная обработка, чтобы вручную обрабатывать каждое нажатие пользователя. Вызывается процедура «ПолучитьИОбработатьДанные», передавая в параметрах href, т. е. ссылку. Именно с помощью ссылки становится понятно, на какой элемент нажал пользователь.
Ниже создается клиентская процедура «ПолучитьИОбработатьДанные», в ней позже будет описано поведение при нажатии пользователя на карту.
Получение ключа API
Чтобы приступить к написанию HTML-кода для отображения карты, предварительно нужно получить API-ключ Яндекс.Карт. Это можно сделать за пару минут в кабинете разработчика. У Яндекса также есть подробная инструкция, как это сделать.
Существуют ограничения на количество бесплатных обращений к API, подробнее можно прочитать в описании условия(yandex.ru/dev/maps/commercial/).
Формирование карты
После получения API-ключа, нужно снова вернуться в конфигуратор для формирования географической карты.
Создание шаблона карты
Открывается созданный ранее общий модуль «РаботаСКартойКлиентСервер» и добавляется функция, которая будет возвращать шаблон кода HTML для отображения карты. Позднее с помощью функции СтрШаблон будет прописан JavaScript код для добавления различных элементов, таких как точки на карте или маршруты. Подобные примеры можно найти в документации(«yandex.ru/dev/maps/jsapi/doc/2.1/quick-start/index.html) к API Яндекс.Карт. В общем модуле указывается следующий код:
В заголовках HTML-документа добавляется несколько мета-тегов для корректного отображения HTML-поля в мобильной платформе. В стилях указывается ширина и высота, равные 100%, чтобы карта занимала всю область поля HTML, также делаются нулевые отступы по краям. Внутри тела документа создается контейнер, в котором будет размещаться карта. Позднее можно обращаться к данному контейнеру по id.
В этом же общем модуле создается еще одна вспомогательная функция, которая будет возвращать координаты центра карты по умолчанию:
Функция ЦентрКартыПоУмолчанию() Возврат Новый Структура("Широта, Долгота", "55.76", "37.64"); КонецФункции
При формировании карты нужно обязательно указывать центральную точку, но бывают ситуации, когда центр карты заранее неизвестен. Например, необходимо установить центр так, чтобы полностью помещались все отметки на карте. В таком случае изначально устанавливается центр в точке по умолчанию, а затем после добавления всех точек устанавливается новая центральная точка.
Создание функции, возвращающей карту
Можно приступить к написанию основной функции для формирования карты. Создается экспортная функция «ПолучитьКарту»:
Функция будет возвращать готовый HTML-код карты.
Передаваемые параметры:
- Масштаб: число от 0 до 19.
- ЦентрКарты: Структура с двумя ключами — «Широта» и «Долгота». Тип данных у значений — строка.
- Точки: Массив структур. Ключи структуры: «Наименование, Код, Адрес, Широта, Долгота». Тип данных у значений — строка.
В данной функции сначала объявляются шаблоны, в которые далее помещаются параметры. СкриптШаблон содержит JavaScript код, который добавляет карту в созданный ранее контейнер, а также наносит точки на карту. С помощью остальных вспомогательных шаблонов скрипт разделяется на части. В основной части функции в цикле обходится каждый элемент из массива точек и добавляется соответствующий код JavaScript в переменную.
Получение данных для отображения
В модуле менеджера справочника «Магазины» создается экспортная функция для получения информации о всех магазинах в виде массива структур. Результат данной функции позднее будет передан в качестве параметра в уже созданную функцию ПолучитьКарту().
Функция ПолучитьМассивМагазинов() Экспорт МассивМагазинов = Новый Массив; Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ | Магазины.Наименование КАК Наименование, | Магазины.Адрес КАК Адрес, | Магазины.Широта КАК Широта, | Магазины.Долгота КАК Долгота, | Магазины.Код КАК Код |ИЗ | Справочник.Магазины КАК Магазины"; РезультатЗапроса = Запрос.Выполнить(); ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать(); Пока ВыборкаДетальныеЗаписи.Следующий() Цикл СтруктураМагазин = Новый Структура( "Наименование, Код, Адрес, Широта, Долгота"); ЗаполнитьЗначенияСвойств(СтруктураМагазин, ВыборкаДетальныеЗаписи); МассивМагазинов.Добавить(СтруктураМагазин); КонецЦикла; Возврат МассивМагазинов; КонецФункции
Заполнение реквизитов формы
Открывается модуль общей формы «МагазиныНаКарте» и создается процедура, которая будет помещать HTML-код с картой в реквизит формы «КартаHTML». Вызов данной процедуры помещается в обработчик события формы «ПриСозданииНаСервере».
&НаСервере Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка) ОпределитьКарту(); КонецПроцедуры &НаСервере Процедура ОпределитьКарту() МассивМагазинов = Справочники.Магазины.ПолучитьМассивМагазинов(); КартаHTML = РаботаСКартойКлиентСервер.ПолучитьКарту( 8,, МассивМагазинов); КонецПроцедуры
Создание демо-данных
Чтобы на карте отображались магазины, добавляются демо-элементы в справочник «Магазины» с помощью команды.
&НаКлиенте Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды) СоздатьДемоДанныеНаСервере(); Сообщить("Демо данные созданы"); КонецПроцедуры &НаСервере Процедура СоздатьДемоДанныеНаСервере() Маг = Справочники.Магазины.СоздатьЭлемент(); Маг.Наименование = "Продуктовый"; Маг.Адрес = "г. Москва, Дмитровское шоссе, д.9"; Маг.Широта = "55.815494"; Маг.Долгота = "37.575396"; Маг.Записать(); Маг = Справочники.Магазины.СоздатьЭлемент(); Маг.Наименование = "Спортивные товары"; Маг.Адрес = "г. Москва, 3-й Самотёчный пер., 23"; Маг.Широта = "55.779682"; Маг.Долгота = "37.610242"; Маг.Записать(); Маг = Справочники.Магазины.СоздатьЭлемент(); Маг.Наименование = "Товары для дома"; Маг.Адрес = "г. Москва, улица Земляной Вал, 33"; Маг.Широта = "55.757158"; Маг.Долгота = "37.659380"; Маг.Записать(); Маг = Справочники.Магазины.СоздатьЭлемент(); Маг.Наименование = "Магазин зимней одежды"; Маг.Адрес = "г. Москва, площадь Киевского Вокзала, 2"; Маг.Широта = "55.744134"; Маг.Долгота = "37.565362"; Маг.Записать(); Маг = Справочники.Магазины.СоздатьЭлемент(); Маг.Наименование = "Магазин компьютеров"; Маг.Адрес = "г. Москва, Лесная улица, 5сБ"; Маг.Широта = "55.778193"; Маг.Долгота = "37.586796"; Маг.Записать(); КонецПроцедуры
Далее устанавливается свойство «ИспользоватьСтандартныеКоманды» у общей формы и добавляется форма в командный интерфейс.
Первый запуск приложения
При запуске мобильного приложения нужно выполнить команду «Создать демо-данные», чтобы в справочнике появились магазины. После этого нужно перейти в общую форму «Магазины на карте».
На карте отобразились точками магазины, нужно попробовать нажать на одну из точек.
Появляется подсказка с названием магазина, адресом и гиперссылкой для построения маршрута. На данный момент при нажатии на гиперссылку ничего не произойдет, потому что не реализован механизм построения маршрута.
Построение маршрута
После возврата в конфигуратор описываются действия приложения при нажатии на данную ссылку. Чтобы построить маршрут от местоположения пользователя до магазина, системе нужно определить координаты пользователя.
Определение местоположения
В общем модуле «ГеопозиционированиеКлиент» добавляется экспортная функция «ПолучитьМестоположение». Местоположение получается с помощью встроенного объекта «СредстваГеопозиционирования».
Функция ПолучитьМестоположение() Экспорт #Если МобильноеПриложениеКлиент Тогда Если НЕ СредстваГеопозиционирования.ИспользованиеДанныхГеопозиционированияВключено() Тогда ПоказатьПредупреждение(,"Средства геопозиционирования отключены в настройках устройства", 60,"Местоположение неопределено"); Возврат Неопределено; КонецЕсли; Провайдер=СредстваГеопозиционирования.ПолучитьСамогоЭнергоЭкономичногоПровайдера(Истина); Если Провайдер = Неопределено Тогда ПоказатьПредупреждение(, "Не удалось определить местоположение", 60, "Местоположение неопределено"); Возврат Неопределено; КонецЕсли; Если СредстваГеопозиционирования.ОбновитьМестоположение(Провайдер.Имя, 30) Тогда Местоположение = СредстваГеопозиционирования.ПолучитьПоследнееМестоположение(Провайдер.Имя); Если НЕ Местоположение = Неопределено Тогда ГЕОДолгота = Местоположение.Координаты.Долгота; ГЕОШирота = Местоположение.Координаты.Широта; Структура=Новый Структура("Широта, Долгота", Формат(ГЕОШирота, "ЧРД=.; ЧГ=0"), Формат(ГЕОДолгота, "ЧРД=.; ЧГ=0")); Возврат Структура; КонецЕсли; Иначе Местоположение = СредстваГеопозиционирования.ПолучитьПоследнееМестоположение(Провайдер.Имя); Если НЕ Местоположение = Неопределено Тогда ГЕОДолгота = Местоположение.Координаты.Долгота; ГЕОШирота = Местоположение.Координаты.Широта; Структура=Новый Структура("Широта, Долгота", Формат(ГЕОШирота, "ЧРД=.; ЧГ=0"), Формат(ГЕОДолгота, "ЧРД=.; ЧГ=0")); Возврат Структура; Иначе ПоказатьПредупреждение(,"Слабый сигнал GPS. Не удалось получить координаты местоположения. Для определения местоположения попробуйте выключить и включить средства геопозиционирования в настройках устройства.", 60,"Слабый сигнал"); Возврат Неопределено; КонецЕсли; КонецЕсли; #КонецЕсли КонецФункции
Создание функции, возвращающей карту с маршрутом
После этого открывается общий модуль «РаботаСКартойКлиентСервер» и добавляется экспортная функция «ПолучитьМаршрут», которая будет возвращать HTML- код карты с построенным маршрутом. В качестве параметров данная функция будет принимать координаты точки отправления и координаты конечной точки маршрута.
Параметры «ТочкаА» и «ТочкаБ» — это структуры с ключами «Широта» и «Долгота». Свойству «boundsAutoApply» присваивается значение «true», чтобы масштаб и центр карты рассчитались автоматически, и маршрут был виден целиком.
Возвращение к просмотру карты без маршрута
В общую форму «МагазиныНаКарте» добавляется команда формы «ВернутьсяКПросмотруМагазинов». В дерево элементов добавляется кнопка, связанная с данной командой, а также создается обработчик команды на клиенте. Эта команда пригодится для того, чтобы закрыть маршрут и вернуться к просмотру всех точек на карте. Логика команды будет описана чуть позже. В процедуру обработчика события «ПриСозданииНаСервере» добавляется следующая строка:
Элементы.ВернутьсяКПросмотруМагазинов.Видимость = Ложь;
Данная кнопка будет показываться пользователю только при отображении маршрута на карте.
Выбор варианта отображения маршрута
В ранее созданную процедуру «ПолучитьИОбработатьДанные» добавляется код, который определит, что пользователь нажал именно на гиперссылку для построения маршрута. Выделяется код магазина, до которого необходимо построить маршрут с помощью встроенной функции «СтрРазделить».
&НаКлиенте Процедура ПолучитьИОбработатьДанные(href) Если СтрНайти(href, "СоставитьМаршрут") > 0 Тогда КодМагазина = СтрРазделить(href, "|")[1]; УзнатьСпособОтображенияМаршрута(КодМагазина); КонецЕсли; КонецПроцедуры
Создается клиентская процедура «УзнатьСпособОтображенияМаршрута», которая отобразит пользователю вопрос о том, где он хочет построить маршрут до магазина: во внешнем приложении Яндекс.Карты или в текущем.
&НаКлиенте Процедура УзнатьСпособОтображенияМаршрута(КодМагазина) Кнопки = Новый СписокЗначений; Кнопки.Добавить("ЭтаКарта", "Остаться в этом приложении"); Кнопки.Добавить("ВнешнееПриложение", "Перейти в приложение с картами"); Кнопки.Добавить("Отмена", "Отмена"); ОповещениеВопросОтчечен = Новый ОписаниеОповещения("ПослеОтветаНаВопрос", ЭтотОбъект, КодМагазина); ПоказатьВопрос(ОповещениеВопросОтчечен, "Выберите способ отображения маршрута", Кнопки,,,"Где проложить маршрут?"); КонецПроцедуры
Далее в модуль формы добавляется экспортная клиентская процедура «ПослеОтветаНаВопрос», которая будет вызываться после того, как пользователь выберет способ построения маршрута. В этой процедуре определяются координаты местоположения пользователя и координаты магазина, до которого требуется проложить маршрут. Полученные данные отправляются в качестве параметров в процедуры для построения маршрута в соответствии с ответом пользователя.
&НаКлиенте Процедура ПослеОтветаНаВопрос(Результат, КодМагазина) Экспорт Если Результат = "Отмена" Тогда Возврат; Иначе Местоположение = ГеопозиционированиеКлиент.ПолучитьМестоположение(); Если Местоположение = Неопределено Тогда Возврат; КонецЕсли; КоординатыМагазина = ПолучитьКоординатыМагазинаПоКоду(КодМагазина); КонецЕсли; Если Результат = "ЭтаКарта" Тогда СоставитьМаршрут(КоординатыМагазина, Местоположение); ИначеЕсли Результат = "ВнешнееПриложение" Тогда ОткрытьЯндексКартыДляМаршрута(КоординатыМагазина, Местоположение); КонецЕсли; КонецПроцедуры
Получение координат конкретного магазина
Создается серверная функция для получения координат магазина по его коду.
&НаСервере Функция ПолучитьКоординатыМагазинаПоКоду(КодМагазина) Координаты = Новый Структура("Широта, Долгота"); Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ | Магазины.Широта КАК Широта, | Магазины.Долгота КАК Долгота |ИЗ | Справочник.Магазины КАК Магазины |ГДЕ | Магазины.Код = &Код"; Запрос.УстановитьПараметр("Код", КодМагазина); РезультатЗапроса = Запрос.Выполнить(); Выборка = РезультатЗапроса.Выбрать(); Если Выборка.Следующий() Тогда ЗаполнитьЗначенияСвойств(Координаты, Выборка); КонецЕсли; Возврат Координаты; КонецФункции
Открытие внешнего приложения Яндекс.Карты
Теперь необходимо создать процедуры «ОткрытьЯндексКартыДляМаршрута» и «СоставитьМаршрут». Первая будет вызывать открытие внешнего приложения Яндекс.Карты и передавать в параметрах точки для построения маршрута. Вторая отобразит маршрут до выбранного магазина на карте внутри приложения.
Нужно создать клиентскую процедуру «ОткрытьЯндексКартыДляМаршрута». В качестве параметров процедура будет принимать две структуры с ключами «Широта» и «Долгота», содержащие координаты магазина и местоположения пользователя.
&НаКлиенте Процедура ОткрытьЯндексКартыДляМаршрута(КоординатыМагазина, Местоположение) СсылкаДляПереходаШаблон = "yandexmaps://maps.yandex.ru/?rtext=%1,%2~%3,%4&rtt=auto"; СсылкаДляПерехода = СтрШаблон(СсылкаДляПереходаШаблон, Местоположение.Широта, Местоположение.Долгота, КоординатыМагазина.Широта, КоординатыМагазина.Долгота); ЗапуститьПриложение(СсылкаДляПерехода); КонецПроцедуры
В процедуре используется встроенный метод платформы «ЗапуститьПриложение», в параметры которого помещается навигационная ссылка для открытия приложения Яндекс.Карты. Как формируется навигационная ссылка можно прочитать в документации(yandex.ru/dev/yandex-apps-launch/maps/doc/concepts/yandexmaps-android-app.html) для разработчиков.
Отображение маршрута внутри приложения 1С
Создается клиентская процедура «СоставитьМаршрут», которая также в качестве параметров будет принимать две структуры с ключами «Широта» и «Долгота», содержащие координаты магазина и местоположения пользователя.
&НаКлиенте Процедура СоставитьМаршрут(КоординатыМагазина, Местоположение) Элементы.ВернутьсяКПросмотруМагазинов.Видимость = Истина; КартаHTML = РаботаСКартойКлиентСервер.ПолучитьМаршрут(Местоположение, КоординатыМагазина); КонецПроцедуры
Помимо присвоения реквизиту формы HTML-кода карты с маршрутом, в данной процедуре будет включена видимость кнопки «ВернутьсяКПросмотруМагазинов», чтобы пользователь мог вернуться обратно к карте с расположением всех магазинов.
Осталось описать действия системы при нажатии на кнопку «ВернутьсяКПросмотруМагазинов». Кнопка должна отображаться только когда на карте отображен маршрут. Поэтому при нажатии устанавливается видимость кнопки в значение «Ложь», а также вызывается процедура «ОпределитьКарту» для того, чтобы на карте снова появились точки всех магазинов.
&НаКлиенте Процедура ВернутьсяКПросмотруМагазинов(Команда) Элементы.ВернутьсяКПросмотруМагазинов.Видимость = Ложь; ОпределитьКарту(); КонецПроцедуры
Запуск готового мобильного приложения
Теперь нужно попробовать запустить приложение и посмотреть, что получилось. После открытия нужно сразу перейти в форму «Магазины на карте». Нужно нажать на одну из точек, и затем на гиперссылку «Проложить маршрут до этого магазина». Мобильное приложение спрашивает пользователя о том, где необходимо проложить маршрут.
Сначала нужно выбрать первый вариант «Остаться в этом приложении».
Видно, что на картах действительно появился маршрут от местоположения пользователя до выбранного магазина, а также появилась кнопка «Вернуться к просмотру магазинов». Нужно нажать на эту кнопку и попробовать другой вариант построения маршрута. Снова нужно выбрать магазин на карте, нажать появившуюся гиперссылку. Теперь на вопрос системы о способе отображения маршрута нужно ответить «Перейти в приложение с картами».
Запустилось приложение Яндекс.Карты и сразу показан необходимый маршрут.
Таким образом, разработано мобильное приложение, которое умеет определять местоположение пользователя, отображать на географической карте точки с краткой информацией об отображаемом объекте, формировать, а также отображать маршруты как в самом приложении, так и во внешнем.
С помощью языка разметки HTML можно создавать не только карты в мобильном приложении 1С, но и целые формы.
Подробнее о создании пользовательских интерфейсов с помощью HTML читайте в следующих статьях по мобильной разработке.