03. 地图基础操作

4 阅读5分钟

MapLibre 学习指南:文章导航

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

base 代码仓库地址:

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

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

节次标题核心内容文档路径
01认识 MapLibre GL JSMapLibre 简介与生态、与 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

03. 地图基础操作

概述

MapLibre GL JS 提供了丰富的地图视图操作方法,本节学习以下核心内容:

  • 导航方法flyTo / easeTo / jumpTo
  • 范围适配fitBounds
  • 视图控制:缩放、平移、旋转、倾斜
  • 事件监听:click、move、zoom、load 等

三种导航方法对比

flyTo — 飞行动画

模拟 飞行效果,先缩小(鸟瞰)再放大到目标位置,最常用于长距离跳转。

map.flyTo({
  center: [121.47, 31.23],  // 目标中心点
  zoom: 12,                  // 目标缩放级别
  speed: 1.2,                // 飞行速度(默认 1.2)
  curve: 1.5,                // 飞行曲线(值越大越"飞高")
  essential: true             // 是否为必要动画(辅助功能相关)
})

特点:视觉效果最好,适合城市间切换、用户引导动画。

easeTo — 平滑过渡

线性平滑过渡到目标视图,没有"飞行"效果,适合短距离移动。

map.easeTo({
  center: [121.47, 31.23],
  zoom: 12,
  bearing: 30,       // 旋转角度
  pitch: 45,         // 倾斜角度
  duration: 2000     // 动画时长(毫秒)
})

特点:可同时设置 bearing/pitch,适合短距离 + 视角变换。

jumpTo — 瞬间跳转

无动画,直接跳转到目标视图。

map.jumpTo({
  center: [121.47, 31.23],
  zoom: 12
})

特点:无过渡效果,适合程序化设置初始视图或批量操作。

三者对比总结

方法动画效果适用距离可设置参数
flyTo飞行弧线长距离center, zoom, speed, curve
easeTo平滑线性短距离center, zoom, bearing, pitch, duration
jumpTo无动画任意center, zoom, bearing, pitch

fitBounds — 范围适配

根据给定的地理边界框,自动调整地图视图使其完整显示在视口中。

// 参数:[[西南角], [东北角]]
map.fitBounds(
  [[73.5, 18.2], [135.0, 53.5]],   // 中国大致范围
  {
    padding: 40,          // 内边距(像素)
    maxZoom: 15,          // 最大缩放级别
    duration: 1500,       // 动画时长
    linear: false         // 是否使用线性动画
  }
)

padding 参数

可以是统一值或分别设定:

// 统一 40px
fitBounds(bounds, { padding: 40 })

// 分别设定
fitBounds(bounds, {
  padding: { top: 50, bottom: 50, left: 300, right: 20 }
})

💡 常见用途:当左侧有控制面板遮挡地图时,可以设置 left: 300 来偏移。


获取和设置地图状态

// 获取当前中心点
const center = map.getCenter()  // { lng, lat }

// 获取当前缩放级别
const zoom = map.getZoom()  // number

// 获取当前旋转角度
const bearing = map.getBearing()  // number (度)

// 获取当前倾斜角度
const pitch = map.getPitch()  // number (度)

// 获取当前可视范围
const bounds = map.getBounds()  // LngLatBounds

// 设置中心点(无动画)
map.setCenter([116.39, 39.91])

// 设置缩放级别(无动画)
map.setZoom(12)

// 设置旋转角度
map.setBearing(45)

// 设置倾斜角度
map.setPitch(60)

// 重置方向(指北)
map.resetNorth()
map.resetNorthPitch()  // 同时重置倾斜

事件监听

MapLibre 的事件系统基于 on / off / once 方法。

地图生命周期事件

// 地图加载完成(样式和首屏瓦片就绪)
map.on('load', () => {
  console.log('地图加载完成')
  // 在这里添加数据源和图层
})

// 样式加载完成(样式 JSON 解析就绪,瓦片可能还没加载)
map.on('style.load', () => {
  console.log('样式加载完成')
})

// 地图首次完整渲染
map.on('idle', () => {
  console.log('地图空闲')
})

交互事件

// 鼠标点击
map.on('click', (e) => {
  console.log('点击坐标:', e.lngLat)  // { lng, lat }
  console.log('屏幕坐标:', e.point)   // { x, y }
})

// 鼠标移动
map.on('mousemove', (e) => {
  console.log('鼠标位置:', e.lngLat)
})

// 右键菜单
map.on('contextmenu', (e) => {
  e.preventDefault()
  console.log('右键:', e.lngLat)
})

视图变化事件

// 缩放变化
map.on('zoom', () => console.log('缩放中', map.getZoom()))
map.on('zoomstart', () => console.log('缩放开始'))
map.on('zoomend', () => console.log('缩放结束', map.getZoom()))

// 移动变化
map.on('move', () => console.log('移动中'))
map.on('movestart', () => console.log('移动开始'))
map.on('moveend', () => console.log('移动结束'))

// 旋转变化
map.on('rotate', () => console.log('旋转中', map.getBearing()))
map.on('rotatestart', () => console.log('旋转开始'))
map.on('rotateend', () => console.log('旋转结束'))

// 倾斜变化
map.on('pitch', () => console.log('倾斜中', map.getPitch()))
map.on('pitchstart', () => console.log('倾斜开始'))
map.on('pitchend', () => console.log('倾斜结束'))

移除事件

function handleClick(e: maplibregl.MapMouseEvent) {
  console.log(e.lngLat)
}

// 添加
map.on('click', handleClick)

// 移除
map.off('click', handleClick)

// 只监听一次
map.once('click', (e) => {
  console.log('只触发一次:', e.lngLat)
})

实用技巧

1. 判断地图是否在移动中

if (map.isMoving()) {
  console.log('地图正在移动/缩放/旋转')
}

2. 限制地图范围

// 用户只能在中国范围内浏览
map.setMaxBounds([[73.5, 18.2], [135.0, 53.5]])

3. 停止正在进行的动画

map.stop()  // 立即停止所有动画

4. 动画完成回调

flyToeaseTo 没有回调参数,需要监听 moveend

map.once('moveend', () => {
  console.log('飞行动画完成')
})
map.flyTo({ center: [121.47, 31.23], zoom: 12 })

本课小结

  • flyTo 适合长距离飞行,视觉效果最好
  • easeTo 适合短距离 + 视角变换,可精确控制时长
  • jumpTo 无动画瞬间跳转
  • fitBounds 自适应显示指定范围,支持 padding 偏移
  • 事件分三类:生命周期(load/idle)、交互(click/mousemove)、视图变化(zoom/move/rotate)
  • on / off / once 管理事件监听

📌 上一节:02. 环境搭建与第一张地图 📌 下一节:04. 地图控件