阅读视图

发现新文章,点击刷新页面。

02. 环境搭建

MapLibre 学习指南:文章导航

在线预览地址:env-00jy66xyyn4y-static.normal.cloudstatic.cn/maplibre-ba…

base 代码仓库地址:

如果这个系列对你有帮助,欢迎给仓库点一个 Star,代码仓库可以拉取到完整的学习代码,在docs目录下有规划良好的.md学习文档,希望可以帮助到你(请给个免费的start哦)。你的支持是我持续更新和完善 MapLibre 学习内容的动力,也能帮助更多正在学习 WebGIS / MapLibre 的前端同学找到这份资料。[个人微信: 1576554007 欢迎一起学习交流]

第一阶段:入门基础(第 1-4 节)

节次 标题 核心内容 文档路径
01 认识 MapLibre GL JS MapLibre 简介与生态、与 Mapbox 的关系、开源许可、应用场景、与其他地图库(Leaflet/OpenLayers/Cesium)对比 src/docs/stage1/01.认识MapLibre.md
02 环境搭建与第一张地图 Vue3+Vite 项目创建、安装 MapLibre GL JS、创建第一张地图(Map 构造函数参数详解)、地图容器与响应式尺寸 src/docs/stage1/02.环境搭建与第一张地图.md
03 地图基础操作 缩放/平移/旋转/倾斜、flyTo/easeTo/jumpTo 动画方法、fitBounds 自适应范围、地图事件监听(click/move/zoom/load) src/docs/stage1/03.地图基础操作.md
04 地图控件 NavigationControl、ScaleControl、GeolocateControl、FullscreenControl、AttributionControl、自定义控件(IControl 接口) src/docs/stage1/04.地图控件.md

02. 环境搭建与第一张地图

环境准备

前置要求

  • Node.js ≥ 18(推荐使用 LTS 版本)
  • 包管理器:pnpm(推荐)/ npm / yarn
  • IDE:VS Code(推荐安装 Vue - Official 扩展)

创建 Vue 3 + TypeScript 项目

# 使用 Vite 创建项目
pnpm create vite maplibre-base --template vue-ts

# 进入项目
cd maplibre-base

# 安装依赖
pnpm install

安装 MapLibre GL JS

pnpm add maplibre-gl

安装后 package.json 中会出现:

{
  "dependencies": {
    "maplibre-gl": "^5.x.x"
  }
}

创建第一张地图

基本步骤

  1. 创建一个 HTML 容器元素
  2. 引入 MapLibre GL JS 和 CSS
  3. 使用 new maplibregl.Map() 初始化地图

最小示例

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from 'vue'
import maplibregl from 'maplibre-gl'
import 'maplibre-gl/dist/maplibre-gl.css'  // 必须引入 CSS

/** 地图容器 DOM 引用 */
const mapContainer = ref<HTMLElement>()
/** 地图实例 */
let map: maplibregl.Map | null = null

onMounted(() => {
  if (!mapContainer.value) return

  map = new maplibregl.Map({
    container: mapContainer.value,  // 容器元素
    style: {                         // 地图样式
      version: 8,
      sources: {
        osm: {
          type: 'raster',
          tiles: ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'],
          tileSize: 256
        }
      },
      layers: [{
        id: 'osm-layer',
        type: 'raster',
        source: 'osm'
      }]
    },
    center: [116.39, 39.91],  // 中心点 [经度, 纬度]
    zoom: 10                   // 缩放级别
  })
})

onBeforeUnmount(() => {
  if (map) {
    map.remove()  // 销毁地图,释放资源
    map = null
  }
})
</script>

<template>
  <div ref="mapContainer" style="width: 100%; height: 100vh;"></div>
</template>

⚠️ 重要:必须引入 maplibre-gl/dist/maplibre-gl.css,否则地图控件样式会异常。


Map 构造函数参数详解

new maplibregl.Map(options) 接受一个配置对象,以下是核心参数:

必填参数

参数 类型 说明
container HTMLElement | string 地图容器,可以是 DOM 元素或元素 ID
style StyleSpecification | string 地图样式,可以是 JSON 对象或样式 URL

视图参数

参数 类型 默认值 说明
center [lng, lat] [0, 0] 地图中心点坐标(经度, 纬度)
zoom number 0 缩放级别(0=全球,18=建筑级别)
bearing number 0 地图旋转角度(0=正北,顺时针)
pitch number 0 地图倾斜角度(0=俯视,60=透视)
minZoom number 0 最小缩放级别
maxZoom number 22 最大缩放级别
maxPitch number 60 最大倾斜角度

