关于 mapbox-google-maps-migration
为将 Google Maps Platform 迁移到 Mapbox GL JS 提供指导,面向维护地图应用的开发者。内容涵盖 API 对照、模式转换、迁移步骤与常见问题。
主要功能
- 01Google Maps 与 Mapbox API 对照
- 02地图事件与坐标转换说明
- 03标记、弹窗和图层迁移
- 04分阶段迁移与测试建议
- 05常见问题及性能优化提示
适用场景
- 01将现有 Google Maps 地图替换为 Mapbox GL JS
- 02转换标记、弹窗和地图事件处理
- 03处理经纬度顺序及数据图层更新
- 04评估迁移范围并规划测试
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mapbox/ mapbox-agent-skills --skill mapbox-google-maps-migration安装后在 Claude Code 中输入/mapbox-google-maps-migration确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
AGENTS.mdevals/evals.jsonreferences/api-services.mdclustering-styling.mddata-performance.mddirections-controls.mdshapes-geocoding.md详细介绍
Mapbox Google Maps 迁移技能
从 Google Maps Platform 迁移到 Mapbox GL JS 的全面指南。提供 API 对应关系、模式转换和成功迁移的策略。
核心理念差异
Google Maps:命令式与面向对象
- 创建对象(Marker、Polygon 等)
- 使用
.setMap(map)添加到地图 - 使用 setter 更新属性
- 高度依赖对象实例
Mapbox GL JS:声明式与数据驱动
- 添加数据源
- 定义图层(可视化表示)
- 使用 JSON 设置样式
- 更新数据,而非对象属性
关键要点: Mapbox 将一切视为数据 + 样式,而非单独的对象。
地图初始化
Google Maps
const map = new google.maps.Map(document.getElementById('map'), {
center: { lat: 37.7749, lng: -122.4194 },
zoom: 12,
mapTypeId: 'roadmap' // or 'satellite', 'hybrid', 'terrain'
});
Mapbox GL JS
mapboxgl.accessToken = 'YOUR_MAPBOX_TOKEN';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12', // or satellite-v9, outdoors-v12
center: [-122.4194, 37.7749], // [lng, lat] - note the order!
zoom: 12
});
主要差异:
- 坐标顺序: Google 使用
{lat, lng},Mapbox 使用[lng, lat] - 身份验证: Google 在脚本标签中使用 API 密钥,Mapbox 在代码中使用访问令牌
- 样式: Google 使用地图类型,Mapbox 使用完整的样式 URL
API 对应关系参考
地图方法
| Google Maps | Mapbox GL JS | 说明 |
|---|---|---|
map.setCenter(latLng) | map.setCenter([lng, lat]) | 坐标顺序相反 |
map.getCenter() | map.getCenter() | 返回 LngLat 对象 |
map.setZoom(zoom) | map.setZoom(zoom) | 行为相同 |
map.getZoom() | map.getZoom() | 行为相同 |
map.panTo(latLng) | map.panTo([lng, lat]) | 平滑移动 |
map.fitBounds(bounds) | map.fitBounds([[lng,lat],[lng,lat]]) | 边界格式不同 |
map.setMapTypeId(type) | map.setStyle(styleUrl) | 方法完全不同 |
map.getBounds() | map.getBounds() | 类似 |
地图事件
| Google Maps | Mapbox GL JS | 说明 |
|---|---|---|
google.maps.event.addListener(map, 'click', fn) | map.on('click', fn) | 语法更简洁 |
event.latLng | event.lngLat | 事件属性名称 |
'center_changed' | 'move' / 'moveend' | 事件名称不同 |
'zoom_changed' | 'zoom' / 'zoomend' | 事件名称不同 |
'bounds_changed' | 'moveend' | 没有直接对应项 |
'mousemove' | 'mousemove' | 相同 |
'mouseout' | 'mouseleave' | 名称不同 |
标记和点
简单标记
Google Maps:
const marker = new google.maps.Marker({
position: { lat: 37.7749, lng: -122.4194 },
map: map,
title: 'San Francisco',
icon: 'custom-icon.png'
});
// Remove marker
marker.setMap(null);
Mapbox GL JS:
// Create marker
const marker = new mapboxgl.Marker()
.setLngLat([-122.4194, 37.7749])
.setPopup(new mapboxgl.Popup().setText('San Francisco'))
.addTo(map);
// Remove marker
marker.remove();
多个标记
Google Maps:
const markers = locations.map(
(loc) =>
new google.maps.Marker({
position: { lat: loc.lat, lng: loc.lng },
map: map
})
);
Mapbox GL JS(对应方式):
// Same object-oriented approach
const markers = locations.map((loc) => new mapboxgl.Marker().setLngLat([loc.lng, loc.lat]).addTo(map));
Mapbox GL JS(数据驱动方式——推荐用于 100 个以上的点):
// Add as GeoJSON source + layer (uses WebGL, not DOM)
map.addSource('points', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: locations.map((loc) => ({
type: 'Feature',
geometry: { type: 'Point', coordinates: [loc.lng, loc.lat] },
properties: { name: loc.name }
}))
}
});
map.addLayer({
id: 'points-layer',
type: 'circle', // or 'symbol' for icons
source: 'points',
paint: {
'circle-radius': 8,
'circle-color': '#ff0000'
}
});
性能优势: Google Maps 会将所有标记渲染为 DOM 元素(即使使用 Data Layer 也是如此),当标记超过 500 个时,速度会变慢。Mapbox 的圆形图层和符号图层通过 WebGL 渲染,因此处理大型数据集(1,000 至 10,000 个以上的点)时速度快得多。这对于构建包含大量点的应用来说是一项显著优势。
信息窗口 / 弹出窗口
Google Maps
const infowindow = new google.maps.InfoWindow({
content: '<h3>Title</h3><p>Content</p>'
});
marker.addListener('click', () => {
infowindow.open(map, marker);
});
Mapbox GL JS
// Option 1: Attach to marker
const marker = new mapboxgl.Marker()
.setLngLat([-122.4194, 37.7749])
.setPopup(new mapboxgl.Popup().setHTML('<h3>Title</h3><p>Content</p>'))
.addTo(map);
// Option 2: On layer click (for data-driven markers)
map.on('click', 'points-layer', (e) => {
const coordinates = e.features[0].geometry.coordinates.slice();
const description = e.features[0].properties.description;
new mapboxgl.Popup().setLngLat(coordinates).setHTML(description).addTo(map);
});
迁移策略
步骤 1:审查当前实现
确定你使用的所有 Google Maps 功能:
- 基础地图与标记
- 信息窗口/弹出窗口
- 多边形/折线
- 地理编码
- 路线规划
- 聚类
- 自定义样式
- 绘图工具
- 街景(Mapbox 没有对应功能)
- 其他高级功能
步骤 2:设置 Mapbox
<script src="https://api.mapbox.com/mapbox-gl-js/v3.18.1/mapbox-gl.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v3.18.1/mapbox-gl.css" rel="stylesheet" />
步骤 3:转换核心地图
从基础地图初始化开始:
- 将
new google.maps.Map()替换为new mapboxgl.Map() - 修正坐标顺序(lat,lng -> lng,lat)
- 更新缩放级别/中心点
步骤 4:逐一转换功能
按复杂程度确定优先级:
- 简单: 地图控件、基础标记
- 中等: 弹出窗口、多边形、线条
- 复杂: 聚类、自定义样式、数据更新
步骤 5:更新事件处理程序
更改事件语法:
google.maps.event.addListener()->map.on()- 更新事件属性名称(
latLng->lngLat)
步骤 6:针对 Mapbox 进行优化
利用 Mapbox 的功能:
- 将多个标记转换为数据驱动图层
- 使用聚类(内置)
- 利用矢量瓦片实现自定义样式
- 使用表达式实现动态样式
步骤 7:全面测试
- 跨浏览器测试
- 移动设备响应式表现
- 使用实际数据量测试性能
- 触控/手势交互
注意事项和常见问题
坐标顺序
// Google Maps
{ lat: 37.7749, lng: -122.4194 }
// Mapbox (REVERSED!)
[-122.4194, 37.7749]
务必仔细检查坐标顺序!
事件属性
// Google Maps
map.on('click', (e) => {
console.log(e.latLng.lat(), e.latLng.lng());
});
// Mapbox
map.on('click', (e) => {
console.log(e.lngLat.lat, e.lngLat.lng);
});
时序问题
// Google Maps - immediate
const marker = new google.maps.Marker({ map: map });
// Mapbox - wait for load
map.on('load', () => {
map.addSource(...);
map.addLayer(...);
});
移除功能
// Google Maps
marker.setMap(null);
// Mapbox - must remove both
map.removeLayer('layer-id');
map.removeSource('source-id');
更新数据且不闪烁
切勿通过移除并重新添加图层来更新数据——这会重新初始化 WebGL 资源,并导致明显闪烁。请改用:
// ✅ Update data in place (no flash)
map.getSource('stores').setData(newGeoJSON);
// ✅ Filter existing data (GPU-side, fastest)
map.setFilter('stores-layer', ['==', ['get', 'category'], 'coffee']);
// ❌ BAD: remove + re-add causes flash
map.removeLayer('stores-layer');
map.removeSource('stores');
map.addSource('stores', { ... });
map.addLayer({ ... });
不适合迁移的情况
以下情况可考虑继续使用 Google Maps:
- 街景至关重要 - Mapbox 没有对应功能
- 与 Google Workspace 深度集成 - Places API 集成紧密
- 已完成大量优化 - 迁移成本高于收益
- 团队专业知识 - 重新培训成本过高
- 短期项目 - 不值得投入迁移工作
快速参考:并排对比
// GOOGLE MAPS
const map = new google.maps.Map(el, {
center: { lat: 37.7749, lng: -122.4194 },
zoom: 12
});
const marker = new google.maps.Marker({
position: { lat: 37.7749, lng: -122.4194 },
map: map
});
google.maps.event.addListener(map, 'click', (e) => {
console.log(e.latLng.lat(), e.latLng.lng());
});
// MAPBOX GL JS
mapboxgl.accessToken = 'YOUR_TOKEN';
const map = new mapboxgl.Map({
container: el,
center: [-122.4194, 37.7749], // REVERSED!
zoom: 12,
style: 'mapbox://styles/mapbox/streets-v12'
});
const marker = new mapboxgl.Marker()
.setLngLat([-122.4194, 37.7749]) // REVERSED!
.addTo(map);
map.on('click', (e) => {
console.log(e.lngLat.lat, e.lngLat.lng);
});
请记住: Mapbox 中的坐标顺序是 lng, lat!
其他资源
与其他技能集成
可配合使用:
- mapbox-web-integration-patterns:针对特定框架的迁移指导
- mapbox-web-performance-patterns:迁移后进行优化
- mapbox-token-security:妥善保护 Mapbox 令牌
- mapbox-geospatial-operations:有效使用 Mapbox 地理空间工具
- mapbox-search-patterns:迁移地理编码/搜索功能
参考文件
以下参考文件包含特定主题的详细迁移指南。在处理相关领域时,请加载这些文件:
references/shapes-geocoding.md— 多边形、折线、自定义图标、地理编码references/directions-controls.md— 路线规划/路由、控件references/clustering-styling.md— 聚类、样式/外观references/data-performance.md— 数据更新、性能、常见迁移模式(门店定位器、绘图工具、热力图)references/api-services.md— API 服务对比、定价、插件、框架集成、测试、迁移检查清单
要加载参考文件,请读取相对于此技能目录的文件,例如:
Load references/shapes-geocoding.md