image

> Демо: ссылка
> Исходники: ссылка

В первый раз столкнувшись с внедрением и кастомизацией Google Maps, я не нашел единой статьи, рассматривающей все необходимые моменты — информацию пришлось искать по крупицам, а что-то выдумывать самому. После чего и было решено написать эту статью, чтобы люди, ранее не работавшие со стилизацией Google Maps, но при этом ограниченные временными рамками (а может, и желанием) для полноценного изучения API, смогли быстро получить необходимую информацию и материалы. Тем более, что и те, кто обладает определенным опытом, смогут почерпнуть для себя из этой статьи какую-нибудь интересную фишку, к примеру — параллакс для элементов информационного окна.

В этой статье мы рассмотрим:

1. Внедрение Google Maps на сайт

  • Добавление через вставку iframe в разметку
  • Добавление через API

2. Кастомизация маркера

  • Инициализация маркера
  • Анимация маркера
  • Изображение маркера

3. Кастомизация информационного окна

  • Добавление информационного окна
  • Открытие информационного окна
  • Кастомизация элементов информационного окна
  • Параллакс-эффект для элементов в информационном окне

4. Кастомизация карты

  • Изменение цвета объектов карты
  • Кастомизация элементов управления
  • Маска для карты

1. Внедрение на сайт

Добавление через вставку iframe в разметку

Если у вас нет необходимости изменять маркер, делать кастомное информационное окно или еще каким-либо образом воздействовать на карту, для ее добавления достаточно сделать следующее:

  • Открыть Google Maps.
  • Найти интересующий объект (например, введя адрес в поиске, либо нажав на нужное название правой кнопкой мыши и выбрав пункт в контекстном меню «Что здесь?»)

    image

    после чего кликнуть на гамбургер:

    image

    Затем находим кнопку «Ссылка/код»:

    image

    Копируем код для вставки:

    image

    Осталось только вставить полученный код в разметку.

Добавление через API

Но если необходимо произвести какие-либо манипуляции, нам понадобится ключ. Если его нет рядом, можно получить тут: ссыль

Встраиваем его в адрес вместо YOUR_API_KEY:

<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"></script>

Если нужно вызывать коллбэк после загрузки api, после ключа надо будет дописать YOUR_API_KEY&callback=initMap с названием вашей функции. Подключаем скрипт на странице и создаем в разметке блок для будущей карты:

<div id="map"></div>

Теперь необходимо инициализировать карту:

function initMap() {
    var coordinates = {lat: 47.212325, lng: 38.933663},
    
        map = new google.maps.Map(document.getElementById('map'), {
            center: coordinates
        });
}

Координаты можно узнать при помощи опции «Что здесь», описанной выше.

Свойства, которые могут сразу понадобиться:

  • zoom: number — определяет первоначальный масштаб.
  • disableDefaultUI: boolean – убирает элементы управления.
  • scrollwheel: boolean — отключает масштабирование колесиком мыши (бывает полезно, если карта на всю ширину страницы и перебивает прокрутку вниз).

2. Кастомизация маркера

Инициализация маркера

Для начала добавим маркер:

function initMap() {
    var coordinates = {lat: 47.212325, lng: 38.933663},

        map = new google.maps.Map(document.getElementById('map'), {
            center: coordinates
        }),
    
        marker = new google.maps.Marker({
            position: coordinates,
            map: map
        });
}

position (обязательно) указывает начальное положение маркера. Если указать те же координаты, что и для карты, то маркер будет по центру экрана. Сместить маркер можно изменив значение координат, либо сменив положение самой карты относительно видимой области (родительского блока).
map (не обязательно) указывает карту, на которой помещается маркер.

Анимация маркера

Для маркера можно задать анимацию:

  • DROP – после загрузки карты маркер падает сверху.
  • BOUNCE – маркер подпрыгивает на месте.

