Вывод интерактивной карты в форму 1С: способы и настройка

· 9 мин

Содержание

Карту в 1С выводят в элемент формы типа «Поле HTML документа»: в реквизит-строку кладут HTML с инициализацией Яндекс.Карт, а само поле показывает результат. Это основной путь для 8.3 с интерфейсом «Такси» — он не требует установки компонент на каждый клиент и одинаково работает в тонком и веб-клиенте.

Три варианта, из которых выбирают: поле HTML (быстро, почти без ограничений по JS), готовая внешняя компонента (нативный рендер, но нужна установка и подпись) и чистая API-интеграция, когда карта нужна не на форме, а для фоновых задач — например, перевести адрес из справочника в координаты. Ниже — когда какой брать, как настроить каждый и что делать с типовыми сбоями.

Какой способ показать карту выбрать

Отталкивайтесь от того, где карта нужна и кто ей пользуется.

СпособКогда подходитМинусы
Поле HTML документаКарта на управляемой форме: точки клиентов, маршруты, выбор адреса мышьюJS грузится из интернета, нужен доступ к api-maps.yandex.ru
Внешняя компонентаНужен нативный рендер, работа без постоянного интернета, тесная связка с данными 1СУстановка и доверие компоненте, сопровождение при обновлении платформы
HTTP-запрос к API (геокодер)Координаты и адреса нужны на сервере: заполнить реквизит, построить отчёт, без визуальной картыКарту «вживую» не показывает, только данные

Короткий ориентир по таблице: карта на форме — поле HTML; координаты без картинки — геокодер на сервере; автономность и глубокая связка с объектами 1С — внешняя компонента.

В 9 случаях из 10 для задач «показать адреса на карте» или «выбрать точку» хватает поля HTML. К компонентам переходят, когда HTML-поля уже не хватает.

Вывод карты через поле HTML документа

Это рабочая лошадка. Поле показывает произвольный HTML, а значит и любую JS-карту — Яндекс, 2ГИС или Google.

Что настроить в Конфигураторе:

  1. Откройте форму, куда встраиваете карту (например, форму списка контрагентов или обработку).
  2. Добавьте реквизит формы типа Строка, неограниченной длины. Назовите, скажем, ДанныеКарты.
  3. Добавьте элемент формы «Поле». В свойстве «Вид» выберите Поле HTML документа.
  4. Свяжите элемент с реквизитом: в свойстве «ПутьКДанным» укажите ДанныеКарты.

Теперь в реквизит нужно положить HTML. Сделайте это в обработчике ПриСозданииНаСервере или ПриОткрытии:

&НаСервере
Процедура ПриСозданииНаСервереСформироватьКарту()
    Шаблон =
    "<!DOCTYPE html>
    |<html><head>
    |<script src='https://api-maps.yandex.ru/2.1/?apikey=ВАШ_КЛЮЧ&lang=ru_RU'></script>
    |<style>html,body,#map{width:100%;height:100%;margin:0}</style>
    |</head><body><div id='map'></div>
    |<script>
    |ymaps.ready(function(){
    |  var map = new ymaps.Map('map', {center:[55.751,37.618], zoom:10});
    |  map.geoObjects.add(new ymaps.Placemark([55.751,37.618], {balloonContent:'Офис'}));
    |});
    |</script></body></html>";

    ДанныеКарты = Шаблон;
КонецПроцедуры

Координаты в Яндекс.Картах идут «широта, долгота» — именно в таком порядке в массиве JS. Перепутаете — метка уедет в другое полушарие.

Если точек много, не вставляйте их руками в шаблон. Соберите на сервере JSON из справочника и подставьте одной строкой в <script>:

Выборка = Запрос.Выполнить().Выбрать();
МассивТочек = Новый Массив;
Пока Выборка.Следующий() Цикл
    МассивТочек.Добавить(Новый Структура("Широта,Долгота,Текст",
        Выборка.Широта, Выборка.Долгота, Выборка.Наименование));
КонецЦикла;

ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, МассивТочек);
СтрокаТочек = ЗаписьJSON.Закрыть();

Дальше СтрокаТочек подставляется в шаблон, а JS в цикле добавляет метки через map.geoObjects.add.

Как прочитать клик по карте обратно в 1С