交互参数

参数 类型 默认值 说明
interactive boolean true 是否允许交互
scrollZoom boolean true 是否允许滚轮缩放
boxZoom boolean true 是否允许框选缩放
dragRotate boolean true 是否允许拖拽旋转
dragPan boolean true 是否允许拖拽平移
keyboard boolean true 是否允许键盘控制
doubleClickZoom boolean true 是否允许双击缩放
touchZoomRotate boolean true 是否允许触摸缩放旋转

其他常用参数

参数 类型 说明
maxBounds LngLatBoundsLike 限制地图可视范围
fitBoundsOptions object fitBounds 的默认配置
attributionControl boolean 是否显示归属控件(默认 true)
hash boolean 是否将地图状态同步到 URL hash
antialias boolean 是否开启抗锯齿

缩放级别含义

级别 大致比例尺 可见内容
0 1:500,000,000 全球
3 1:70,000,000
5 1:18,000,000 国家
8 1:2,000,000
10 1:500,000 城市
13 1:70,000 城区
15 1:18,000 街道
17 1:4,000 建筑
20 1:500 详细

地图样式(Style)

MapLibre 的样式是一个 JSON 对象,遵循 Style Specification。最简结构如下:

{
  "version": 8,
  "sources": {
    "source-name": {
      "type": "raster",
      "tiles": ["https://tile-server/{z}/{x}/{y}.png"],
      "tileSize": 256
    }
  },
  "layers": [
    {
      "id": "layer-name",
      "type": "raster",
      "source": "source-name"
    }
  ]
}

使用在线样式 URL

除了手写 JSON,也可以直接传入样式 URL:

const map = new maplibregl.Map({
  container: 'map',
  style: 'https://demotiles.maplibre.org/style.json'  // MapLibre 官方演示样式
})

常用免费底图

/** OSM 标准底图 */
const osmStyle = {
  version: 8,
  sources: {
    osm: {
      type: 'raster',
      tiles: ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'],
      tileSize: 256
    }
  },
  layers: [{ id: 'osm', type: 'raster', source: 'osm' }]
}

/** ESRI 卫星影像 */
const satelliteStyle = {
  version: 8,
  sources: {
    satellite: {
      type: 'raster',
      tiles: ['https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}'],
      tileSize: 256
    }
  },
  layers: [{ id: 'satellite', type: 'raster', source: 'satellite' }]
}

/** CARTO 暗色底图 */
const darkStyle = {
  version: 8,
  sources: {
    dark: {
      type: 'raster',
      tiles: ['https://basemaps.cartocdn.com/dark_all/{z}/{x}/{y}@2x.png'],
      tileSize: 256
    }
  },
  layers: [{ id: 'dark', type: 'raster', source: 'dark' }]
}

Vue 3 中使用 MapLibre 的注意事项

1. 不要将 Map 实例存为 reactive/ref

// ❌ 错误:会导致 Vue 深度代理 Map 对象,严重影响性能
const map = ref<maplibregl.Map>()

// ✅ 正确:使用普通变量
let map: maplibregl.Map | null = null

MapLibre Map 实例内部有大量 WebGL 上下文和事件监听器,Vue 的响应式代理会干扰其内部状态。

2. 组件卸载时销毁地图

onBeforeUnmount(() => {
  if (map) {
    map.remove()  // 释放 WebGL 上下文和事件监听
    map = null
  }
})

3. 容器必须有明确的宽高

地图容器 必须 有确定的宽度和高度,否则地图不会渲染:

/* ✅ 正确 */
.map-container {
  width: 100%;
  height: 100%;
}

/* ❌ 错误 - 高度为 auto 时容器高度为 0 */
.map-container {
  width: 100%;
}

4. 地图加载完成后再操作

map.on('load', () => {
  // 在这里添加数据源、图层等
  map.addSource('my-source', { ... })
  map.addLayer({ ... })
})

本课小结

  • MapLibre GL JS 通过 npm/pnpm 安装,必须同时引入 CSS
  • new maplibregl.Map(options) 是一切的起点
  • 核心参数:containerstylecenterzoom
  • Vue 中注意:不要用 ref() 包裹 Map 实例,卸载时要 map.remove()
  • 容器必须有明确的宽高

📌 上一节:01. 认识 MapLibre 📌 下一节:03. 地图基础操作

❌