Пример интерактивной работы с картами 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 не будет опубликован. Обязательные поля помечены *