Вывод стилизованной интерактивной карты Гугла

HTML: выводим блок карты и координаты

map.php
  <div id="mapsGoogle" data-lat="55.748238" data-lng="37.63897"></div>
 
  <?php foreach ($items as $item) { ?>
  <div><a class="js-point" href="#" data-id="<?=$item['id'];?>"><?=$item['name']; ?></a></div>
  <meta name="point"
    data-id="<?=$item['id'];?>"
    data-lat="<?php echo $item['lat'] ?>"
    data-lng="<?php echo $item['lng']; ?>"
    data-name='<?=htmlspecialchars($item['name'], ENT_QUOTES & ~ENT_COMPAT); ?>'
    data-address='<?=htmlspecialchars($item['description'], ENT_QUOTES & ~ENT_COMPAT); ?>'
    />
  <?php } ?>

CSS: стили

maps.stylus
  #mapsGoogle
    width: 100%
    height: 460px
    img
      max-width: none

JS: подключение карты

RequireJS-map.js
define([
  'jquery',
  'gmaps'
], function($, gmaps) {
 
  "use strict";
 
  var $map;
  var $centerMap;
  var $bounds;
  var contentPoint;
  var $markers = [];
  var pointCount = 0;
 
  var $dataPoints, dataPoints;
 
  // Google Maps API v3 Styled Maps JSON
  var $stylesMap = {'Custom':
    [{"featureType":"landscape.man_made","elementType":"geometry.fill","stylers":[{"saturation":100},{"lightness":19},{"gamma":2.65},{"hue":"#ff9100"}]},{"featureType":"road.arterial","elementType":"geometry.fill","stylers":[{"color":"#b39471"}]},{"featureType":"road.highway","elementType":"geometry.fill","stylers":[{"color":"#a65624"}]},{"featureType":"road.highway","elementType":"geometry.stroke","stylers":[{"visibility":"off"}]},{"featureType":"poi","elementType":"geometry.fill","stylers":[{"color":"#e2d0b8"}]},{"featureType":"landscape.natural","stylers":[{"hue":"#ffa200"},{"saturation":-56},{"lightness":-8}]},{"featureType":"water","stylers":[{"hue":"#0099ff"},{"saturation":-23}]},{"featureType":"administrative.locality","elementType":"labels.text.fill","stylers":[{"color":"#060406"}]},{"featureType":"administrative.land_parcel","elementType":"labels.text.fill","stylers":[{"color":"#865d4c"}]},{"featureType":"road.highway","elementType":"labels.text.fill","stylers":[{"color":"#fffffe"}]},{"featureType":"road.highway","elementType":"labels.text.stroke","stylers":[{"color":"#7c4022"},{"weight":2.9}]},{"featureType":"road.highway","elementType":"labels.icon","stylers":[{"hue":"#ff8800"}]},{"featureType":"transit.station","elementType":"labels.text.fill","stylers":[{"color":"#c94a1b"}]}]
  };
 
  var imageMarker = new gmaps.MarkerImage('/image/map-marker.png',
    new google.maps.Size(76, 80),
    new google.maps.Point(0,0),
    new google.maps.Point(38, 80));
 
  $(function() {
 
    $dataPoints = $('meta[name="point"]');
    dataPoints = {};
    if(!$dataPoints.length) return;
 
    initMapPoints();
    showMap();
    initInteractiveMap($('.js-point'));
 
  });
 
  function initInteractiveMap($control) {
    if(!$control.length) return;
    $control.on('click', function(e){
      e.preventDefault();
      var id = $(this).attr('data-id');
      showPoints(dataPoints[id]);
    });
  }
 
  function showPoints(point) {
    hidePoints();
 
    contentPoint = getPointContent(point.name, point.address);
    var $_marker = addMarker($map, point.lat, point.lng, $bounds, contentPoint, imageMarker);
    $markers.push($_marker);
 
    $map.fitBounds($bounds);
    $map.setZoom(11);
  }
 
   function hidePoints() {
    if (!$markers) return;
    for (var ind in $markers) {
      $markers[ind].setMap(null);
    }
    pointCount = 0;
    $markers = [];
    $bounds = new gmaps.LatLngBounds();
    $map.fitBounds($bounds);
  }
 
  function initMapPoints() {
    $dataPoints.each(function() {
      dataPoints[$(this).data('id')] = {
        lat: $(this).data('lat'),
        lng: $(this).data('lng'),
        name: $(this).data('name'),
        address: $(this).data('address')
        };
    });
  }
 
  function showMap() {
 
    var lat = $('#mapsGoogle').data('lat'); // Координата 1 берется из атрибута data-lat селектора selector
    var lng = $('#mapsGoogle').data('lng'); // Координата 2 берется из атрибута data-lng селектора selector
 
    //Опции для карты
    $centerMap = new gmaps.LatLng(lat, lng);
    var mapOptions = {
        zoom: 10,
        center: $centerMap,
        streetViewControl: false,
        overviewMapControl: false,
        scaleControl: false,
        mapTypeId: 'Custom',
        mapTypeControl: true,
        mapTypeControlOptions: {
          mapTypeIds: ['Custom']
        },
        zoomControl: true,
        zoomControlOptions: {
            style: gmaps.ZoomControlStyle.LARGE,
            position: gmaps.ControlPosition.LEFT_TOP
        },
        panControl: false,
        disableDefaultUI: true,
        scrollwheel: true
    };
 
    //Создаём карту и ставим точку
    $map = new gmaps.Map(document.getElementById("mapsGoogle"), mapOptions);
    var $styledMapType = new gmaps.StyledMapType($stylesMap['Custom'], {name: 'Custom'});
    $map.mapTypes.set('Custom', $styledMapType);
    $bounds = new gmaps.LatLngBounds();
 
    for (var pointId in dataPoints) {
      var dataPoint = dataPoints[pointId];
      if (dataPoint.lat && dataPoint.lng) {
        contentPoint = getPointContent(dataPoint.name, dataPoint.address);
        var $_marker = addMarker($map, dataPoint.lat, dataPoint.lng, $bounds, contentPoint, imageMarker);
        $markers.push($_marker);
        pointCount++;
      }
    }
 
    if (pointCount > 1) {
      $map.fitBounds($bounds);
    }
    else if (pointCount == 1) {
      $map.setCenter($bounds.getCenter());
      $map.setZoom(13);
    }
  }
 
  //Функция добавления точки (lat, lng) на карту mapId с расширением границ boundsId
  function addMarker(mapId, lat, lng, boundsId, contentPoint, imageMarker) {
    var $point = new gmaps.LatLng(lat, lng);
    var $marker = new gmaps.Marker({
                      map: mapId,
                      position: $point,
                      icon: imageMarker
    });
    var $mapInfoWindow = new gmaps.InfoWindow({content: ""});
    gmaps.event.addListener($marker, 'click', function() {
        $mapInfoWindow.setContent(contentPoint);
        $mapInfoWindow.open(mapId, this);
    });
    if (boundsId) boundsId.extend($point);
    return $marker;
  }
 
  function getPointContent(name, address) {
    return '<b>' + name + '</b><br />' + address;
  }
 
});

Фичи

Показывать только одно окно с адресом

Происходит закрытие прошлого информационного окна при щелчке на другой точке:

var prevMark;
 
// ...
 
gmaps.event.addListener($marker, 'click', function() {
    if(typeof prevMark != 'undefined') {
      prevMark.close();
    }
    mapInfoWindow.setContent(contentPoint);
    mapInfoWindow.open(mapId, this);
    prevMark = mapInfoWindow;
});

Маршруты: как добавить заправки