'use strict'
import { MarkerClusterer } from '@googlemaps/markerclusterer'
import Events from '../_events'
import MarkerUI from './map.google.marker'
const GoogleMapsDriver = ((window) => {
class GoogleMapsDriver {
getName () {
return 'GoogleMapsDriver'
}
init (el, config = []) {
const ui = this
ui.el = el
ui.config = config
ui.markers = []
window[`init${ui.getName()}`] = () => {
ui.googleApiLoaded()
}
const script = document.createElement('script')
script.src = `https://maps.googleapis.com/maps/api/js?key=${
config.key
}&callback=init${ui.getName()}`
script.async = true
script.defer = true
document.head.appendChild(script)
}
googleApiLoaded () {
const ui = this
const el = ui.el
const config = ui.config
const mapDiv = el.querySelector('.mapAPI-map')
const zoom =
config.mapZoom && config.mapZoom !== '0'
? parseInt(config.mapZoom)
: 10
const center =
config.center && config.center !== ','
? {
lat: config.center[1],
lng: config.center[0],
}
: {
lat: 0,
lng: 0,
}
const style = config.style ? config.style : null
console.log(`${ui.getName()}: API is loaded`)
// init fontawesome icons
ui.MarkerUI = MarkerUI.init()
ui.map = new window.google.maps.Map(mapDiv, {
zoom,
center,
fullscreenControl: true,
styles: style,
})
ui.default_zoom = zoom
mapDiv.classList.add('mapboxgl-map')
ui.popup = new ui.MarkerUI({
map: ui.map,
align: ['center', 'top'],
divClass: 'mapboxgl-popup popup mapboxgl-popup-anchor-bottom d-none',
html:
'
',
})
ui.popup.setMap(ui.map)
ui.geocoder = new window.google.maps.Geocoder()
ui.cluster = new MarkerClusterer(ui.map, null, {
styles: [
{
width: 30,
height: 30,
className: 'mapboxgl-cluster',
},
],
})
el.dispatchEvent(new Event(Events.MAPAPILOADED))
}
addMarker (crds, config) {
const ui = this
const pos = {
lat: crds[1],
lng: crds[0],
}
const marker = new ui.MarkerUI({
position: pos,
map: ui.map,
align: ['center', 'top'],
html: ``,
onClick: () => {
const el = document.querySelector(`#Marker${config.id}`)
ui.showPopup(pos, config.content)
el.dispatchEvent(new Event(Events.MAPMARKERCLICK))
},
})
ui.markers.push(marker)
ui.cluster.addMarker(marker)
marker.setMap(ui.map);
return marker
}
showPopup (pos, content) {
const ui = this
const popup = ui.popup.getDiv()
if (ui.config.flyToMarker) {
ui.map.setCenter(pos) // panTo
if (!ui.config.noZoom) {
ui.map.setZoom(18)
}
}
// keep it hidden to render content
popup.style.opacity = '0'
popup.classList.remove('d-none')
popup.querySelector('.mapboxgl-popup-content .html').innerHTML = content
popup
.querySelector('.mapboxgl-popup-close-button')
.addEventListener('click', (e) => {
e.preventDefault()
ui.hidePopup()
})
// set position when content was rendered
ui.popup.setPosition(pos, ['center', 'top'])
// display popup
popup.style.opacity = '1'
popup.style['margin-top'] = '-1rem'
}
hidePopup () {
const ui = this
const popup = ui.popup.getDiv()
popup.classList.add('d-none')
if (!ui.config.noRestoreBounds || ui.config.flyToBounds) {
ui.restoreBounds()
}
ui.el.dispatchEvent(new Event(Events.MAPPOPUPCLOSE))
}
geocode (addr, callback) {
const ui = this
ui.geocoder.geocode(
{
address: addr,
},
(results, status) => {
if (status === 'OK') {
// results[0].geometry.location;
if (typeof callback === 'function') {
callback(results)
}
return results
} else {
console.error(
`${ui.getName()}: Geocode was not successful for the following reason: ${status}`
)
}
}
)
}
reverseGeocode (latLng, callback) {
const ui = this
ui.geocoder.geocode(
{
location: latlng,
},
(results, status) => {
if (status === 'OK') {
// results[0].formatted_address;
if (typeof callback === 'function') {
callback(results)
}
return results
} else {
console.error(
`${ui.getName()}: Reverse Geocoding was not successful for the following reason: ${status}`
)
}
}
)
}
addGeoJson (config) {
const ui = this
const geojson = JSON.parse(config.geojson)
// const firstMarker = geojson.features[0].geometry.coordinates
// Map.setCenter(firstMarker);
const bounds = new window.google.maps.LatLngBounds()
// add markers to map
geojson.features.forEach((marker) => {
const id = marker.id
const crds = marker.geometry.coordinates
const content = marker.properties.content
ui.addMarker(crds, {
id,
content,
icon: marker.icon,
flyToMarker: config.flyToMarker,
})
bounds.extend({
lat: parseFloat(crds[1]),
lng: parseFloat(crds[0]),
})
})
if (ui.markers.length > 1) {
ui.map.fitBounds(bounds, {
padding: 30,
}) // panToBounds
} else if (ui.markers[0]) {
ui.map.setCenter(ui.markers[0].getPosition())
}
ui.default_bounds = bounds
ui.default_zoom = ui.map.getZoom()
}
getMap () {
const ui = this
return ui.map
}
getPopup () {
const ui = this
return ui.popup
}
restoreBounds () {
const ui = this
if (ui.default_bounds && ui.markers.length > 1) {
ui.map.fitBounds(ui.default_bounds, {
padding: 30,
}) // panToBounds
} else {
if (ui.markers[0]) {
ui.map.setCenter(ui.markers[0].getPosition())
}
ui.restoreZoom()
}
}
restoreZoom () {
const ui = this
ui.map.setZoom(ui.default_zoom)
}
}
return GoogleMapsDriver
})(window)
export default GoogleMapsDriver