
开发地图类 Web 应用时高德地图 JS API 是国内使用最频繁的地图方案之一。它提供了一套非常完整的前端地图能力从基础底图加载、Marker 标记、信息窗体、路径规划到行政区划、地理编码、自定义图层等都能覆盖。很多开发者第一次接触高德地图时会遇到两个典型问题一是不知道如何申请 Key 并正确接入二是只会在页面上渲染一张地图不知道怎么把业务数据比如设备位置、店铺坐标、小区楼栋转换成可交互的标记和弹窗。这篇文章就围绕高德地图 JS API 2.0 的入门实战来展开。我们会从最重要的环境准备讲起接着拆解地图初始化、Marker、InfoWindow、事件监听等核心知识点最后用一个“小区周边信息可视化”的完整案例把这些知识串起来。文章里的代码都是可以复制运行的版本和参数也会标注清楚。不管你是刚接触前端地图开发还是准备在后台管理系统中集成地图模块这篇内容都适合你收藏后一步步跟着做。1. 高德地图 JS API 是什么为什么要学它1.1 地图 API 在前端开发中的位置在业务系统中地图能力通常不是核心业务但它往往是体验的放大器。比如外卖平台展示骑手位置、物流系统展示运输轨迹、房产平台展示小区周边配套、设备运维平台展示设备分布这些都离不开地图。高德地图 JS API 是一套运行在浏览器端的 JavaScript 接口它帮我们解决了下面几个关键问题底图加载不用自己处理瓦片拼接、缩放级别、坐标系切换。交互交互交互拖拽、缩放、双击放大等地图操作直接可用。数据可视化支持 Marker、Polyline、Polygon、Circle、HeatMap 等多种图层。业务融合可以基于经纬度把业务数据标在地图上也可以反过来通过点击地图获取坐标。换句话说当我们把地图当成一个普通的前端组件来使用时高德 JS API 就是最省力的载体。1.2 高德地图 JS API 1.4 与 2.0 的区别目前常用的高德地图 JS API 版本有两个1.4.x 和 2.0.x。2.0 版本在 2021 年之后逐渐成为主流两者的主要区别如下对比项JS API 1.4JS API 2.0加载方式通过 script 标签全局引入支持 npm 包和 script 标签引入底层渲染Canvas 与 DOM 混用全面转向 Canvas 渲染性能更好构建工具兼容需要全局变量 AMap配合 Webpack/Vite 更方便做按需加载安全密钥部分服务无需推荐使用安全密钥官方维护状态仍在维护新项目建议使用 2.0本文的示例统一使用 2.0 版本这是目前官方主推的版本也是新项目接入成本最低的版本。1.3 常用概念经纬度、坐标系、Marker在进入代码之前有几个基础概念必须先弄清楚。经纬度是最常见的坐标表示方式。高德地图中的经纬度顺序是[经度, 纬度]也就是[lng, lat]这一点在写代码时很容易和某些地图 SDK 弄反。举个例子杭州西湖的坐标约为经度 120.137、纬度 30.259那么传给高德的数组就是[120.137, 30.259]。坐标系是另一个容易踩坑的地方。国内地图普遍使用 GCJ-02 坐标系俗称“火星坐标系”它是在 WGS-84 标准经纬度基础上做了加密偏移的。如果你拿 GPS 设备采集到的原始 WGS-84 坐标直接打到高德地图上可能会出现几百米的偏移。高德官方提供了坐标转换 API专门用于将其他坐标系坐标转换为高德坐标系。Marker是地图上的点标记业务里最常见的需求就是在地图上画若干个点。Marker 可以自定义图标、旋转角度、锚点位置也可以绑定点击事件。这块内容会在后面的核心代码中详细讲解。2. 环境准备与账号开通2.1 注册开发者账号并创建应用在使用高德地图 JS API 之前需要先有一个高德开放平台账号。整个流程如下打开高德开放平台使用高德账号登录。进入“控制台 - 应用管理 - 我的应用”。点击“创建新应用”填写应用名称和应用类型。在应用下点击“添加 Key”选择服务平台为“Web端JS API”。创建成功后会得到一个 Key 和一个安全密钥jscode。这里需要特别注意JS API 2.0 强制开启了安全密钥校验。也就是说只配置 Key 不够还必须配置安全密钥。配置安全密钥有两种方式方式一直接在 HTML script 标签中代理请求。script typetext/javascript window._AMapSecurityConfig { securityJsCode: 你的安全密钥, }; /script方式二在服务端设置代理避免在前端暴露密钥。这种方案更安全适合生产环境。可以在服务端接收请求后加上安全密钥再转发到高德服务端。2.2 引入方式script 标签与 npm 包高德地图 JS API 2.0 提供两种引入方式。如果项目是普通 HTML 页面使用 script 标签引入即可script typetext/javascript window._AMapSecurityConfig { securityJsCode: 你的安全密钥, }; /script script typetext/javascript srchttps://webapi.amap.com/maps?v2.0key你的Key/script注意上面的v2.0表示加载 2.0 版本。加载完成后浏览器全局会挂载一个AMap对象所有地图操作都通过它来完成。如果项目是 Vue 或 React 工程更推荐使用 npm 包方式。npm install amap/amap-jsapi-loader --saveamap/amap-jsapi-loader是高德官方提供的加载器它封装了 script 标签动态加载逻辑更适合工程化项目。后面完整实战部分会以这个方式为主。2.3 示例项目结构为了后面方便对照我们先规划好一个最小项目结构maptest ├── index.html └── src ├── main.js └── map ├── init.js ├── marker.js └── infoWindow.jsindex.html入口 HTML 文件用于挂载地图容器。src/main.js项目入口负责初始化地图并调用各功能模块。src/map/init.js地图初始化逻辑。src/map/marker.js标记管理逻辑。src/map/infoWindow.js信息窗体管理逻辑。如果你的项目本身是 Vue 或者 React 脚手架也可以把对应逻辑写在组件中思路完全一致。本文为了突出地图 API 本身使用原生 ES Module 示例避免框架写法干扰理解。3. 地图初始化第一个最小示例3.1 创建地图容器在地图上展示内容之前HTML 里必须有一个承载地图的容器节点。高德地图最终会在这个节点的区域内渲染底图。!DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title高德地图 JS API 入门示例/title style #mapContainer { width: 100%; height: 100vh; } /style /head body div idmapContainer/div script srchttps://webapi.amap.com/maps?v2.0key你的Key/script script // 地图初始化代码 /script /body /html这里要注意一个非常基础但容易忽略的点容器必须有明确的高度。如果父级元素没有高度或者容器本身没有设置 height地图初始化的结果是空白控制台会出现“container”相关报错或没有任何报错但地图不显示。所以上面示例中为#mapContainer设置了100vh的高度。3.2 初始化地图实例地图实例通过new AMap.Map(containerId, options)创建。const map new AMap.Map(mapContainer, { zoom: 12, // 初始缩放级别范围 3-20 center: [120.137, 30.259], // 初始中心点经纬度 viewMode: 2D, // 地图模式2D 或 3D pitch: 0, // 倾斜角度3D 模式下生效 rotate: 0, // 旋转角度 resizeEnable: true, // 是否监控地图容器尺寸变化 });关键参数解释zoom地图缩放级别数值越大显示的地图范围越小、细节越多。center地图初始化时的中心点坐标。viewMode2D是普通平面地图3D会带一点倾斜透视效果。resizeEnable如果地图容器在初始化后尺寸发生变化比如侧边栏收起这个配置能自动调整地图大小。初始化之后如果页面上出现了高德地图并且可以正常拖拽缩放说明接入已经成功。3.3 通过 npm 方式初始化如果使用 Vite 或 Webpack 工程推荐使用官方加载器代码会更整洁。// src/main.js import AMapLoader from amap/amap-jsapi-loader; window._AMapSecurityConfig { securityJsCode: 你的安全密钥, }; async function initMap() { const AMap await AMapLoader.load({ key: 你的Key, version: 2.0, plugins: [], }); const map new AMap.Map(mapContainer, { zoom: 12, center: [120.137, 30.259], viewMode: 2D, resizeEnable: true, }); return map; } initMap().then((map) { console.log(地图初始化成功, map); });通过AMapLoader.load返回的AMap对象是完整的命名空间后续才能使用AMap.Marker、AMap.InfoWindow等类。这里建议把initMap写成返回 Promise 的方法方便在外部继续做业务扩展。4. 核心能力拆解Marker、InfoWindow、事件与坐标转换4.1 Marker 点标记的使用Marker 是地图中最常用的覆盖物。它的作用是把一个业务点放到地图的某个经纬度上并可以自定义展示内容。最简单的 Marker 用法如下const marker new AMap.Marker({ position: [120.137, 30.259], title: 站点名称, map: map, });创建 Marker 时如果传入map它会被立即添加到当前地图实例上。不传map的话需要手动调用marker.setMap(map)。在实际项目中Marker 通常需要自定义图标和大小const marker new AMap.Marker({ position: [120.137, 30.259], content: div classcustom-marker站点/div, offset: new AMap.Pixel(-30, -40), anchor: bottom-center, zIndex: 120, });这里有个容易踩坑的地方content传入的是一段 HTML 字符串图标中心点并不一定等于经纬度对应的位置。默认情况下Marker 的锚点在图标中心但如果你给 Marker 设置了高宽不一的自定义 DOM那锚点位置就会出现偏差。可以通过offset或者anchor来控制标记和坐标点之间的相对位置保证点击标记时能够准确指向业务坐标。批量添加 Marker 时建议把所有 marker 实例存到一个数组中方便后续做删除、隐藏、聚合等操作。const markerList []; const positions [ [120.137, 30.259], [120.152, 30.274], [120.128, 30.241], ]; positions.forEach((pos, index) { const m new AMap.Marker({ position: pos, title: 点位${index 1}, map: map, }); markerList.push(m); });4.2 InfoWindow 信息窗体如果用户点击 Marker 后只看到一个点交互反馈是不够的。通常做法是点击 Marker 时弹出信息窗体显示详细业务数据。InfoWindow 的用法如下const infoWindow new AMap.InfoWindow({ offset: new AMap.Pixel(0, -30), autoMove: true, }); function showInfo(content, position) { infoWindow.setContent(content); infoWindow.open(map, position); }然后给上面的 Marker 绑定点击事件marker.on(click, () { showInfo( div h4站点名称/h4 p地址浙江省杭州市西湖区/p p建议到访时间全天/p /div , marker.getPosition()); });这里要注意的是infoWindow.open(map, position)的第二个参数必须是一个AMap.LngLat对象而不是普通数组。marker.getPosition()返回的正好就是AMap.LngLat所以上面代码可以直接使用。如果你的项目中每次只允许打开一个信息窗体那么全局只创建一个InfoWindow实例打开新内容前修改内容并重新打开这是性能最优的做法。如果每个 Marker 都 new 一个 InfoWindow页面上的 DOM 节点会越来越多影响体验。4.3 事件监听高德地图和它的覆盖物都支持事件监听。最常用的事件有两种地图事件map.on(click, (e) { console.log(地图点击位置经纬度, e.lnglat); // e.lnglat 是 AMap.LngLat 对象 // 可以通过 e.lnglat.getLng() 和 e.lnglat.getLat() 获取经度和纬度 });Marker 事件marker.on(click, (e) { console.log(点了标记, e.target); });在实际项目中事件监听要注意内存泄漏问题。尤其在 Vue/React 组件销毁时需要手动移除事件监听和销毁地图实例。map.off(click, handleMapClick); marker.off(click, handleMarkerClick); map.destroy();map.destroy()会销毁地图实例释放相关资源。如果只是移除单个 Marker可以调用marker.setMap(null)。4.4 坐标转换与常见坐标系前面我们提到过坐标系的问题。这里展开说明一下。高德地图 JS API 内置了一个坐标转换插件使用前需要在AMapLoader.load的 plugins 参数中声明。const AMap await AMapLoader.load({ key: 你的Key, version: 2.0, plugins: [AMap.Geocoder], });Geeocoder 插件支持地址和经纬度互转也支持坐标转换。下面是一个地址转经纬度的示例const geocoder new AMap.Geocoder({ city: 全国, }); geocoder.getLocation(玉环市坎门街道, (status, result) { if (status complete result.geocodes.length) { const lnglat result.geocodes[0].location; console.log(坐标, lnglat); } else { console.error(地址解析失败); } });如果你拿到的数据是 GPS 原始坐标希望通过高德地图展示需要调用坐标转换接口。高德官方提供的转换服务是https://restapi.amap.com/v3/assistant/coordinate/convert需要带上 Key 和原始坐标。批量转换一次最多支持 40 个坐标点格式是lng,lat|lng,lat。需要注意的是由于涉及跨域和密钥安全线上项目不建议在浏览器直接调用这个 REST API更合适的做法是由后端服务代为请求。前端只需要把业务坐标统一处理成高德坐标系后传给地图。5. 完整实战小区周边信息可视化前面几节拆解的是零散知识点下面用一个完整案例把它们串联起来。假设我们要在一张地图上展示某个小区的周边配套信息包括便利店、停车场、药店三类 POI兴趣点。5.1 需求分析这个小项目的需求可以拆成四块在地图上展示小区所在位置。根据经纬度加载周边 POI 列表。用不同颜色图标区分 POI 类型。点击 POI 标记后弹出信息窗体展示名称、地址、类型。这里的 POI 数据我们使用静态模拟数据重点是展示地图层面的实现逻辑。如果你想接入高德真实 POI 搜索能力可以使用AMap.PlaceSearch插件它的用法会在 5.5 节补充说明。5.2 项目骨架与页面结构我们基于原生 Vite 项目来演示。先创建项目npm create vitelatest poi-map -- --template vanilla cd poi-map npm install amap/amap-jsapi-loader然后在index.html中准备好地图容器!DOCTYPE html html langzh-CN head meta charsetUTF-8 / meta nameviewport contentwidthdevice-width, initial-scale1.0 / title小区周边 POI 展示/title style * { margin: 0; padding: 0; box-sizing: border-box; } html, body, #app { width: 100%; height: 100%; } #mapContainer { width: 100%; height: 100%; } .poi-marker { display: flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: 50%; color: #fff; font-size: 12px; font-weight: bold; cursor: pointer; border: 2px solid #fff; box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); } .poi-marker.shop { background-color: #ff6d3d; } .poi-marker.parking { background-color: #3d7eff; } .poi-marker.pharmacy { background-color: #00b578; } /style /head body div idmapContainer/div script typemodule src/src/main.js/script /body /htmlpoi-marker这个类名对应的样式会用在自定义 Marker 内容上。三种类型分别对应三种颜色视觉上能快速区分。5.3 编写地图初始化与 Marker 展示逻辑接下来是核心的src/main.jsimport AMapLoader from amap/amap-jsapi-loader; window._AMapSecurityConfig { securityJsCode: 你的安全密钥, }; const MAP_KEY 你的Key; // 小区中心坐标 const COMMUNITY_CENTER [121.2628, 28.0853]; // 模拟周边 POI 数据 const poiList [ { name: 便民超市, type: shop, address: 海都花园东门 100 米, position: [121.2642, 28.0861] }, { name: 中心停车场, type: parking, address: 小区南侧入口, position: [121.2619, 28.0849] }, { name: 社区药店, type: pharmacy, address: 海都花园北门对面, position: [121.2635, 28.0872] }, { name: 生鲜便利店, type: shop, address: 坎门街道海城路, position: [121.2651, 28.0855] }, { name: 室外停车场, type: parking, address: 小区东侧临时停车场, position: [121.2658, 28.0847] }, ]; async function initMap() { const AMap await AMapLoader.load({ key: MAP_KEY, version: 2.0, plugins: [AMap.Scale, AMap.ToolBar], }); const map new AMap.Map(mapContainer, { zoom: 16, center: COMMUNITY_CENTER, viewMode: 2D, resizeEnable: true, }); map.addControl(new AMap.Scale()); map.addControl(new AMap.ToolBar()); return { AMap, map }; } function renderMarkers(AMap, map) { // 创建信息窗体全局只用一个实例 const infoWindow new AMap.InfoWindow({ offset: new AMap.Pixel(0, -30), autoMove: true, }); pois.forEach((poi) { const marker new AMap.Marker({ position: poi.position, content: div classpoi-marker ${poi.type}${poi.type shop ? 商 : poi.type parking ? 停 : 药}/div, offset: new AMap.Pixel(-15, -15), title: poi.name, map: map, }); marker.on(click, () { const content div stylepadding: 8px 10px; min-width: 180px; div stylefont-size: 16px; font-weight: bold; margin-bottom: 6px;${poi.name}/div div stylefont-size: 13px; color: #666;类型${poi.type}/div div stylefont-size: 13px; color: #666;地址${poi.address}/div /div ; infoWindow.setContent(content); infoWindow.open(map, marker.getPosition()); }); }); } async function boot() { const { AMap, map } await initMap(); renderMarkers(AMap, map); } boot();这段代码做的事情很简单通过官方加载器初始化地图。使用AMap.Scale和AMap.ToolBar添加比例尺和缩放工具条。遍历 POI 数组为每个 POI 创建自定义 Marker。给每个 Marker 绑定点击事件点击后通过全局唯一的 InfoWindow 展示详情。5.4 运行与预期结果在项目目录下运行npm run dev浏览器打开 Vite 提供的本地地址正常情况下可以看到初始地图中心在小区所在位置缩放级别为 16。地图上有 5 个彩色圆形标记颜色和类型一一对应。点击任意标记会弹出一个信息窗体显示名称、类型、地址。地图可以正常拖拽和缩放右下角或左上角有工具栏和比例尺。如果页面白屏或者地图不显示优先检查下面几项控制台是否有Invalid key或安全密钥相关报错。index.html中是否已经引入src/main.js。地图容器是否有高度。5.5 扩展接入高德 POI 搜索上面的示例使用了静态模拟数据。真实项目里POI 数据一般来自后端接口或者高德 POI 搜索。高德 JS API 中 POI 搜索通过AMap.PlaceSearch插件完成。const AMap await AMapLoader.load({ key: MAP_KEY, version: 2.0, plugins: [AMap.PlaceSearch], }); const placeSearch new AMap.PlaceSearch({ pageSize: 10, pageIndex: 1, city: 玉环市, extensions: all, }); placeSearch.searchNearBy(便利店, COMMUNITY_CENTER, 1000, (status, result) { if (status complete result.poiList.pois.length) { console.log(POI 数据, result.poiList.pois); // result.poiList.pois 里有 name, address, location 等字段 } });searchNearBy表示在指定坐标点周围搜索关键词第三个参数表示搜索半径单位是米。拿到结果后可以把poi.location作为 Marker 的 position然后把 POI 详情存入数组用于后续展示。需要提醒的是POI 搜索有日配额限制。生产环境建议由后端统一封装请求、缓存结果避免前端高频请求触发限流。6. 常见问题与排查思路6.1 地图不显示页面空白这是最常见的接入问题。可能原因和排查步骤如下。问题现象常见原因解决思路地图容器是空白容器没有高度给容器设置明确的 height如 100vh 或 500px地图容器是空白JS API 未加载成功查看 Network 面板确认 script 是否加载检查 Key 是否有效地图容器是空白安全密钥未配置确认window._AMapSecurityConfig配置了正确的securityJsCode地图初始化报Invalid keyKey 绑定错误或平台错误确认 Key 的应用类型是“Web端JS API”而不是 Web服务部分功能报plugin not found插件未在 plugins 中声明在AMapLoader.load的 plugins 数组中补上对应插件6.2 使用自定义 Marker 时点击位置不准出现这个问题的原因是自定义content的 DOM 尺寸和默认锚点不一致。解决办法是按需调整offset通常取宽高的一半的负值。比如我们的 POI Marker 宽度和高度都是 30px那么offset就是new AMap.Pixel(-15, -15)。如果想实现底部尖角效果可以组合使用anchor: bottom-center。6.3 坐标有几十米到几百米的偏移这种问题基本可以确定是坐标系不一致。需要确认业务数据的坐标系来源高德开放平台获取的数据直接使用。GPS 设备数据先通过坐标转换接口转成 GCJ-02 再展示。其他地图如百度地图导出的坐标百度坐标系BD-09也不等于高德坐标系需要转换。6.4 内存泄漏页面反复跳转后地图越来越卡在单页应用中如果每次进入页面都创建地图实例离开时没有销毁就会堆积大量地图实例。建议在组件卸载时执行清理操作。如果是 Vue 组件可以在onUnmounted中处理onUnmounted(() { map.destroy(); });如果只是临时隐藏地图而非销毁可以调用map.destroy()后重新初始化或者使用container的display: none切换配合map.resize()。6.5 高德地图 Key 泄露风险如果 Key 和 SecurityJsCode 写在前端只要用户打开浏览器调试面板就能看到。为了避免被恶意调用建议在高德开放平台为 Key 设置域名白名单。敏感服务如坐标转换、POI 搜索尽量由后端代理调用。定期更换密钥。7. 最佳实践与工程建议7.1 统一封装地图初始化逻辑一个项目里可能有多个页面都要用到地图每个页面都写一遍AMapLoader.load和new AMap.Map会非常冗余。更合理的做法是把地图逻辑封装成模块。// src/map/index.js import AMapLoader from amap/amap-jsapi-loader; let mapInstance null; export async function createMap(containerId, center, zoom 14) { const AMap await AMapLoader.load({ key: 你的Key, version: 2.0, plugins: [AMap.Scale, AMap.ToolBar, AMap.InfoWindow], }); mapInstance new AMap.Map(containerId, { zoom, center, viewMode: 2D, resizeEnable: true, }); return { AMap, map: mapInstance }; } export function getMapInstance() { return mapInstance; }这样业务页面只需要关心数据展示逻辑不用在意地图底层如何加载。7.2 使用数据层和覆盖物分层管理如果页面上的 Marker 数量很多比如几十上百个建议封装一个 Marker 管理器统一处理新增、删除、清空操作。这样一方面代码更清晰另一方面也方便做聚合和显隐控制。class MarkerManager { constructor(map) { this.map map; this.markers []; } addMarker(option) { const marker new AMap.Marker({ ...option, map: this.map, }); this.markers.push(marker); return marker; } clear() { this.markers.forEach((marker) marker.setMap(null)); this.markers []; } getMarkerById(id) { return this.markers.find((marker) marker.getExtData().id id) || null; } }在创建 Marker 时可以通过extData参数存储业务 ID方便后续查找和操作。7.3 性能优化合理使用聚合与限流当 Marker 数量超过几百个时直接渲染会明显卡顿。这时有两个常用方案。使用高德AMap.MarkerClusterer插件做点聚合。结合地图视野moveend事件只渲染当前视野范围内的 Marker。建议先用聚合插件写法相对简单效果也直观。如果业务对点位密度要求很高再做视野裁剪也是不错的选择。7.4 经纬度和业务数据的绑定不要把经纬度硬编码在前端。真实场景中坐标数据应该和业务对象一起存储比如数据库中的设备点位表有lng、lat字段。前端从接口拿到数据后再渲染 Marker。这样数据更新只需要改数据库不需要改前端代码。7.5 生产环境的安全与合规在地图功能的开发中有两点需要特别重视。一是密钥安全。不要在前端暴露不需要暴露的服务密钥。生产环境建议关闭安全密钥的前端明文配置改用服务端代理方式。二是数据处理合规。涉及用户定位、轨迹等敏感数据时需要遵循最小必要原则只展示业务必要的信息日志中不要输出无关的精确位置信息。8. 总结与后续学习方向本文围绕高德地图 JS API 2.0从账号准备、环境搭建、地图初始化到 Marker、InfoWindow、事件监听和坐标转换完整走了一遍接入过程。最后的“小区周边信息可视化”案例把核心知识点整合成一个可以直接运行的小项目。如果你照着本文完成了一遍应该已经掌握以下技能在高德开放平台创建应用并配置 Key 和安全密钥。通过 script 标签或 npm 包接入高德地图 JS API。初始化地图实例理解 zoom、center、viewMode 等核心参数。创建自定义 Marker解决锚点偏移问题。使用 InfoWindow 展示业务详情。了解坐标系差异和基本的坐标转换思路。在工程化项目中对地图实例进行封装和性能优化。下一步可以根据业务方向继续学习如果你做的是巡检类系统可以研究AMap.Polyline和AMap.MovingMarker用轨迹回放和路径规划补全业务能力。如果你做的是设备管理后台可以研究AMap.Circle和AMap.Polygon在地图上画电子围栏。如果你需要处理大量 POI 数据可以研究AMap.MarkerClusterer点聚合。如果你需要深度定制地图样式可以研究高德自定义地图平台通过样式 ID 加载个性化底图。地图开发本身不难难点在于把地图能力和业务系统本身结合起来。建议你直接拿一个真实业务场景去练习比如把公司附近的便利店或停车场标上去完成以后再尝试优化渲染逻辑和交互体验。实践几次之后你会发现高德地图 JS API 就是我们日常开发的普通工具之一完全不需要有神秘感。