Skip to content

Commit

Permalink
feat!: allow loading api script externally
Browse files Browse the repository at this point in the history
  • Loading branch information
HusamElbashir committed May 28, 2022
1 parent d7d2d3d commit 2a55b60
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 31 deletions.
70 changes: 42 additions & 28 deletions src/components/GoogleMap.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
<script lang="ts">
import { defineComponent, PropType, ref, onMounted, onBeforeUnmount, watch, toRef, provide, markRaw } from "vue";
import { mapSymbol, apiSymbol, loaderInstance, mapTilesLoadedSymbol, customMarkerClassSymbol } from "../shared/index";
import { mapSymbol, apiSymbol, mapTilesLoadedSymbol, customMarkerClassSymbol } from "../shared/index";
import { Loader } from "@googlemaps/js-api-loader";
import { createCustomMarkerClass } from "../utils";
import { IControlPosition } from "../@types/index";
let loaderInstance: Loader | undefined;
const mapEvents = [
"bounds_changed",
"center_changed",
Expand All @@ -29,6 +31,9 @@ const mapEvents = [
export default defineComponent({
props: {
apiPromise: {
type: Promise as PropType<Promise<typeof google>>,
},
apiKey: {
type: String,
default: "",
Expand Down Expand Up @@ -277,47 +282,56 @@ export default defineComponent({
const loadMapsAPI = () => {
try {
const { apiKey, region, version, language, libraries } = props;
loaderInstance.value = new Loader({ apiKey, region, version, language, libraries });
loaderInstance = new Loader({ apiKey, region, version, language, libraries });
} catch (err) {
// Loader instantiated again with different options, which isn't allowed by js-api-loader
console.error(err);
}
};
onMounted(() => {
loadMapsAPI();
const setupMap = (_google: typeof google) => {
api.value = markRaw(_google.maps);
map.value = markRaw(new _google.maps.Map(mapRef.value as HTMLElement, resolveOptions()));
const CustomMarker = createCustomMarkerClass(api.value);
api.value[customMarkerClassSymbol] = CustomMarker;
mapEvents.forEach((event) => {
map.value?.addListener(event, (e: unknown) => emit(event, e));
});
(loaderInstance.value as Loader).load().then(() => {
api.value = markRaw(google.maps);
map.value = markRaw(new google.maps.Map(mapRef.value as HTMLElement, resolveOptions()));
const CustomMarker = createCustomMarkerClass(api.value);
api.value[customMarkerClassSymbol] = CustomMarker;
ready.value = true;
mapEvents.forEach((event) => {
map.value?.addListener(event, (e: unknown) => emit(event, e));
});
const otherPropsAsRefs = (Object.keys(props) as (keyof typeof props)[])
.filter(
(key) =>
!["apiPromise", "apiKey", "version", "libraries", "region", "language", "center", "zoom"].includes(key)
)
.map((key) => toRef(props, key));
ready.value = true;
watch(
[() => props.center, () => props.zoom, ...otherPropsAsRefs] as const,
([center, zoom], [oldCenter, oldZoom]) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { center: _, zoom: __, ...otherOptions } = resolveOptions();
const otherPropsAsRefs = (Object.keys(props) as (keyof typeof props)[])
.filter((key) => !["center", "zoom"].includes(key))
.map((key) => toRef(props, key));
map.value?.setOptions(otherOptions);
watch(
[() => props.center, () => props.zoom, ...otherPropsAsRefs] as const,
([center, zoom], [oldCenter, oldZoom]) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { center: _, zoom: __, ...otherOptions } = resolveOptions();
if (zoom !== undefined && zoom !== oldZoom) map.value?.setZoom(zoom);
map.value?.setOptions(otherOptions);
const centerHasChanged = !oldCenter || center.lng !== oldCenter.lng || center.lat !== oldCenter.lat;
if (center && centerHasChanged) map.value?.panTo(center);
}
);
};
if (zoom !== undefined && zoom !== oldZoom) map.value?.setZoom(zoom);
onMounted(() => {
if (props.apiPromise && props.apiPromise instanceof Promise) {
props.apiPromise.then(setupMap);
} else {
loadMapsAPI();
const centerHasChanged = !oldCenter || center.lng !== oldCenter.lng || center.lat !== oldCenter.lat;
if (center && centerHasChanged) map.value?.panTo(center);
}
);
});
(loaderInstance as Loader).load().then(setupMap);
}
});
onBeforeUnmount(() => {
Expand Down
4 changes: 1 addition & 3 deletions src/shared/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { Loader } from "@googlemaps/js-api-loader";
import type { MarkerClusterer } from "@googlemaps/markerclusterer";
import { InjectionKey, ref, Ref } from "vue";
import { InjectionKey, Ref } from "vue";

export const mapSymbol: InjectionKey<Ref<google.maps.Map>> = Symbol("map");
export const apiSymbol: InjectionKey<Ref<typeof google.maps>> = Symbol("api");
Expand All @@ -12,7 +11,6 @@ export const customMarkerClassSymbol = Symbol("CustomMarker") as unknown as "Cus
* was fully loaded (including its tiles) to decide their behavior
*/
export const mapTilesLoadedSymbol: InjectionKey<Ref<boolean>> = Symbol("mapTilesLoaded");
export const loaderInstance = ref<Loader | null>(null);

export const polylineEvents = [
"click",
Expand Down

0 comments on commit 2a55b60

Please sign in to comment.