Частая задача — пользователь ткнул в карту, а 1С должна узнать координаты точки. После загрузки документа у поля срабатывает событие «Документ сформирован». В его обработчике на клиенте доступен DOM через Элементы.ПолеКарты.Документ:

&НаКлиенте
Процедура ПолеКартыДокументСформирован(Элемент)
    Документ = Элементы.ПолеКарты.Документ;
    // через Документ.defaultView доступен window и ваши JS-функции
КонецПроцедуры

Обратный канал «из JS в 1С» делают просто: JS при клике пишет координаты в скрытый элемент DOM (например, в value поля input), а 1С по кнопке или таймеру читает это значение из Документ. Схема неказистая, но надёжная и работает в тонком и веб-клиенте одинаково.

Готовые внешние компоненты и решения

Внешняя компонента рисует карту средствами ОС, а не через встроенный браузер. Её берут, когда поля HTML мало: нужен офлайн-режим, тяжёлые слои или скорость на тысячах объектов.

Что учесть перед внедрением:

  • 🔌 Компоненту нужно подключить методом ПодключитьВнешнююКомпоненту и, как правило, положить в макет конфигурации или в общий макет.
  • 🖥️ Для веб-клиента компонента должна быть собрана под браузер (технология Native API), иначе заработает только в тонком клиенте под Windows.
  • 🔄 При смене версии платформы компоненту иногда приходится пересобирать или обновлять — это сопровождение, которого нет у поля HTML.

Готовые решения проще не писать самому, а взять с Инфостарта: там есть обёртки над Яндекс.Картами, 2ГИС и OpenStreetMap, часть бесплатна, часть платная (ориентировочно от нескольких сотен до пары тысяч рублей за разработку). Перед покупкой проверьте, под какую платформу и какой клиент собрана компонента.

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

Подключение API Яндекс.Карт: ключ и инициализация

Без API-ключа JS-карта либо не загрузится, либо будет ругаться в консоли браузера. Ключ получают в кабинете разработчика Яндекса (раздел для JavaScript API и Геокодера).

Порядок:

  1. Заведите аккаунт в кабинете разработчика Яндекса.
  2. Создайте ключ для нужного продукта. JS API и HTTP Геокодер — это РАЗНЫЕ ключи, один вместо другого не подойдёт.
  3. Для веб-варианта пропишите список доменов, с которых разрешены запросы.
  4. Подставьте ключ в параметр apikey у тега <script> (для JS) или в строку запроса (для геокодера).

О стоимости коротко. У Яндекса есть бесплатный лимит на число загрузок карты и геокодирований в сутки; при превышении включается платный тариф по договору. Google Maps требует привязки карты оплаты (billing) и даёт ежемесячный бесплатный объём, сверх него — поминутная тарификация. У 2ГИС есть бесплатный MapGL для ограниченного использования. Точные цифры и условия смотрите на странице тарифов выбранного сервиса — они меняются, выдумывать их не стоит.

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

Яндекс, 2ГИС или Google — что встраивать

Техника встраивания для всех трёх одинакова: тот же тег <script> с ключом и инициализация карты в поле HTML. Отличается только API и условия:

  • Яндекс.Карты. Лучшее покрытие адресов по России, подробный геокодер по российским улицам и домам. Документация на русском. Для задач с отечественными контрагентами — вариант по умолчанию.
  • 2ГИС (MapGL). Сильная детализация по городам: этажность, организации внутри зданий, входы. Удобно для доставки и выездных служб. Покрытие сильнее в крупных городах.
  • Google Maps. Глобальное покрытие, если среди контрагентов есть зарубежные адреса. Требует привязки карты оплаты даже для бесплатного объёма — для чисто российской базы избыточен.

Менять провайдера на уже готовой форме несложно: HTML-поле и логика заполнения реквизитов остаются, переписывается только содержимое <script> и строка запроса к геокодеру.

Геокодирование адресов: из строки в координаты

Геокодер превращает адрес («Москва, Тверская, 7») в пару координат. Это нужно, чтобы поставить метку на карту или просто записать широту и долготу в реквизиты справочника — без визуальной карты вообще.

Запрос идёт с сервера 1С по HTTP. Пример функции для Яндекс HTTP Геокодера:

&НаСервере
Функция ПолучитьКоординаты(Адрес)
    Ключ = "ВАШ_КЛЮЧ_ГЕОКОДЕРА";

    Соединение = Новый HTTPСоединение("geocode-maps.yandex.ru", 443,
        , , , , Новый ЗащищенноеСоединениеOpenSSL);

    АдресURL = КодироватьСтроку(Адрес, СпособКодированияСтроки.КодировкаURL);
    Ресурс = "/1.x/?apikey=" + Ключ + "&format=json&geocode=" + АдресURL;

    Ответ = Соединение.Получить(Новый HTTPЗапрос(Ресурс));
    Если Ответ.КодСостояния <> 200 Тогда
        Возврат Неопределено;
    КонецЕсли;

    Чтение = Новый ЧтениеJSON;
    Чтение.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку());
    Данные = ПрочитатьJSON(Чтение);
    Чтение.Закрыть();

    Коллекция = Данные["response"]["GeoObjectCollection"]["featureMember"];
    Если Коллекция.Количество() = 0 Тогда
        Возврат Неопределено; // адрес не распознан
    КонецЕсли;

    Поз = Коллекция[0]["GeoObject"]["Point"]["pos"]; // "долгота широта"
    Части = СтрРазделить(Поз, " ");
    Возврат Новый Структура("Широта,Долгота", Число(Части[1]), Число(Части[0]));
КонецФункции

Два момента, на которых спотыкаются:

  • В ответе геокодера строка pos содержит сначала долготу, потом широту — наоборот относительно порядка в JS-карте. Поэтому в структуре выше Части[1] это широта, а Части[0] долгота.
  • Адрес обязательно кодируется через КодироватьСтроку(..., СпособКодированияСтроки.КодировкаURL), иначе пробелы и кириллица сломают запрос.

Чтобы не дёргать геокодер каждый раз, сохраняйте полученные координаты в реквизиты справочника контрагентов или адресов. Повторный расчёт делайте только когда адрес изменился — так вы не упираетесь в суточный лимит.

Производительность и практические хитрости

Карта с сотнями меток легко начинает тормозить. Несколько приёмов, которые реально помогают:

  • 📍 Кластеризация меток. Вместо тысячи Placemark используйте ymaps.Clusterer — близкие точки схлопываются в один значок с числом. Форма перестаёт зависать.
  • 💾 Кэшируйте координаты. Геокодьте адрес один раз и храните результат. Повторное геокодирование одного и того же адреса — пустая трата лимита.
  • ⏳ Грузите карту по требованию. Если поле на вкладке, которую открывают редко, формируйте HTML не при открытии формы, а при активации страницы — форма откроется быстрее.
  • 🌐 Проверьте доступ в интернет с сервера и с клиента. Для JS-карты интернет нужен на машине пользователя (браузер тянет api-maps), для геокодера — на сервере 1С.

Если карта нужна в отчёте или на печать, снимайте со статической Static API картинкой по координатам — это быстрее и не зависит от JS в поле.

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

Перед первым запуском пройдитесь по короткому списку — он снимает большинство «карта не рисуется»:

Что проверить перед запуском карты
Выполнено: 0 / 6

Типичные ошибки при выводе карты

Большинство сбоев — это либо ключ, либо доступ в сеть, либо порядок координат.

Диагностика: выберите симптом

Частые вопросы

Нужен ли ключ, если карта только для внутренней базы?
Да. JS API Яндекс.Карт требует ключ в любом случае, даже для одного пользователя. Разница только в тарифе: для внутренней базы почти всегда хватает бесплатного лимита.
Можно ли показать карту в веб-клиенте 1С?
Да, поле HTML документа работает и в тонком, и в веб-клиенте. Внешняя компонента — только если она собрана под браузер по технологии Native API.
Чем геокодер отличается от карты?
Карта (JS API) рисует интерактивную картинку в поле. Геокодер (HTTP API) ничего не рисует — он по строке адреса возвращает координаты, которые вы сами записываете в реквизиты или ставите на карту.
Что выбрать для офлайн-работы без интернета?
Поле HTML и облачные API не подойдут — им нужен интернет. Нужна внешняя компонента с локальным картографическим движком либо заранее подготовленные тайлы.
Почему метки встали в океане у берегов Африки?
Классический признак нулевых или перепутанных координат. Проверьте, что в справочнике не пустые широта/долгота и что порядок координат не перевёрнут при передаче в JS.