---
title: "Overlay View"
description: "title: 
description: 使用 Google 的 OverlayView 在地图的纬度和经度位置渲染 Vue 插槽内容。与 InfoWindow 不同，它将 HTML 结构和样式交由你自行处理。"
canonical_url: "https://nuxt-scripts.zhcndoc.com/scripts/google-maps/api/overlay-view"
last_updated: "2026-08-11T09:33:14.627Z"
---

---

title: <script-google-maps-overlay-view>

description: 使用 Google 的 [`OverlayView`](https://developers.google.com/maps/documentation/javascript/customoverlays) 在地图的纬度和经度位置渲染 Vue 插槽内容。与 `InfoWindow` 不同，它将 HTML 结构和样式交由你自行处理。

</script-google-maps-overlay-view>



<script-types filter="ScriptGoogleMapsOverlayView" script-key="google-maps">



</script-types>

## 标记锚定

嵌套在 `ScriptGoogleMapsMarker` 中时，叠加层会继承标记的位置，并在标记被拖动时跟随其移动。

```vue
<template>
  <ScriptGoogleMaps api-key="your-api-key">
    <ScriptGoogleMapsMarker
      :position="{ lat: -34.397, lng: 150.644 }"
      :options="{ gmpDraggable: true }"
    >
      <ScriptGoogleMapsOverlayView
        anchor="bottom-center"
        :offset="{ x: 0, y: -50 }"
      >
        <div class="custom-tooltip">
          自定义 Vue 内容
        </div>
      </ScriptGoogleMapsOverlayView>
    </ScriptGoogleMapsMarker>
  </ScriptGoogleMaps>
</template>
```

## 受控与非受控开启状态

该遮罩层支持两种开启状态模式：非受控（组件管理）和受控（通过 `v-model:open` 由父级管理）。

**非受控。** 组件拥有自己的开启状态。遮罩层默认打开；传入 `:default-open="false"` 可在开始时关闭。当不需要响应父级的状态变化时，这是最简单的模式。

```vue
<template>
  <!-- 挂载时立即打开（默认） -->
  <ScriptGoogleMapsOverlayView :position="{ lat: -34.397, lng: 150.644 }">
    <div>始终可见的标签</div>
  </ScriptGoogleMapsOverlayView>

  <!-- 保持关闭；需要切换时使用 v-model:open -->
  <ScriptGoogleMapsOverlayView
    :position="{ lat: -34.397, lng: 150.644 }"
    :default-open="false"
  >
    <div>初始隐藏</div>
  </ScriptGoogleMapsOverlayView>
</template>
```

**受控。** 将 `v-model:open` 绑定到父级的 ref。状态由父级管理，遮罩层反映该状态。当某些内部行为改变状态时（例如标记聚合的自动隐藏行为），遮罩层会更新绑定的 ref。

```vue
<script setup lang="ts">
const open = ref(true)
</script>

<template>
  <ScriptGoogleMapsOverlayView v-model:open="open" :position="{ lat: -34.397, lng: 150.644 }">
    <div>由父级控制</div>
  </ScriptGoogleMapsOverlayView>
</template>
```

当绑定 `v-model:open` 时，`defaultOpen` 不起作用；应直接向绑定的引用传递初始值。

以 `defaultOpen: false` 开始的非受控遮罩层没有公开方法可供之后打开。对于任何需要切换开启状态的遮罩层，请绑定 `v-model:open`。

## 点击标记时显示弹窗

使用 `v-model:open` 可以保持遮罩层挂载，通过 CSS 切换可见性。这避免了重新挂载的开销并保留内部状态。

```vue
<script setup lang="ts">
const open = ref(false)
</script>

<template>
  <ScriptGoogleMaps api-key="your-api-key">
    <ScriptGoogleMapsMarker
      :position="{ lat: -34.397, lng: 150.644 }"
      @click="open = !open"
    >
      <ScriptGoogleMapsOverlayView
        v-model:open="open"
        anchor="bottom-center"
        :offset="{ x: 0, y: -50 }"
      >
        <div class="custom-popup">
          <button @click.stop="open = false">
            ×
          </button>
          <p>此处可放置任何 Vue 内容</p>
        </div>
      </ScriptGoogleMapsOverlayView>
    </ScriptGoogleMapsMarker>
  </ScriptGoogleMaps>
</template>
```

对于可以接受重新挂载的简单场景，也可以使用 `v-if`：

```vue
<ScriptGoogleMapsMarker
  :position="{ lat: -34.397, lng: 150.644 }"
  @click="open = true"
>
  <ScriptGoogleMapsOverlayView v-if="open">
    <MyPopup @close="open = false" />
  </ScriptGoogleMapsOverlayView>
</ScriptGoogleMapsMarker>
```

## 持久标签

```vue
<template>
  <ScriptGoogleMaps api-key="你的 API 密钥">
    <ScriptGoogleMapsOverlayView
      :position="{ lat: -34.397, lng: 150.644 }"
      anchor="center"
      :block-map-interaction="false"
    >
      <span class="bg-white px-1.5 py-0.5 rounded">
        标签文本
      </span>
    </ScriptGoogleMapsOverlayView>
  </ScriptGoogleMaps>
</template>
```

## 位置格式

`position` 属性接受纯 `LatLngLiteral`（`{ lat, lng }`）或 `google.maps.LatLng` 实例，因此你可以直接传递地图 API 的值而无需先进行转换。

```vue
<script setup lang="ts">
const mapRef = ref()

async function showSydney() {
  // 通过地图 API 将查询解析为 LatLng 格式的值
  const sydney = await mapRef.value?.resolveQueryToLatLng('Sydney, Australia')
  // 直接传递，兼容两种格式
  position.value = sydney
}

const position = ref()
</script>

<template>
  <ScriptGoogleMaps ref="mapRef" api-key="your-api-key">
    <ScriptGoogleMapsOverlayView v-if="position" :position="position">
      <div>已解析的位置</div>
    </ScriptGoogleMapsOverlayView>
  </ScriptGoogleMaps>
</template>
```

## 地图平移

当一个已经打开的覆盖层首次附加到地图时，它会以 40px 的边距平移到视野内。将已挂载的覆盖层从关闭切换为打开时，目前不会再次执行平移步骤。

要自定义边距或禁用平移：

```vue
<!-- 自定义边距 -->
<ScriptGoogleMapsOverlayView :pan-on-open="60">
  ...
</ScriptGoogleMapsOverlayView>

<!-- 禁用平移 -->
<ScriptGoogleMapsOverlayView :pan-on-open="false">
  ...
</ScriptGoogleMapsOverlayView>
```

## 集群感知

当在 `ScriptGoogleMapsMarkerClusterer` 内部使用时，当其父标记在缩小视图时加入集群，遮罩层视图会自动隐藏。这可以防止孤立的遮罩层漂浮在集群图标上方。

当其标记被集群时，遮罩层会将 `v-model:open` 更新为 `false`。用户在放大回来后需要重新打开遮罩层（例如再次点击标记）。

要禁用此行为：

```vue
<ScriptGoogleMapsMarkerClusterer>
  <ScriptGoogleMapsMarker :position="markerPosition">
    <ScriptGoogleMapsOverlayView :hide-when-clustered="false">
      ...
    </ScriptGoogleMapsOverlayView>
  </ScriptGoogleMapsMarker>
</ScriptGoogleMapsMarkerClusterer>
```

## 打开状态动画

遮罩层在可见时会在其内容包装器上设置 `data-state="open"`。向组件传递一个 class，以定位该包装器并为其设置进入动画：

```vue
<ScriptGoogleMapsOverlayView v-model:open="open" class="popup">
  <div>
    动画弹窗
  </div>
</ScriptGoogleMapsOverlayView>

<style>
.popup[data-state="open"] {
  animation: fadeIn 200ms ease-out;
}
@keyframes fadeIn {
  from { opacity: 0; transform: scale(0.95); }
  to { opacity: 1; transform: scale(1); }
}
</style>
```

关闭时会立即将锚点设置为 `visibility: hidden`；组件不会等待 `transitionend` 或 `animationend`，因此 CSS 退出动画不会显示。模板 ref 会公开 `dataState`，供需要获取当前状态的代码使用，但它不是插槽 prop。

<callout>

`blockMapInteraction` 属性（默认为 `true`）会调用 `google.maps.OverlayView.preventMapHitsAndGesturesFrom()`，以阻止点击、轻触和拖动事件从遮罩层传播到地图。对于标签等非交互式遮罩层，请将其设置为 `false`。

</callout>
