From c85d2782e2748fda8b5f7b49344cf49575115602 Mon Sep 17 00:00:00 2001 From: harlan Date: Wed, 4 Sep 2024 02:39:57 +1000 Subject: [PATCH] feat(googleMaps): unified styling of static image and map Fixes #202 --- docs/content/scripts/content/google-maps.md | 17 +++++++ .../third-parties/google-maps/styled.vue | 45 +++++++++++++++++++ src/runtime/components/ScriptGoogleMaps.vue | 26 +++++++++-- 3 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 playground/pages/third-parties/google-maps/styled.vue diff --git a/docs/content/scripts/content/google-maps.md b/docs/content/scripts/content/google-maps.md index d0ec0443..46ad4a85 100644 --- a/docs/content/scripts/content/google-maps.md +++ b/docs/content/scripts/content/google-maps.md @@ -248,6 +248,23 @@ If you want to load the Google Maps immediately, you can use the `trigger` prop. ``` +#### Map Styling + +You can style the map by using the `mapOptions.styles` prop. You can find pre-made styles on [Snazzy Maps](https://snazzymaps.com/). + +This will automatically work for both the static map placeholder and the interactive map. + +```vue + + +``` + ### Component API See the [Facade Component API](/docs/guides/facade-components#facade-components-api) for full props, events, and slots. diff --git a/playground/pages/third-parties/google-maps/styled.vue b/playground/pages/third-parties/google-maps/styled.vue new file mode 100644 index 00000000..062a009f --- /dev/null +++ b/playground/pages/third-parties/google-maps/styled.vue @@ -0,0 +1,45 @@ + + + + + diff --git a/src/runtime/components/ScriptGoogleMaps.vue b/src/runtime/components/ScriptGoogleMaps.vue index 08aba57d..b307162b 100644 --- a/src/runtime/components/ScriptGoogleMaps.vue +++ b/src/runtime/components/ScriptGoogleMaps.vue @@ -89,7 +89,6 @@ const props = withDefaults(defineProps<{ trigger: ['mouseenter', 'mouseover', 'mousedown'], width: 640, height: 400, - centerMarker: true, }) const emits = defineEmits<{ @@ -124,7 +123,7 @@ const options = computed(() => { return defu({ center: centerOverride.value }, props.mapOptions, { center: props.center, zoom: 15, - mapId: 'map', + mapId: props.mapOptions?.styles ? undefined : 'map', }) }) const ready = ref(false) @@ -292,7 +291,11 @@ onMounted(() => { center = await resolveQueryToLatLang(center as string) } map.value!.setCenter(center as google.maps.LatLng) - if (props.centerMarker) { + if (typeof props.centerMarker === 'undefined' || props.centerMarker) { + if (options.value.mapId) { + // not allowed to use advanced markers with styles + return + } if (prev[0]) { const prevCenterHash = hash({ position: prev[0] }) // @ts-expect-error broken upstream type @@ -335,6 +338,22 @@ if (import.meta.server) { }) } +function transformMapStyles(styles: google.maps.MapTypeStyle[]) { + return styles.map((style) => { + const feature = style.featureType ? `feature:${style.featureType}` : '' + const element = style.elementType ? `element:${style.elementType}` : '' + const rules = (style.stylers || []).map((styler) => { + return Object.entries(styler).map(([key, value]) => { + if (key === 'color' && typeof value === 'string') { + value = value.replace('#', '0x') + } + return `${key}:${value}` + }).join('|') + }).filter(Boolean).join('|') + return [feature, element, rules].filter(Boolean).join('|') + }).filter(Boolean) +} + const placeholder = computed(() => { let center = options.value.center if (center && typeof center === 'object') { @@ -349,6 +368,7 @@ const placeholder = computed(() => { size: `${props.width}x${props.height}`, key: apiKey, scale: 2, // we assume a high DPI to avoid hydration issues + style: props.mapOptions?.styles ? transformMapStyles(props.mapOptions.styles) : undefined, markers: [ ...(props.markers || []), center,