先说几个核心判断:要在微信小程序的 map 组件里实现静态地图展示,这条路不是走截图或者图片方案,而是直接动用原生地图渲染。听起来简单,但坑不少——一旦其中一个条件没满足,地图白屏、标记点消失、缩放卡顿全来了。说到底,核心就一句话:必须走微信原生的 map 渲染层,不能用 cover-view 包裹,不能搞 custom-style,也别把坐标系混着用。

强制走原生渲染层,别碰 custom-style 和 cover-view
uni-app 的 map 组件在微信小程序端,是不支持用 canvas 或者自定义样式来渲染的。真机上出现标记点凭空消失、点击没反应、拖动卡住不动,90% 的原因都是没强制启用原生层。
写法上必须这样:。注意 style 里宽高缺一不可,别想着用 vh 或者 rpx 动态计算——在某些机型上,这样解析会失败。
有两个大忌:一是别加 custom-style,二是别用 cover-view 把 map 标签包起来。所有覆盖层组件,比如定位按钮、气泡提示,都写在 map 标签外部,通过 @markertap 或 @callouttap 来关联事件。
如果你的项目同时跑 H5 和 App,得用 v-if="platform === 'mp-weixin'" 把微信专属写法隔离开,不然 H5 端就会报错。
坐标统一为 GCJ-02,而且必须显式传入 lat/lng
微信原生地图对坐标类型极度敏感。要是直接把高德 API 返回的 WGS-84 坐标丢进去,偏个 300-500 米是常有的事。更坑的是,uni.getLocation({ type: 'wgs84' }) 在真机上经常返回空值,或者偏差很大。
正确的做法只有一条:获取用户位置时,只用 uni.getLocation({ type: 'gcj02' })——这是微信小程序端唯一稳定可靠的定位类型。
如果你要查附近门店,而用的是高德或百度接口,必须调用它们的坐标转换 API(比如高德的 /v3/conv/coord),把结果转成 GCJ-02 再喂给地图组件。
哪怕只显示一个中心点,也一定要显式设置 :latitude 和 :longitude 两个属性。别指望靠 show-location 自动居中,否则标记点很有可能不渲染。
自定义标记图标必须用合法本地路径
真机上图标不显示,几乎全是路径问题。一个常见的误区是:开发工具里跑得通,真机就不一定能跑通。
路径必须是绝对路径,以 / 开头,而且文件要真实存在于 static 目录下面。比如这样写:iconPath: '/static/icon-store.png'。
有三类写法不要用:相对路径(如 '../static/xxx')、变量拼接路径(如 iconPath: `${baseUrl}/store.png`)、网络图(除非域名已加白名单且走 HTTPS)。
图标尺寸建议控制在 30×30 rpx 以内,太大影响渲染性能。width 和 height 必须显式设置,否则 iOS 上有可能会被拉伸变形。
动态更新 markers 时 id 必须是数字且全局唯一
微信原生地图对 markers 数组里的 id,既有类型校验又有唯一性要求。用字符串 ID(比如 "store_123")在 iOS 上大概率会让 @markertap 事件失效。如果 id 重复,新标记会覆盖旧的,但点击触发的仍是旧数据。
所以 id 字段必须用整数。推荐直接用后端返回的主键,通过 Number(store.id) 转换一下,别自己拼字符串。
每次更新 markers 之前,务必深拷贝一次:this.markers = JSON.parse(JSON.stringify(newMarkers)),否则微信内部的引用缓存可能导致界面不刷新。
另外,不要在 marker 对象里塞大字段(比如完整门店描述、长文本),只保留 id、latitude、longitude、name、iconPath 这几个必要项就行。
最后说一句,最容易被忽视的三个坑:坐标系混用、marker 的 ID 类型写错、图标路径不规范——这三样一旦叠加,就会导致开发工具里一切正常,一到真机就全面崩盘。调试时,第一时间去检查 console 里有没有报 marker not found 或 invalid coordinate,而不是在那儿反复改样式。
