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

Опубликовал Anton Loginchev (logos) в раздел Обмен - Интеграция с WEB

В этой публикации приведен пример, как можно взаимодействовать с 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()");

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

Скачать файлы

Наименование Файл Версия Размер
карты инфостарт2.dt
.dt 86,24Kb
16.10.12
164
.dt 86,24Kb 164 Скачать

См. также

Комментарии
1. Максим Волков (maxlenium) 34 17.10.12 08:31 Сейчас в теме
Интересная разработка. Правда она идет в виде конфигурации, т.е. она оторвана от клиентской базы? Все данные надо заносить вручную?
2. Максим Волков (maxlenium) 34 17.10.12 08:39 Сейчас в теме
Кстати, я бы сказал даже отличная разработка. Нужно просто разобраться с некоторыми кнопками. Фактически создание и корректировка объектов идет на карте.
3. Anton Loginchev (logos) 59 17.10.12 08:49 Сейчас в теме
(1) maxlenium, Это пример, шаблон. Я его выдернул из одного своего проекта, по сути база тут нужна, как хранилище точек с дополнительными характеристиками. В полной версии ещё были фильтры по областям, рисованным на карте, по дополнительным признакам, но это было уже достаточно тривиально, поэтому было обрезано. Обработка возможна и без привязки к БД, но в её рамках хотелось показать взаимодействие, как GUIDы объектов передаются туда-обратно на хтмл страницу и параллельно модификации карты меняются и объекты БД с ней связанные.
4. Данила Елистратов (CagoBHuK) 25 17.10.12 10:58 Сейчас в теме
5. Anton Loginchev (logos) 59 17.10.12 11:08 Сейчас в теме
(4) CagoBHuK, Прям дежавю какое то. "Давно сделано" просит денег. Эта разработка - бесплатная.
6. Anton Loginchev (logos) 59 17.10.12 11:10 Сейчас в теме
(4) CagoBHuK, Хотя, Вас, как автора http://forum.infostart.ru/forum24/topic42266/ вполне можно понять. Своё детище нужно защищать и продвигать. :-)
7. Андрей Комар (akomar) 377 20.10.12 20:39 Сейчас в теме
Поставил +. Очень хорошая бесплатная разработка.
8. Anton Loginchev (logos) 59 20.10.12 22:59 Сейчас в теме
9. Сергей Камнев (Sergey Kamnev) 22.10.12 10:04 Сейчас в теме
1. Есть ли кэширование?
2. Есть ли возможность работать офф-лайн (версия Яндекс.Карты под Android может быть скачена для оффлайн просмотра, правда, при этом не работает поиск)?
3. Почему Google Maps, а не Яндекс.Карты?
10. Anton Loginchev (logos) 59 22.10.12 10:22 Сейчас в теме
(9) Sergey Kamnev,
1. Сейчас работает сугубо интерактивно, вопрос кэширования не поднимался.
2. Соответственно, вопрос не поднимался.
3. АПИ у гугла приятнее документирован. Основной упор ставился именно на взаимодействие с сеансом 1С, у яндекса описание объектов событий, передаваемых в обработчик события я не нашёл, может плохо искал. За сим был избран гугл.
11. Сергей Камнев (Sergey Kamnev) 22.10.12 13:24 Сейчас в теме
logos, ясно, спасибо за ответ.

Программу взял на заметку. Спасибо за труд!
12. Серж Иванов (adminfo2002) 96 21.02.13 16:09 Сейчас в теме
Отличная разработка.
Долго мучался с картами и проблемой отлавливания событий в 1С - сразу снялись все вопросы.
Спасибо автору :)
SunShinne; +1 Ответить
13. Сергей Алферов (SunShinne) 592 03.01.14 19:15 Сейчас в теме
Ставлю + безусловно. Однако у меня не работает - карты вообще не отображаются.
14. Сергей Алферов (SunShinne) 592 03.01.14 19:37 Сейчас в теме
может Гугл что-то поменял в кодах?
15. Сергей Алферов (SunShinne) 592 03.01.14 19:46 Сейчас в теме
при попытке поставить флаг "Ввод новых объектов" в карте объектов развития выводится следующая ошибка:
{Обработка.КартаСостоянийТК.Форма.Форма.Форма(56)}: Метод объекта не обнаружен (Eval)
Результат = Элемент.Документ.parentWindow.Eval(Код);
16. Сергей Алферов (SunShinne) 592 09.01.14 20:49 Сейчас в теме
Нашел ошибку в коде Java - Обработки.КартаСостоянияТК.Макеты.МакетГуглВерсия3Текст надо заменить в тексте map_canvas на map-canvas, после исправления все работает.
17. Сергей Алферов (SunShinne) 592 09.01.14 20:54 Сейчас в теме
то же исправление требуется для ОбластиНаКарте.Макет
18. Anton Loginchev (logos) 59 13.01.14 10:05 Сейчас в теме
Действительно, поменял гугл. Раньше у них в апи было предопределено имя map_canvas, потом заменили подчеркивание на тире. Альтернативный вариант - можно вручную для map_canvas задавать его размеры, что создает лишние проблемы с ресайзом итп. Сам недавно случайно заметил этот нюанс, обновить публикацию забыл. Спасибо за комментарий.
19. Павел Титов (JIeHIH) 17.01.14 19:27 Сейчас в теме
Возможно не совсем в тему, но все же, столкнулся с проблемой.
Стоит цель не программно дописывать код скрипта по добавлению координат полигона, а через функцию скрипта передавать координаты. Как я понимаю это нужно делать в обработчике события ДокументСформирован, вот только почему то при попытке обратиться к объекту у которого есть метод по добавлению координат, возвращается ошибка мол нет такого объекта, если я выполняю перед этим инициализацию программно через 1с, то переменную видит.
И еще почему то событие ДокументСформирован срабатывает дважды.
20. Александр Ковалев (kovaleks78) 3 17.01.14 22:14 Сейчас в теме
Есть задача вывести на карте района точки по списку адресов в 1С. Что посоветуете использовать для решения?
21. Anton Loginchev (logos) 59 18.01.14 16:15 Сейчас в теме
(19) JIeHIH, Криво, но можно использовать глобальную переменную, которая хранит ссылку на полигон, вызывать методы, добавляющие точки в полигон через eval.
(20) kovaleks78, По списку адресов сложнее, нужно делать запросы к тому же гуглу или яндексу, чтоб получить координаты по адресу, а так не принципиально чем. У меня, например, выводится список точек на карте, правда не по адресам, а по координатам.
22. Павел Титов (JIeHIH) 20.01.14 10:39 Сейчас в теме
(21) logos, Возможно я немного некорректно изложил проблему, в скрипте я завел глобальную переменную, которая является полигоном, код взял у гугла в примерах, там создается объект полигона у которого есть методы добавления координат, присвоение этого полигона переменной происходит в момент обновления страницы, так вот задача узнать когда это произойдет, когда отработает скрипт.