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 项目

bash 复制代码
# 使用 Vite 创建项目
pnpm create vite maplibre-base --template vue-ts

# 进入项目
cd maplibre-base

# 安装依赖
pnpm install

安装 MapLibre GL JS

bash 复制代码
pnpm add maplibre-gl

安装后 package.json 中会出现:

json 复制代码
{
  "dependencies": {
    "maplibre-gl": "^5.x.x"
  }
}

创建第一张地图

基本步骤

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

最小示例

vue 复制代码
<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`
style `StyleSpecification string`

视图参数

参数 类型 默认值 说明
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。最简结构如下:

json 复制代码
{
  "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:

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

常用免费底图

ts 复制代码
/** 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

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

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

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

2. 组件卸载时销毁地图

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

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

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

css 复制代码
/* ✅ 正确 */
.map-container {
  width: 100%;
  height: 100%;
}

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

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

ts 复制代码
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. 地图基础操作

相关推荐
原则猫1 小时前
前端基础大厦
前端
陈随易2 小时前
编程语言级别的Skill市场,AI Agent 的未来形态
前端·后端·程序员
SoaringHeart3 小时前
Flutter进阶:基于 EasyRefresh 的下拉刷新封装 n_easy_refresh_mixin.dart
前端·flutter
IT_陈寒5 小时前
Vite的热更新突然不香了,排查三小时差点砸键盘
前端·人工智能·后端
子兮曰5 小时前
Agency-Agents 深度解析:400+ AI 专家的"梦之队"如何重塑开发工作流
前端·后端·vibecoding
竹林8186 小时前
用 The Graph 查询链上数据实战:从手搓 RPC 到 Subgraph,我的 NFT 项目数据加载快了 10 倍
前端·javascript
妙码生花6 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(十九):点选验证码代码逐行目检
前端·后端·go
Awu12277 小时前
⚡从零开发 Agent CLI(五)实现一个可治理、可扩展的工具系统
前端·人工智能·claude
咪库咪库咪8 小时前
Vue3-生命周期
前端
莪_幻尘8 小时前
你的 AI Skill 越多越蠢?Token 上下文爆炸的求生指南
前端·ai编程