Pull to refresh

Google Maps — кастомизируй меня полностью

Reading time 7 min
Views 169K
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
Tags:
Hubs:
+34
Comments 15
Comments Comments 15

Articles