Поп-ап на картах гугл, объект google.maps.InfoWindow, привлекателен возможностью вставки в него собственного HTML контента. Но кастомизация внешнего вида ограничена. По сути вы можете применить стили только к внутреннему содержимому, прописывая стили для контейнера .gm-style-iw.
Разработчики прибегают к разным уловкам, чтобы изменить внешний вид рамки информационного окна, элемента закрытия и посягают даже на внешний вид треугольной стрелки внизу.
Вот что мы имеем по-дефолту от Гугл.
На следующем слайде выделен прямоугольник, стили которого мы контролируем.
Крестик для закрытия окна хоть визуально и расположен внутри области, на самом деле не является частью контента выделенного контейнера.
Пользуясь одними только стилями, рамку основного окна можно перекрыть с помощью отрицательных значений margin. Остаётся проблема с треугольной стрелкой, которую кастомизировать какими то красивыми способами уже не получится.
Потому вместо InfoWindow попробуем запрограммировать собственное кастомное наложение.
Если хотите разобраться во всем самостоятельно, то начните с этого раздела помощи Google.
Собственное наложение для карты Гугл.
Нам не хватает класса в контейнере, который изображает InfoWindow. Добавив его, мы сможем применить нужные стили.
И давайте также покажем треугольничек стрелки окна, например, не внизу, а справа от окна.
Меня устраивает белый цвет заднего фона, но поменяв стили, я могу задать и другой цвет для всего контейнера:
Кастомный OverlayView
Я взял за начальный вариант, тот код который предлагает Гугл в своём туториале (см. ссылку выше). Мне нужно было передать следующие данные в мой Overlay:
- content — HTML код для содержимого окна
- map — ссылка на объект карты google.maps.Map
- point — координаты, к которым привязан Overlay — google.maps.LatLng
- width — ширина окна в пикселях.
Код кастомного InfoWindow
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
// берем за базу прототип google.maps.OverlayView INFWOverlay.prototype = new google.maps.OverlayView(); /** * Custom Infoview constructor */ function INFWOverlay(content, map, point, width) { // Инициализация this.width_ = width; this.point_ = point; this.content_ = content; this.map_ = map; // переменная для хранения DOM контейнера this.div_ = null; // подключим overlay к карте this.setMap(map); } /** * Операции при добавлении overlay на карту */ INFWOverlay.prototype.onAdd = function() { var CIW = this; var div = document.createElement('div'); div.style.border = 'none'; div.style.borderWidth = '0px'; div.style.position = 'absolute'; // здесь я задал нужный мне класс, для которого буду // затем создавать каскадные стили div.classList.add('customInfoWindow'); // добавим HTML контент div.innerHTML = CIW.content_; // займемся созданием кнопки Close (крестик в углу) var divClose = document.createElement('div'); divClose.classList.add('close'); divClose.addEventListener('click', function (e) { CIW.toggle(); }); // добавим крестик в окно div.appendChild(divClose); CIW.div_ = div; // добавим элемент в набор pane overlayimage нашей карты var panes = CIW.getPanes(); panes.overlayImage.appendChild(CIW.div_); }; /** * эта функция позволяет позиционировать окно на карте * во время прорисовки */ INFWOverlay.prototype.draw = function() { // получим доступ к т.н. проекции окна var overlayProjection = this.getProjection(); // проекция позволяет нам вычислить позицию окна // относительно документа, переводя гео координаты // в x,y канваса на экране var sw = overlayProjection.fromLatLngToDivPixel(this.point_); // т.к я решил показывать треугольник стрелки справа, то окно я // сдвину вправо и немного вверх от точки позиционирования // Треугольник стрелки имеет размеры в моём случае - 5x10 точек. var div = this.div_; div.style.left = (sw.x - this.width_ - 5) + 'px'; div.style.top = (sw.y - 50) + 'px'; div.style.width = (this.width_) + 'px'; div.style.height = 'auto'; }; /** * Далее идут функции реализующие удаление, скрытие окна * они не требуют подробного описания * и не отличаются от примера в руководстве от Гугл. */ INFWOverlay.prototype.onRemove = function() { this.div_.parentNode.removeChild(this.div_); }; // Set the visibility to 'hidden' or 'visible'. INFWOverlay.prototype.hide = function() { if (this.div_) { // The visibility property must be a string enclosed in quotes. this.div_.style.visibility = 'hidden'; } }; INFWOverlay.prototype.show = function() { if (this.div_) { this.div_.style.visibility = 'visible'; } }; INFWOverlay.prototype.toggle = function() { if (this.div_) { if (this.div_.style.visibility === 'hidden') { this.show(); } else { this.hide(); } } }; // Detach the map from the DOM via toggleDOM(). // Note that if we later reattach the map, it will be visible again, // because the containing <div> is recreated in the overlay's onAdd() method. INFWOverlay.prototype.toggleDOM = function() { if (this.getMap()) { // Note: setMap(null) calls OverlayView.onRemove() this.setMap(null); } else { this.setMap(this.map_); } }; |
Использование кастомного InfoWindow
Сейчас мы воспользуемся всей этой писаниной сверху. Нам понадобится какая то точка на карте и объект карты.
Я предполагаю, что в HTML присутствует такой контейнер для показа карты:
1 |
<div style="width: 500px; height: 450px" id="myMap"></div> |
Тогда в коде инициализации карты, я напишу что то вроде:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<script> // какие то координаты var myPos = new google.maps.LatLng(55.45, 45.77); // настройки карты var myOptions = { zoom: 7, center: myPos, mapTypeId: google.maps.MapTypeId.ROADMAP } // объект карты var map = new google.maps.Map(document.getElementById('#myMap'), myOptions); // кастомный Overlay var overlay = new INFWOverlay("<span>Тут ваш HTML код для создания описания</span>", map, // карта myPos, // точка на карте 200 // ширина окна); // покажем окно overlay.show(); </script> |
Это, конечно, не всё. Нужен ещё код для CSS, который наводит красоту.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
// Override google MAP API CSS .customInfoWindow { background-color: #fff; padding: 15px; box-sizing: border-box; box-shadow: 0 0 15px 0 rgba(50,50,50,0.5); } // треугольная стрелка // для генерации обычно использую онлайн конструктор .customInfoWindow:after { position: absolute; right: -5px; top: 45px; content: ""; width: 0; height: 0; border-style: solid; border-width: 5px 0 5px 5px; border-color: transparent transparent transparent #000; } // крестик .customInfoWindow .close { position: absolute; top: 15px; right: 15px; width: 10px; height: 10px; float: right; // вставьте вашу картинку для крестика :) background: url(close-google-popup.png) center center no-repeat; opacity: 1; } |
В результате всех этих манипуляций в HTML коде гугл будет появляться окно, которые вы сможете полностью кастомизировать.