Как закалялся код...: Компонент Карты Гугл в 1С битрикс. Свое изображение маркера.

понедельник, 9 июня 2014 г.

Компонент Карты Гугл в 1С битрикс. Свое изображение маркера.

Изначально версия компонента битрикс Карты Гугл (bitrix:map.google.view) при установке маркеров на карте позволяет установить только собственно координаты маркера (долгота и широта - LON и LAT) и содержание всплывающего по клику маркера окна (TEXT) которое может быть HTML содержимым.

Требуется иметь возможность указывать свое изображение маркера для каждой точки, и попутно всплывающую подсказку (TITLE). В действительности по данной инструкции можно настроить и другие возможности расположения маркеров api карт гугл.



Итак, вставляем компонент гугл карти битрикс map.google.view и копируем стандартный шаблон компонента. Для добавления новых возможностей понадобится поправить javascript код шаблона компонента (файл script.js). Открываем файл, находим код добавления маркеров:


window.BX_GMapAddPlacemark = function(arPlacemark, map_id)
 {
  var map = GLOBAL_arMapObjects[map_id];
  
  if (null == map)
   return false;

  if(!arPlacemark.LAT || !arPlacemark.LON)
   return false;

  var obPlacemark = new google.maps.Marker({
   'position': new google.maps.LatLng(arPlacemark.LAT, arPlacemark.LON),
   'map': map
  });
  
  if (BX.type.isNotEmptyString(arPlacemark.TEXT))
  {
   obPlacemark.infowin = new google.maps.InfoWindow({
    content: arPlacemark.TEXT.replace(/\n/g, '
')
   });
   
   google.maps.event.addListener(obPlacemark, 'click', function() {
    if (null != window['__bx_google_infowin_opened_' + map_id])
     window['__bx_google_infowin_opened_' + map_id].close();

    this.infowin.open(this.map, this);
    window['__bx_google_infowin_opened_' + map_id] = this.infowin;
   });
  }
  
  return obPlacemark;
 }

Метод BX_GMapAddPlacemark выводится в PHP коде шаблона компонента с массивом параметров каждой метки (arPlacemark) передаваемой в настройках компонента map.google.view - MAP_DATA/PLACEMARKS (см. Google: настраиваемая карта). Далее параметры метки обрабатываются в коде скрипта используя API Карт Google, ссылка на который есть в начале поста.

В моем случае понадобилось устанавливать следующие свойства маркера из API:
  • icon - собственно изображение маркера. Имеет свой размер (size), начало координат изображения (origin), якорь - базовая точка изображения которая которая встанет на координаты маркера (anchor).
  • shape - область нажатия маркера по которой будет открываться описание. Это полигон со своими координатами относительно изображения маркера. Пример использования маркера в виде флага можно посмотреть здесь.
  • title - Всплывающая подсказка.

Изучив API Гугл дорабатываем код исходя из требований:
(В примере за дефолтные значение принято что маркер имеет размеры 32x32)

window.BX_GMapAddPlacemark = function(arPlacemark, map_id)
 {
  var map = GLOBAL_arMapObjects[map_id];
  
  if (null == map)
   return false;

  if(!arPlacemark.LAT || !arPlacemark.LON)
   return false;
   
  var image = null;
  var shape = null;
  if(arPlacemark.ICON && BX.type.isNotEmptyString(arPlacemark.ICON.URL))
  {
   // Ожидаем появления в настройках маркера объекта ICON 
   // с описанием свойств нужных для создания маркера в API Google
   // Его будем задавать в настройках компонента
   // URL - Адрес изображения
   // Размер (объект google.maps.Size) создается из ожидаемых свойств WIDTH и HEIGHT
   // origin не особо важен думаю в большинстве случаев 0,0 (верхний левый угол)
   // anchor - якорь задается ожидаемыми свойствами ANCHOR_X и ANCHOR_Y
   image = {
    url: arPlacemark.ICON.URL,
    size: new google.maps.Size(
     arPlacemark.ICON.WIDTH?parseInt(arPlacemark.ICON.WIDTH):32, 
     arPlacemark.ICON.HEIGHT?parseInt(arPlacemark.ICON.HEIGHT):32
     ),  
    origin: new google.maps.Point(0,0),
    anchor: new google.maps.Point(
     arPlacemark.ICON.ANCHOR_X?parseInt(arPlacemark.ICON.ANCHOR_X):16, 
     arPlacemark.ICON.ANCHOR_Y?parseInt(arPlacemark.ICON.ANCHOR_Y):32
     )
   };
   
   // Координаты кликабельной области ожидаем в массиве
   // превращаем в нужный полигон (shape)
   if(arPlacemark.ICON.TOUCH_AREA)
   {
    for (var i in arPlacemark.ICON.TOUCH_AREA) {
     arPlacemark.ICON.TOUCH_AREA[i] = parseInt(arPlacemark.ICON.TOUCH_AREA[i], 10);
    }
    
    shape = {
     coord: arPlacemark.ICON.TOUCH_AREA,
     type: 'poly'
    };
   }
  }
  
  // Конструктор маркера теперь немного больше чем в изначальном варианте
  var obPlacemark = new google.maps.Marker({
   position: new google.maps.LatLng(arPlacemark.LAT, arPlacemark.LON),
   map: map,
   icon: image,
   shape: shape,
   title: arPlacemark.TITLE?arPlacemark.TITLE:null
  });
  
  if (BX.type.isNotEmptyString(arPlacemark.TEXT))
  {
   obPlacemark.infowin = new google.maps.InfoWindow({
    content: arPlacemark.TEXT.replace(/\n/g, '
')
   });
   
   google.maps.event.addListener(obPlacemark, 'click', function() {
    if (null != window['__bx_google_infowin_opened_' + map_id])
     window['__bx_google_infowin_opened_' + map_id].close();

    this.infowin.open(this.map, this);
    window['__bx_google_infowin_opened_' + map_id] = this.infowin;
   });
  }
  
  return obPlacemark;
 }

Теперь можно задать параметры компонента bitrix:map.google.view программно следующим образом:

// Массив со всеми настройками изображения маркера
// обработка которых была реализована ранее в коде скрипта шаблона битрикс компонента
$icon = array(
 'URL'=>SITE_TEMPLATE_PATH."/images/icons/marker.png", // Изображение размером 32x32
 'WIDTH'=> 32, 
 'HEIGHT'=>32, 
 'ANCHOR_X'=>16,
 'ANCHOR_Y'=>32,
 'TOUCH_AREA' => array(5,4,5,30,30,28,28,4),
);

// Массив маркеров
// Может создаваться к примеру из объектов инфоблока со свойствами координат
$placemarks = array(
 array('TEXT' => 'Текст маркера 1', 
  'TITLE' => 'Маркер 1', 
  'LAT' => '55.7415819', 
  'LON' => '37.6453949',
  'ICON' => $icon
 ),
 array('TEXT' => 'Текст маркера 2', 
  'TITLE' => 'Маркер 2', 
  'LAT' => '55.7415819', 
  'LON' => '37.6453949',
  'ICON' => $icon
 ),
 array('TEXT' => 'Текст маркера 3', 
  'TITLE' => 'Маркер 3', 
  'LAT' => '55.7415819', 
  'LON' => '37.6453949',
  'ICON' => $icon
 ),
);

// Итоговый массив данных для компонента map.google.view
$map_data = array( 
 'google_lat' => '37.632495', 
 'google_lon' => '55.749792', 
 'google_scale' => 11, 
 'PLACEMARKS' => $placemarks, 
);

$APPLICATION->IncludeComponent("bitrix:map.google.view", "extended", Array(
 "INIT_MAP_TYPE" => "ROADMAP", // Стартовый тип карты
 "MAP_DATA" => serialize($map_data), // Сериализуем подготовленные данные
 "MAP_WIDTH" => "748", // Ширина карты
 "MAP_HEIGHT" => "700", // Высота карты
 "CONTROLS" => array( // Элементы управления
  0 => "SMALL_ZOOM_CONTROL",
  1 => "TYPECONTROL",
  2 => "SCALELINE",
 ),
 "OPTIONS" => array( // Настройки
  0 => "ENABLE_DRAGGING",
  1 => "ENABLE_SCROLL_ZOOM",
  2 => "ENABLE_KEYBOARD"
 ),
 "MAP_ID" => "google_map_id", // Идентификатор карты
 ),
 false
);

Как я уже писал подобным образом в компоненте map.google.view можно реализовать и остальные возможности API Google карт по необходимости.

Комментариев нет:

Отправить комментарий