---
title: "MaplibreProjection"
description: "切换地图投影为球形地球（globe），支持按 zoom 插值在球体与平面间过渡。"
canonical_url: "https://maplibre.mhaibaraai.cn/docs/environment/projection"
---
# MaplibreProjection

> 切换地图投影为球形地球（globe），支持按 zoom 插值在球体与平面间过渡。

## 简介

`MaplibreProjection` 调用 `setProjection` 设置地图投影：`type` 缺省为 `'globe'`，也可传 `'mercator'` / `'vertical-perspective'` 或按 zoom 插值的表达式；`options` 透传完整投影规格，优先级高于 `type`。切换底图（`setStyle`）后自动重设，卸载时还原为组件接管前的投影。

> [!NOTE]
> 
> 投影有三种来源：样式 
> 
> projection
> 
>  字段、
> 
> MaplibreProjection
> 
> 、
> 
> MaplibreGlobeControl
> 
> 。组件挂载后覆盖样式声明，卸载时还原样式原值（未声明则为 mercator）；控件切换不回写组件，下次样式重载或组件 props 变化时以组件值为准。每张地图只挂一个 
> 
> MaplibreProjection
> 
> 。

## 用法

低 zoom 下展示球体，搭配 `MaplibreSky` 的 `atmosphere-blend` 渲染大气光晕：

```vue [ProjectionExample.vue]
<template>
  <div class="h-115 w-full overflow-hidden rounded-(--ui-radius) border border-default">
    <MaplibreMap :options="{ style: 'https://tiles.openfreemap.org/styles/liberty', center: [105, 30], zoom: 1.5 }">
      <MaplibreProjection />
      <MaplibreSky
        :options="{
          'sky-color': '#199EF3',
          'horizon-color': '#f0f8ff',
          'atmosphere-blend': ['interpolate', ['linear'], ['zoom'], 0, 1, 5, 1, 7, 0]
        }"
      />
    </MaplibreMap>
  </div>
</template>
```

## 示例

### 缩放过渡

`type` 使用插值表达式，缩小时为球体、放大后平滑过渡为平面：

```vue [ProjectionTransitionExample.vue]
<script setup lang="ts">
import type { ProjectionDefinitionSpecification } from '@maplibre/maplibre-gl-style-spec'

// zoom 10 以下为球体，10~12 之间平滑过渡为平面墨卡托
const type: ProjectionDefinitionSpecification = ['interpolate', ['linear'], ['zoom'], 10, 'vertical-perspective', 12, 'mercator']
</script>

<template>
  <div class="h-115 w-full overflow-hidden rounded-(--ui-radius) border border-default">
    <MaplibreMap :options="{ style: 'https://tiles.openfreemap.org/styles/positron', center: [116.39, 39.91], zoom: 3 }">
      <MaplibreProjection :type="type" />
      <MaplibreNavigationControl position="top-right" />
    </MaplibreMap>
  </div>
</template>
```

### 样式声明

样式自带 `projection` 时无需组件即可生效；挂载组件临时覆盖，卸载后还原样式原值：

```vue [ProjectionStyleExample.vue]
<script setup lang="ts">
import type { StyleSpecification } from 'maplibre-gl'

const flat = ref(false)

// 样式自带 globe 投影；组件挂载时覆盖为 mercator，卸载后还原样式原值
const style: StyleSpecification = {
  version: 8,
  projection: { type: 'globe' },
  sources: {},
  layers: [{ id: 'background', type: 'background', paint: { 'background-color': '#0b1026' } }]
}
</script>

<template>
  <div class="h-115 w-full overflow-hidden rounded-(--ui-radius) border border-default">
    <MaplibreMap :options="{ style, center: [105, 30], zoom: 1.5 }">
      <MaplibreTiandituLayer layer="img" />
      <div class="absolute left-3 top-3 z-10">
        <UButton size="xs" color="neutral" variant="solid" @click="flat = !flat">
          {{ flat ? 'Restore style projection' : 'Override with mercator' }}
        </UButton>
      </div>
      <MaplibreProjection v-if="flat" type="mercator" />
    </MaplibreMap>
  </div>
</template>
```

## API

### Props

```ts
/**
 * Props for the MaplibreProjection component
 */
interface MaplibreProjectionProps {
  /**
   * 投影类型：'mercator' / 'globe' / 'vertical-perspective'，或按 zoom 插值的表达式（如 `['interpolate', ['linear'], ['zoom'], 10, 'vertical-perspective', 12, 'mercator']`）
   * @default 'globe'
   */
  type?: ProjectionDefinitionSpecification | undefined;
  /**
   * 完整投影规格，优先级高于 type
   */
  options?: ProjectionSpecification | undefined;
}
```

## Changelog

See commit history for [src/runtime/components/environment/Projection.vue](https://github.com/mhaibaraai/movk-maplibre/commits/main/src/runtime/components/environment/Projection.vue).


## Sitemap

See the full [sitemap](https://maplibre.mhaibaraai.cn/sitemap.md) for all pages.
