Пример интерактивной работы с картами Google.



В этой публикации приведен пример, как можно взаимодействовать с Google Maps API, интерактивно создавать и редактировать объекты карты, обрабатывать события объектов карты.

К сожалению, прошлая публикация была потёрта в результате какой то ошибке на сервере базы данных, поэтому приходится создавать новую, улучшенную версию. В этой публикации я постараюсь рассмотреть способ взаимодействия с картами не как со статичным объектом, когда предварительно формируется текст html страницы, который показывается пользователю, а как с объектом, обладающим «рычагами» для управления.

В тестовом примере показаны: рисование полигонов в статике из данных БД, рисование маркеров в статике, создание маркеров интерактивно без перерисовки карты, перемещение маркеров.

Массив статических элементов передается при формировании страницы, как xml блок, ввиду чего, к сожалению, страница некорректно работает в firefox. Проблема легко лечится вынесением массива из html блока и формированием объектов динамически.

Для динамических изменений веб страницы необходимо вызывать её скриптовые функции. В 1С это выглядит довольно «неудобно»:

Функция Скрипт(Элемент,Код)
Результат = Элемент.Документ.parentWindow.Eval(Код);
Возврат Результат;
КонецФункции

Для собственного удобства я обернул вызов javascript кода в функцию. Здесь «Элемент» — поле HTML текста, а «Код» — код на языке javascript. Для вызова доступны глобальные переменные блока и функции оттуда же. Поэтому, для создания маркера мы создаем функцию в макете html страницы, которая по списку параметров создает маркер:

function placemarker(iconId,lat,lng,title,GUID){
var pos = new google.maps.LatLng(parseFloat(lat), parseFloat(lng));
var marker = new google.maps.Marker({ position: pos, map: map, title: title, icon: icons[iconId] });
}

В функцию передаются текстовые значения координат, названия точки и иконки (если она есть)

Кроме того, что маркер размещается на поле HTML документа, необходимо отразить его создание в базе данных. Для этого создаются подписки на события нажатия на карту.

google.maps.event.addListener(map, 'click', mapClick);

function mapClick(event) {
sender = "map";
eventname = "click";
latlng = event.latLng;
}

Обработчик устанавливает значения глобальных переменных, к сожалению более красивого способа я пока не нашёл. Эти глобальные переменные доступны в обработчике нажатия на поле HTML документа в 1С. С помощью переменной sender определяется объект, с которым произошло событие, с помощью eventname — само событие, а в переменной latlng находятся координаты, если они применимы.

В обработке нажатия на поле HTML текста осуществляется обработка всех подобных событий.

&НаКлиенте
Процедура ПолеHTMLТекстаПриНажатии(Элемент, ДанныеСобытия, СтандартнаяОбработка)
ИсточникСобытия  = Скрипт(Элемент,"sender");
Событие    = Скрипт(Элемент,"eventname");
Если ИсточникСобытия = "map" И Событие = "dragend" Тогда
Возврат;
КонецЕсли;
Широта = Скрипт(Элемент,"latlng.lat()");
Долгота = Скрипт(Элемент,"latlng.lng()");
Если ИсточникСобытия = "marker" Тогда
GUID  = Скрипт(Элемент,"myGUID");
ТК = ПолеHTMLТекстаПриНажатииНаСервере(GUID);
Если Событие = "click" Тогда
Если НЕ ТК = Неопределено ИЛИ ВводНовыхОбъектов Тогда
ПараметрыФормы  = Новый Структура("Ключ",ТК);
Форма = ПолучитьФорму("Справочник.ОбъектыРазвития.ФормаОбъекта",ПараметрыФормы);
ДанныеФормы = Форма.Объект;
ЗаполнитьНаСервере(ДанныеФормы,Широта,Долгота);
КопироватьДанныеФормы(ДанныеФормы,Форма.Объект);
Форма.ОткрытьМодально();
КонецЕсли;
ИначеЕсли Событие = "dragend" Тогда
ПараметрыОбновления = Новый Структура("Широта,Долгота,GUID",Широта,Долгота,GUID);
Структура = Новый ФиксированнаяСтруктура(ПараметрыОбновления);
ОбновитьКоординатыТК(Структура);
КонецЕсли;
ИначеЕсли ИсточникСобытия = "map" И Событие = "click" И ВводНовыхОбъектов Тогда
ВводНовогоТК = Истина;
ПараметрыФормы  = Новый Структура("Ключ",ТК);
Форма = ПолучитьФорму("Справочник.ОбъектыРазвития.ФормаОбъекта",ПараметрыФормы);
ДанныеФормы = Форма.Объект;
ЗаполнитьНаСервере(ДанныеФормы,Широта,Долгота);
КопироватьДанныеФормы(ДанныеФормы,Форма.Объект);
Форма.ОткрытьМодально();
КонецЕсли;
КонецПроцедуры

