内容
在您的 Nuxt 应用程序中显示性能优化的谷歌地图。

谷歌地图 允许您将地图嵌入到您的网站中,并使用您的内容进行自定义。

Nuxt 脚本提供了一个 useScriptGoogleMaps 可组合组件和一个无头 ScriptGoogleMaps 组件来与谷歌地图交互。

ScriptGoogleMaps

The ScriptGoogleMaps 组件是 useScriptGoogleMaps 可组合组件的包装器。它提供了一种简单的方法,可以将谷歌地图嵌入到您的 Nuxt 应用程序中。

它通过利用 元素事件触发器 进行了性能优化,只在特定元素事件发生时加载谷歌地图。

在加载谷歌地图之前,它使用 静态地图 API 显示一个占位符。

默认情况下,它将在 mouseovermouseclick 事件上加载。

计费和权限

您需要一个具有访问 地图 JavaScript API 权限的 API 密钥。可选地,您可以向 静态地图 API(在延迟加载时使用占位符地图时需要)和 位置 API(在使用查询(例如“纽约”)进行搜索时需要)提供权限。

显示交互式 JS 地图需要地图 JavaScript API,这是一个付费服务。如果用户与地图交互,将产生以下费用

  • 地图 JavaScript API 每 1000 次加载收取 7 美元(使用谷歌地图的默认值)
  • 静态地图 API 每 1000 次加载收取 2 美元 - 仅在您不提供 placeholder 插槽时使用。
  • 地理编码 API 每 1000 次加载收取 5 美元 - 仅在您不提供 google.maps.LatLng 对象(而不是 center 属性的查询字符串)时使用。

但是,如果用户从未与地图交互,则仅会收取静态地图 API 使用费(每 1000 次加载 2 美元),假设您正在使用它。

计费将在 未来的更新 中优化。

如果您想避免这些费用并且可以接受交互性较低的地图,则应该考虑使用 Iframe 嵌入

演示

Google Maps Static Map

静态图像:悬停以加载交互式

将鼠标悬停在地图上将触发谷歌地图脚本加载并初始化地图。

属性

The ScriptGoogleMaps 组件接受以下属性。

您必须提供一个 center 属性才能使地图正确加载,或者您应该提供 mapOptions 并在其中配置 center 选项。

地图

  • center: 地图的中心位置。您可以提供一个包含位置的字符串,或使用 { lat: 0, lng: 0 } 对象。
  • apiKey: 谷歌地图 API 密钥。必须具有访问静态地图 API 的权限。您也可以选择使用 public.scripts.googleMaps.apiKey 密钥将其作为运行时配置提供。
  • centerMarker: 是否在中心位置显示标记。默认为 true
  • mapOptions: 地图的选项。请参阅 地图选项

占位符

您可以使用以下属性自定义占位符图像,或者您可以使用 #placeholder 插槽自定义占位符图像。

  • placeholderOptions: 自定义占位符图像属性。请参阅 静态地图 API
  • placeholderAttrs: 自定义占位符图像属性。

大小

如果您想渲染一个大于 640x640 的地图,您应该提供自己的占位符,因为 静态地图 API 不支持渲染大于此尺寸的地图。

  • width: 地图的宽度。默认为 640
  • height: 地图的高度。默认为 400

优化

  • trigger: 加载谷歌地图的触发事件。默认为 mouseover。请参阅 元素事件触发器 以了解更多信息。
  • aboveTheFold: 为屏幕上可见内容优化占位符图像。默认为 false

标记

您可以通过提供一个 MarkerOptions 数组来向静态地图和交互式地图添加标记。请参阅 标记选项

  • markers: 要在地图上显示的标记数组。

有关更多信息,请参阅 标记 示例。

指南

立即加载占位符

谷歌地图占位符图像默认情况下是延迟加载的。如果您地图在屏幕上可见内容区域,则应该更改此行为,或者考虑使用 #placeholder 插槽自定义占位符图像。

<ScriptGoogleMaps above-the-fold />

高级标记控制

如果您需要对地图上的标记进行更多控制,可以使用公开的 createAdvancedMapMarker 函数,该函数将返回标记实例。

<script lang="ts" setup>
const googleMapsRef = ref()
onMounted(() => {
  const marker = googleMapsRef.value.createAdvancedMapMarker({
    position: { }
  })
})
</script>
<template>
    <ScriptGoogleMaps ref="googleMapsRef" />
</template>

高级地图控制

该组件公开了所有内部 API,因此您可以根据需要自定义地图。

<script lang="ts" setup>
const googleMapsRef = ref()
onMounted(async () => {
  const api = googleMapsRef.value
  
  // Access internal APIs
  const googleMaps = api.googleMaps.value // google.maps api
  const mapInstance = api.map.value // google.maps.Map instance
  
  // Convert a query to lat/lng
  const query = await api.resolveQueryToLatLang('Space Needle, Seattle, WA') // { lat: 0, lng: 0 }
  
  // Import a Google Maps library
  const geometry = await api.importLibrary('geometry')
  const distance = new googleMaps.geometry.spherical.computeDistanceBetween(
    new googleMaps.LatLng(0, 0),
    new googleMaps.LatLng(0, 0)
  )
})
</script>
<template>
    <ScriptGoogleMaps ref="googleMapsRef" />
