93 lines
3 KiB
Vue
93 lines
3 KiB
Vue
<template>
|
|
<div>
|
|
<div id="map" />
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
name: 'google-map',
|
|
props: {
|
|
addresses: Array,
|
|
zipCode: String
|
|
},
|
|
data() {
|
|
return {
|
|
country: 'USA',
|
|
geocoder: null
|
|
};
|
|
},
|
|
computed: {
|
|
zipCodeAddress() {
|
|
return `${this.zipCode ?? ''} ${this.country}`;
|
|
}
|
|
},
|
|
watch: {
|
|
async addresses(newAddresses) {
|
|
this.createMapWithMarkersForAddresses(newAddresses);
|
|
}
|
|
},
|
|
methods: {
|
|
async getMap(center) {
|
|
const { Map } = await window.google.maps.importLibrary('maps');
|
|
return new Map(document.getElementById('map'), {
|
|
center,
|
|
mapId: 'map_id',
|
|
mapTypeControl: false
|
|
});
|
|
},
|
|
getBounds(locations) {
|
|
const bounds = new window.google.maps.LatLngBounds();
|
|
locations?.forEach((location) => bounds.extend(location));
|
|
return bounds;
|
|
},
|
|
async setGeocoder() {
|
|
if (this.geocoder == null) {
|
|
const { Geocoder } = await window.google.maps.importLibrary('geocoding');
|
|
this.geocoder = new Geocoder();
|
|
}
|
|
},
|
|
async addMarkersToMap(map, positions) {
|
|
const { AdvancedMarkerElement } = await window.google.maps.importLibrary('marker');
|
|
positions?.forEach((position) => new AdvancedMarkerElement({ map, position }));
|
|
},
|
|
async getLocationsFromAddresses(addresses) {
|
|
await this.setGeocoder();
|
|
|
|
const geocodeShopAddressPromises = addresses?.map((address) => this.geocoder.geocode({ address })) ?? [];
|
|
const geocodeShopAddressResults = await Promise.all(geocodeShopAddressPromises);
|
|
return geocodeShopAddressResults.map((result) =>
|
|
(result?.results?.length > 0
|
|
? result.results[0].geometry?.location
|
|
: null))
|
|
.filter((loc) => loc != null);
|
|
},
|
|
async getBoundsFromAddress(address) {
|
|
await this.setGeocoder();
|
|
const result = await this.geocoder.geocode({ address });
|
|
return result?.results?.length > 0
|
|
? result.results[0].geometry?.bounds
|
|
: null;
|
|
},
|
|
async createMapWithMarkersForAddresses(addresses) {
|
|
const shopPositions = await this.getLocationsFromAddresses(addresses);
|
|
const zipBounds = await this.getBoundsFromAddress(this.zipCodeAddress);
|
|
const map = await this.getMap(zipBounds.getCenter());
|
|
|
|
await this.addMarkersToMap(map, shopPositions);
|
|
|
|
const positionsToDisplay = shopPositions.concat(zipBounds.getNorthEast(), zipBounds.getSouthWest());
|
|
const bounds = this.getBounds(positionsToDisplay);
|
|
map.fitBounds(bounds);
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
#map {
|
|
height: 250px;
|
|
width: 100%;
|
|
}
|
|
</style>
|