function initMap() {
    var coordinates = {lat: 47.212325, lng: 38.933663},

        map = new google.maps.Map(document.getElementById('map'), {
            center: coordinates
        }),

        marker = new google.maps.Marker({
            position: coordinates,
            map: map,
            animation: google.maps.Animation.BOUNCE
        });
}

Анимацию можно задать при инициализации маркера, добавить или убрать, вызвав метод setAnimation().

Пример анимации маркера при закрытии информационного окна и прекращении при открытии:

google.maps.event.addListener(infowindow,'closeclick',function(){
    marker.setAnimation(google.maps.Animation.BOUNCE);
});

marker.addListener('click', function () {
    marker.setAnimation(null);
});

Изображение маркера

Изображение маркера можно изменить, задав адрес картинки для свойства icon.

image = 'images/marker.png',
marker = new google.maps.Marker({
    position: coordinates,
    map: map,
    icon: image
});

3. Кастомизация информационного окна

Добавление информационного окна

В кастомное информационное окно можно добавить любую разметку через свойство content:

function initMap() {
    var coordinates = {lat: 47.212325, lng: 38.933663},
        popupContent = '<p class="content">Что угодно</p>',
        markerImage = 'images/marker.png',

        map = new google.maps.Map(document.getElementById('map'), {
            center: {lat: 47.212325, lng: 38.933663}
        }),

        marker = new google.maps.Marker({
            position: coordinates,
            map: map,
            icon: markerImage
        }),

        infowindow = new google.maps.InfoWindow({
            content: popupContent
        });
}

Открытие информационного окна

Чтобы информационное окно было видно сразу, надо вызвать метод open():

infowindow.open(map, marker);

Также следует добавить вызов окна при клике на маркер (в противном случае мы не сможем открыть попап):

marker.addListener('click', function() {
    infowindow.open(map, marker);
});

Кастомизация элементов информационного окна

Информационное окно может быть как кастомное, так и стандартное. В кастомное мы можем добавить любые элементы и работать с ними, возможности ограничены лишь фантазией.

Основная проблема, с которой можно столкнуться при кастомизации любого из типов – края (белая область) вокруг контента и стрелочка. Эти элементы не поддаются css выборке.

image

Решить проблему можно при помощи псевдоэлементов для доступных блоков. Также, если по какой-либо причине нет возможности использовать лишний псевдоэлемет, рамочку можно убрать при помощи тени.

.gm-style-iw {
  background: $black;
  box-shadow: -14px 0px 0px $black, -14px 9px 0px $black, -14px -8px 0px $black, 15px -8px 0px $black, 15px 9px 0px $black;
}

Но обо всем по порядку:

.gm-style-iw — основной блок, в нем находится контент. На скриншоте, расположенном выше, этот блок имеет черный фон.
.poi-info-window — обертка для текста в стандартном информационном окне, находится внутри. .gm-style-iw
.gm-style-iw + div – крестик.

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

.gm-style-iw {
  overflow: visible !important;

  div {
    overflow: visible !important;
  }
}

Теперь для .gm-style-iw, или блоков внутри можно создать псевдоэлементы для перекрытия фона и стрелочки:

.gm-style-iw {
  // Фон
  &::before {
    content: '';
    width: calc(100% + 29px);
    height: calc(100% + 17px);
    @include absolute;
    @include center-align;
    background: $black;
  }
  
  // Стрелочка
  &::after {
    content: '';
    width: 0;
    height: 0;
    border: 22px solid transparent;
    border-top-color: $black;
    z-index: 4;
    @include absolute;
    top: auto;
    bottom: -53px;
    margin: auto;
  }
}

Получаем следующее:

image

Параллакс-эффект для элементов в информационном окне

Тут возникает небольшая проблема, связанная с тем, что объекты карты создаются динамически, и нельзя просто так взять и прикрепить к ним обработчик, а клонировать блок при помощи .clone(true) в контент информационного окна с переносом обработчиков нам не позволит API.

Как вариант, можно проверять наличие элемента и сохранять после появления:

var $parallaxImg  = null;
this.$body.mousemove(function(e) {
    if($parallaxImg) {
        ...
    } else if($(this.parallaxImg).length) {
        $parallaxImg = $(this.parallaxImg);
    }
}.bind(this));

Теперь просто добавим код, смещающий блок по горизонтали в зависимости от положения курсора:

var $parallaxImg  = null;

this.$body.mousemove(function(e) {
    if($parallaxImg) {
        var $el    = $(e.currentTarget),
            xPos   = e.pageX - (window.innerWidth / 2),
            mXPcnt = Math.round(xPos / $el.width() * 100),
            diffX  = $parallaxImg.width() - $el.width(),
            myX    = diffX * (mXPcnt / 1500);

        $parallaxImg.animate({left: myX}, 0);
    } else if($(this.parallaxImg).length) {
        $parallaxImg = $(this.parallaxImg);
    }
}.bind(this));

Если клик по динамическому элементу нужно обработать, просто ставим обработчик на обертку и ловим объект на всплытии:

$('.map').on('click', '.js-parallax-img', function() {
    ...
});

4. Кастомизация карты

Изменение цвета объектов карты

Для стилизации карты используется массив стилей, в котором указывается селектор и css-свойство, которое необходимо применить.

Пример настроек, окрашивающих воду в фиолетовый цвет:

var styles = [
        {
            "featureType": "water",
            "stylers": [
                {
                    "color": "#a73cff"
                }
            ]
        }
    ]

Применяем параметры:

map.setOptions({styles: styles});

Для настройки стилей проще всего использовать специализированный сервис, к примеру Google Maps APIs Styling Wizard. Для детальной настройки карты жмем «More options»:

image

Производим настройку:

image

Копируем полученный json:

image

Если массив стилей очень большой, его можно поместить в отдельный .json файл и применить стили после его загрузки:

$.getJSON("../json/map-style/map-style.json", function(data) {
    map.setOptions({styles: data});
});

В конечном итоге получаем вот такие настройки карты:

var coordinates = {lat: 47.212325, lng: 38.933663},
    popupContent = this.$popupContent.html(),
    markerImage = 'images/marker.png',
    zoom = 15,

    map = new google.maps.Map(document.getElementById('map'), {
        center: coordinates,
        zoom: zoom,
        disableDefaultUI: true
    }),

    infowindow = new google.maps.InfoWindow({
        content: popupContent
    }),

    marker = new google.maps.Marker({
        position: coordinates,
        map: map,
        icon: markerImage
    });

$.getJSON("../json/map-style/map-style_colored.json", function(data) {
    map.setOptions({styles: data});
});

google.maps.event.addListener(infowindow,'closeclick',function(){
    marker.setAnimation(google.maps.Animation.BOUNCE);
});

marker.addListener('click', function () {
    marker.setAnimation(null);
});

marker.addListener('click', function() {
    infowindow.open(map, marker);
});

infowindow.open(map, marker);

Кастомизация элементов управления

image

Кнопки «Карта» и «Спутник» находятся в блоке с классом .gm-style-mtc

image

Кнопки увеличения и уменьшения изображения в блоке с классом .gmnoprint

image

Кнопка режима просмотра улиц имеет класс .gm-svpc

image

Используя эти классы, можно сделать с элементами управления все, что душе угодно. В данном случае я скрыл элементы управления, но для примера изменил цвет:

.gm-style-mtc > div,
.gmnoprint > div,
.gm-svpc {
  background-color: #f63981 !important;
}

Маска для карты

Ну, и на закуску — очень простая вещь, но может для кого-нибудь окажется в новинку. По сути — просто блок на весь размер карты, либо являющийся картинкой, либо с фоновым изображением. Также есть свойство mask-image, но оно поддерживается не всеми браузерами.

Единственное, на что тут следует обратить внимание — css свойство pointer-events, которое на маске должно быть в значении none. Это позволит не учитывать этот блок в событиях мыши (проще говоря, кликать и скроллить сквозь этот блок).

image