</template>

立即加载

如果您想立即加载谷歌地图,可以使用 trigger 属性。

<template>
<ScriptGoogleMaps trigger="immediate">
</ScriptGoogleMaps>
</template>

地图样式

您可以使用 mapOptions.styles 属性来设置地图的样式。您可以在 Snazzy 地图 上找到预制样式。

这将自动适用于静态地图占位符和交互式地图。

<script setup lang="ts">
const mapOptions = {
  styles: [{ elementType: 'labels', stylers: [{ visibility: 'off' }, { color: '#f49f53' }] }, { featureType: 'landscape', stylers: [{ color: '#f9ddc5' }, { lightness: -7 }] }, { featureType: 'road', stylers: [{ color: '#813033' }, { lightness: 43 }] }, { featureType: 'poi.business', stylers: [{ color: '#645c20' }, { lightness: 38 }] }, { featureType: 'water', stylers: [{ color: '#1994bf' }, { saturation: -69 }, { gamma: 0.99 }, { lightness: 43 }] }, { featureType: 'road.local', elementType: 'geometry.fill', stylers: [{ color: '#f19f53' }, { weight: 1.3 }, { visibility: 'on' }, { lightness: 16 }] }, { featureType: 'poi.business' }, { featureType: 'poi.park', stylers: [{ color: '#645c20' }, { lightness: 39 }] }, { featureType: 'poi.school', stylers: [{ color: '#a95521' }, { lightness: 35 }] }, {}, { featureType: 'poi.medical', elementType: 'geometry.fill', stylers: [{ color: '#813033' }, { lightness: 38 }, { visibility: 'off' }] },
}
</script>
<template>
<ScriptGoogleMaps :mapOptions="mapOptions" />
</template>

组件 API

请参阅 外观组件 API 以了解完整的属性、事件和插槽。

事件

The ScriptGoogleMaps 组件在谷歌地图加载时发出一个 ready 事件。

const emits = defineEmits<{
  ready: [map: google.maps.Map]
}>()

要订阅谷歌地图事件,可以使用 ready 事件。

<script setup lang="ts">
function handleReady({ map }) {
  map.addListener('center_changed', () => {
    console.log('Center changed', map.getCenter())
  })
}
</script>

<template>
  <ScriptGoogleMaps @ready="handleReady" />
</template>

插槽

该组件默认情况下提供最少的 UI,仅足以使其功能齐全且可访问。您可以通过多种插槽以您喜欢的方式自定义地图。

default

default 插槽用于显示始终可见的内容。

<template>
  <ScriptGoogleMaps>
    <div class="absolute top-0 left-0 right-0 p-5 bg-white text-black">
      <h1 class="text-xl font-bold">
        My Custom Map
      </h1>
    </div>
  </ScriptGoogleMaps>
</template>

awaitingLoad

该插槽用于在加载谷歌地图时显示内容。

<template>
  <ScriptGoogleMaps>
    <template #awaitingLoad>
      <div class="bg-blue-500 text-white p-5">
        Click to load the map!
      </div>
    </template>
  </ScriptGoogleMaps>
</template>

loading

该插槽用于在加载谷歌地图时显示内容。

注意:这默认情况下显示一个 ScriptLoadingIndicator 以实现可访问性和用户体验,通过提供一个插槽,您将覆盖此组件。确保您提供了一个加载指示器。

<template>
  <ScriptGoogleMaps>
    <template #loading>
      <div class="bg-blue-500 text-white p-5">
        Loading...
      </div>
    </template>
  </ScriptGoogleMaps>
</template>

placeholder

该插槽用于在加载谷歌地图之前显示占位符图像。默认情况下,这将显示谷歌地图静态 API 的地图图像。

通过提供您自己的占位符插槽,您将禁用默认的占位符图像的使用,并且不会收取静态地图 API 使用费。

<template>
  <ScriptGoogleMaps>
    <template #placeholder="{ placeholder }">
      <img :src="placeholder">
    </template>
  </ScriptGoogleMaps>
</template>

useScriptGoogleMaps

The useScriptGoogleMaps 可组合组件使您可以对谷歌地图 SDK 进行细粒度的控制。它提供了一种加载谷歌地图 SDK 并以编程方式与之交互的方法。

export function useScriptGoogleMaps<T extends GoogleMapsApi>(_options?: GoogleMapsInput) {}

请遵循 注册表脚本 指南以了解有关高级用法的更多信息。

GoogleMapsApi

export interface GoogleMapsApi {
  // @types/google.maps
  maps: typeof google.maps
}

示例

加载谷歌地图 SDK 并以编程方式与之交互。

<script setup lang="ts">
/// <reference types="google.maps" />
const { onLoaded } = useScriptGoogleMaps({
  apiKey: 'key'
})
const map = ref()
onMounted(() => {
  onLoaded(async (instance) => {
    const maps = await instance.maps as any as typeof google.maps // upstream google type issue
    new maps.Map(map.value, {
      center: { lat: -34.397, lng: 150.644 },
      zoom: 8
    })
    // Do something with the map
  })
})
</script>
<template>
    <div ref="map" />
</template>