1c-crm-red
Как интегрировать Яндекс.Карты в мобильное приложение 1C
27.02.2023

Как интегрировать Яндекс.Карты в мобильное приложение 1C

Разработчики мобильных приложений на платформе 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 читайте в следующих статьях по мобильной разработке.

Автор статьи

Чубай Владислав
Чубай Владислав

Инженер-программист группы мобильной разработки

Есть вопросы по статье? Задайте их нам!
info-big
Рассылка «Новости компании»: узнавайте о новых продуктах, услугах и спецпредложениях
Отправляя эту форму, Вы соглашаетесь с Политикой конфиденциальности и даете согласие на обработку персональных данных компанией «1С-Рарус»

Остались вопросы?
Нужна консультация?
Свяжитесь с нами!