На этом быстрый старт Google Maps окончен. Надеюсь, эта статья оказалась для вас полезной.

Исходники можно найти тут: GitHub
Поделиться с друзьями
-->

Комментарии (15)


  1. sleeply4cat
    26.03.2017 22:10
    +1

    (\


  1. kirillaristov
    26.03.2017 22:27
    +1

    https://www.google.ru/intl/ru/permissions/geoguidelines.html

    Обратите внимание, что нельзя сильно менять исходный вид сервисов. Запрещено удалять объекты на карте, размывать их, добавлять рельеф, обозначать природные явления и менять цвет интерфейса Google Карт и Google Планета Земля.


    1. forgotten
      27.03.2017 10:08
      +1

      И там же:

      Обязательно ли показывать данные об авторстве, добавленные на карту?

      Да. Если автоматически сгенерированная строка с указанием авторства Google или наших партнеров оказалась удалена или скрыта, ее необходимо добавить в другое место на странице (например, в подпись к изображению из Google Планета Земля). Текст должен быть разборчивым и находиться рядом с картой.

      https://www.google.ru/intl/ru/permissions/geoguidelines/attr-guide.html


  1. DEM_dwg
    27.03.2017 08:53
    +1

    Делаю нечто похожее, на основе гугл таблиц и яндекс карт.
    Объекты на карте формируются на основе запросов к гугл таблицам.
    Так же формируются таблицы, на основе запросов к гугл таблицам.
    Не помню уже почему использовал именно Яндекс карты, но у них довольно понятное и доступное АПИ, очень большая библиотека примеров. Да и визуально Яндекс карты мне больше нравятся.


  1. rednaxi
    27.03.2017 08:54
    +1

    Я думаю, важно еще упомянуть, что Javascript API гугл-карт это платный сервис, как и Static api.
    Бесплатны лишь первые 25000 загрузок карт в сутки, потом нужно платить по 0,5$ за каждую тысячу загрузок.


    В этом плане привлекательнее выглядят яндекс-карты, которые дают бесплатно пользоваться своим апи для размещения карт, и лимитируют только геокодер.


    1. TutmeeAgency
      27.03.2017 10:44

      Спасибо))


    1. nikitasius
      27.03.2017 10:47
      +1

      Бесплатны лишь первые 25000 загрузок карт в сутки

      В моем случае был лимит на 25к фотоснимов и эти 25к очень и очень мало, но у гугла отличное качество со спутника, что позволяет строить шикарные карты (скачал 20к фоток и склеил постер).


  1. hardtop
    27.03.2017 09:11
    +1

    Очень круто. Спасибо!


  1. NeuroZ
    27.03.2017 20:08
    +1

    Спасибо, шикарная статья! Очень помогла :)
    Пишите еще :)


  1. fridmayer
    27.03.2017 20:08
    +1

    А никто случаем не подскажет, почему могла пропасть Google-карта на сайте после установки SSL? То есть получается следующее — если заходить просто на http://some_site.ru, то карта есть, а если зайти через httpS://some_site.ru, то карта не отображается.


    1. NeuroZ
      28.03.2017 10:44
      +1

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


      1. fridmayer
        28.03.2017 14:49
        +1

        Благодарю, помогло. Счастье, оказывается, было так близко :)


  1. andech
    28.03.2017 17:19
    +1

    Может быть кто-нибудь знает, есть ли в API возможность использовать 3D вид планеты при отдалении карты, как это сделано у самого Google? Я не про Google Earth, т.е., чтобы это работало в браузере без плагинов.


    1. TutmeeAgency
      29.03.2017 10:23

      Тоже интересовался этим вопросом, но, перерыв пару-тройку страниц поисковой выдачи в гугле по нескольким запросам, оставил тщетные надежды на использование данного сервиса.


  1. Optimus_990
    29.03.2017 10:25
    +1

    Хорошее объяснение, особенно для того кто первый раз столкнулся с внедрением и кастомизацией Google Maps. Я уверен, что многим будет полезно.