DigitalConsumer.ISS/src/iss-components/google-map/google-map.vue
2023-11-15 16:25:27 -05:00

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>