Следующим образом получаются значения глобальных переменных, играющих роль параметров события. Дальнейшая обработка тривиальна, рассматривать её не будем.

ИсточникСобытия = Скрипт(Элемент,"sender");

Широта = Скрипт(Элемент,"latlng.lat()");

Долгота = Скрипт(Элемент,"latlng.lng()");

Аналогичным образом осуществляется и перемещение маркеров. Только вместо события карты вызывается событие маркера, которое привязывается к нему при создании.

26 Comments

  1. maxlenium

    Интересная разработка. Правда она идет в виде конфигурации, т.е. она оторвана от клиентской базы? Все данные надо заносить вручную?

    Reply ↓
  2. maxlenium

    Кстати, я бы сказал даже отличная разработка. Нужно просто разобраться с некоторыми кнопками. Фактически создание и корректировка объектов идет на карте.

    Reply ↓
  3. logos

    (1) maxlenium, Это пример, шаблон. Я его выдернул из одного своего проекта, по сути база тут нужна, как хранилище точек с дополнительными характеристиками. В полной версии ещё были фильтры по областям, рисованным на карте, по дополнительным признакам, но это было уже достаточно тривиально, поэтому было обрезано. Обработка возможна и без привязки к БД, но в её рамках хотелось показать взаимодействие, как GUIDы объектов передаются туда-обратно на хтмл страницу и параллельно модификации карты меняются и объекты БД с ней связанные.

    Reply ↓
  4. CagoBHuK

    Давно сделано: http://forum.infostart.ru/forum24/topic42266/

    Reply ↓
  5. logos

    (4) CagoBHuK, Прям дежавю какое то. «Давно сделано» просит денег. Эта разработка — бесплатная.

    Reply ↓
  6. logos

    (4) CagoBHuK, Хотя, Вас, как автора http://forum.infostart.ru/forum24/topic42266/ вполне можно понять. Своё детище нужно защищать и продвигать. 🙂

    Reply ↓
  7. akomar

    Поставил +. Очень хорошая бесплатная разработка.

    Reply ↓
  8. logos

    (7) akomar, Спасибо

    Reply ↓
  9. Sergey Kamnev

    1. Есть ли кэширование?

    2. Есть ли возможность работать офф-лайн (версия Яндекс.Карты под Android может быть скачена для оффлайн просмотра, правда, при этом не работает поиск)?

    3. Почему Google Maps, а не Яндекс.Карты?

    Reply ↓
  10. logos

    (9) Sergey Kamnev,

    1. Сейчас работает сугубо интерактивно, вопрос кэширования не поднимался.

    2. Соответственно, вопрос не поднимался.

    3. АПИ у гугла приятнее документирован. Основной упор ставился именно на взаимодействие с сеансом 1С, у яндекса описание объектов событий, передаваемых в обработчик события я не нашёл, может плохо искал. За сим был избран гугл.

    Reply ↓
  11. Sergey Kamnev

    logos, ясно, спасибо за ответ.

    Программу взял на заметку. Спасибо за труд!

    Reply ↓
  12. free-lancer-2018

    Отличная разработка.

    Долго мучался с картами и проблемой отлавливания событий в 1С — сразу снялись все вопросы.

    Спасибо автору 🙂

    Reply ↓
  13. SunShinne

    Ставлю + безусловно. Однако у меня не работает — карты вообще не отображаются.

    Reply ↓
  14. SunShinne

    может Гугл что-то поменял в кодах?

    Reply ↓
  15. SunShinne

    при попытке поставить флаг «Ввод новых объектов» в карте объектов развития выводится следующая ошибка:

    {Обработка.КартаСостоянийТК.Форма.Форма.Форма(56)}: Метод объекта не обнаружен (Eval)

    Результат = Элемент.Документ.parentWindow.Eval(Код);

    Reply ↓
  16. SunShinne

    Нашел ошибку в коде Java — Обработки.КартаСостоянияТК.Макеты.МакетГуглВерсия3Текст надо заменить в тексте map_canvas на map-canvas, после исправления все работает.

    Reply ↓
  17. SunShinne

    то же исправление требуется для ОбластиНаКарте.Макет

    Reply ↓
  18. logos

    Действительно, поменял гугл. Раньше у них в апи было предопределено имя map_canvas, потом заменили подчеркивание на тире. Альтернативный вариант — можно вручную для map_canvas задавать его размеры, что создает лишние проблемы с ресайзом итп. Сам недавно случайно заметил этот нюанс, обновить публикацию забыл. Спасибо за комментарий.

    Reply ↓
  19. JIeHIH

    Возможно не совсем в тему, но все же, столкнулся с проблемой.

    Стоит цель не программно дописывать код скрипта по добавлению координат полигона, а через функцию скрипта передавать координаты. Как я понимаю это нужно делать в обработчике события ДокументСформирован, вот только почему то при попытке обратиться к объекту у которого есть метод по добавлению координат, возвращается ошибка мол нет такого объекта, если я выполняю перед этим инициализацию программно через 1с, то переменную видит.

    И еще почему то событие ДокументСформирован срабатывает дважды.

    Reply ↓
  20. kovaleks78

    Есть задача вывести на карте района точки по списку адресов в 1С. Что посоветуете использовать для решения?

    Reply ↓
  21. logos

    (19) JIeHIH, Криво, но можно использовать глобальную переменную, которая хранит ссылку на полигон, вызывать методы, добавляющие точки в полигон через eval.

    (20) kovaleks78, По списку адресов сложнее, нужно делать запросы к тому же гуглу или яндексу, чтоб получить координаты по адресу, а так не принципиально чем. У меня, например, выводится список точек на карте, правда не по адресам, а по координатам.

    Reply ↓
  22. JIeHIH

    (21) Возможно я немного некорректно изложил проблему, в скрипте я завел глобальную переменную, которая является полигоном, код взял у гугла в примерах, там создается объект полигона у которого есть методы добавления координат, присвоение этого полигона переменной происходит в момент обновления страницы, так вот задача узнать когда это произойдет, когда отработает скрипт.

    Reply ↓
  23. 7OH

    «Ваш браузер не поддерживается Google Maps JavaScript API. Выберите другой.Подробнее…Закрыть»

    Что посоветуете делать?

    Reply ↓
  24. Mellow

    (23) 1С использует стандартный com компонент webbrowser который предоставляет windows. По умолчанию для всех приложений эта компонента работает в режиме совместимости IE7. Для смены режима совместимости требуется добавить в реестр ключ с именем приложения и кодом уровня совместимости.

    Подробнее здесь: https://weblog.west-wind.com/posts/2011/May/21/Web-Browser-Control-Specifying-the-IE-Version

    Reply ↓
  25. andrey235

    Карта вообще не отображается в 1С, хоть и учел изменения из (16). Автор писал, что учтет в публикации, но не сделал этого. Выгрузил итоговый скрипт в текстовый файл html, добавил свой google key в заголовок. После этого карта запускается из html в браузере, но никаких меток не выводит. В 1С всё равно не отображается. Помогите, пож., я пока совсем зелёный в этом.

    Reply ↓
  26. logos

    (25) Это писалось в 2012 году, когда в платформу был встроен движок IE 9 (кажется), тогда это работало. Потом многое было переписано в угоду большей безопасности, современным браузерам. Некоторые наработки по использованию ПолеHTMLДокумента я публиковал в другой статье, про работу с большими данными. Оттуда можно взять «скелет» фрейма и в него уже положить страницу с гуглокартами. Подозреваю, что ещё и апи у гуглокарт могло с тех пор поменяться.

    Вот ссылка на статью.

    Постараюсь найти время и актуализировать эту статью под современные реалии.

    Reply ↓

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *