uni-app农场地图——高德 JS API 实现全解析(天地图影像作为layers)

1. 适用场景

面向 国内 App(uni-app + renderjs) 的农场地图:

  • 展示农场地块多边形、阀门/网关设备点
  • 手绘圈地、删除地块、点击地块拉设备列表
  • 安装设备时在地图上选址(GCJ02)
  • 长按设备调整安装位置

2. 为什么在 uni-app 里必须用 renderjs?

Vue 逻辑层运行在 App 的 JS 引擎里,不能直接操作 WebView 里的 DOM。高德 AMap.Map 必须跑在浏览器环境。

因此采用 双 Script 分层:

模板桥接:

javascript 复制代码
<view :prop="propList" :change:prop="mapView.receiveAllProps" />

receiveAllProps 是 renderjs 侧的唯一入口,根据 editModedrawStatusisAddDevice 等切换地图行为。

3. 与父页面的数据契约(allProps

index.vue 通过 updateAllPropsData 推送:

字段 含义
farmFloorData 地块列表(坐标已在父层转为地图可用格式)
valve 当前地块设备列表
centerPoint 农场中心 [lng, lat]
drawStatus 2 进入手绘地块
editMode 1 正常 / 3 删除地块
isAddDevice 是否开启安装选址
showScale / showGeolocation 控件显隐

向父组件抛出的事件(与 Mapbox 版一致):

  • polygonData --- 手绘完成坐标(GCJ02)
  • valveMarkerClick / valvePositionUpdate
  • positionSelected --- 安装选址
  • handleDeviceListByZone / deleteFloor / updateFloorData

设计要点:地图组件只做「渲染 + 交互」,农场/设备业务仍在 index.vue

4. 坐标系策略(高德方案的关键)

  • 接口、uni 定位、addFarm:GCJ-02
  • 高德地图实例内部:也按 GCJ-02 使用(与国标一致,显示上最省事)
  • 父页面 getAllFloor 时会把接口 GCJ02 转成 WGS84 再传给地图

安装选址时,PositionPicker 返回的 positionResult.position 在代码里又做了一次:

javascript 复制代码
coordtransform.wgs84togcj02(positionResult.position.lng, positionResult.position.lat)

统一坐标系标准:上报父组件、写库一律 GCJ02。

定位控件里则将高德定位结果 gcj02towgs84panTo,用于在地图上标蓝点。

5. 地图初始化:高德引擎 + 非高德底图

initAMap() 并非默认高德卫星,而是 自定义 TileLayer 叠瓦片:

  1. 天地图影像 img_w(WMTS,TILEMATRIXSET=w
  2. Mapbox 卫星(AMap.TileLayer,默认 visible: false
  3. 天地图注记 cia_w
javascript 复制代码
map = new AMap.Map("container", {
  viewMode: '3D',
  zoom: 17,
  center: centerPointData,
  layers: [tiandituImgLayer, mapboxSatelliteLayer, tiandituRoadLayer],
})

缩放分级切换(zoomchange):

  • zoom <= 17.5:天地图影像
  • zoom > 17.5:隐藏天地图,显示 Mapbox 卫星

思路:日常用合规国内影像,放大看田块细节时用高清卫星。引擎仍是高德,底图可插拔。

还需配置:

javascript 复制代码
window._AMapSecurityConfig = { securityJsCode: '...' }
AMapLoader.load({ key, version: '2.0', plugins: [...] })

插件包括 PolygonEditorGeolocationScale 等。

6. 功能实现思路(按模块)

6.1 地块展示 initPolygon

  1. map.remove(polygons) 清旧多边形
  2. 遍历 FloorListcoordinatespath,首尾闭合
  3. new AMap.Polygon({ path, fillOpacity, strokeColor, extData })
  4. getBounds().getCenter() 得到中心,再 AMap.Marker 显示地块名
  5. 绑定 polygon.on('click')handlePolygonClick

删除模式 edit === 3:红色虚线边框、加粗 stroke,提高可点区域。

选中逻辑:setOptions 改填充/描边,隐藏当前地块名称 Marker,调用 handleDeviceListByZone

6.2 手绘地块 drawPolygon

  1. map.on('click') 采点 → polygonSaveTemp
  2. 每点一个 AMap.Marker(红点)
  3. < 3 点:AMap.Polyline 虚线;>= 3 点:AMap.Polygon 预览
  4. 页面 DOM #point-next / #point-cancel(在 index.vue)完成/撤销
  5. 完成 → callMethod('drawFloor', polygonSaveTemp) → 逻辑层 wgs84togcj02 → emit('polygonData')

撤销时用 map.clearMap() 再重绘临时图形(注意会清掉其它覆盖物,需之后 initPolygon 恢复)。

6.3 设备点 initValves / addMarker

  • AMap.Marker + 自定义 content HTML(图标、状态角标、灌溉动画)
  • 点击 → onValveMarkerClick
  • 长按 3s → 进入位置调整(需处理与 dragstart/zoomstart 冲突,代码里用 document 级 touch 监听取消误触)

6.4 安装选址 initPositionPicker

动态加载 AMapUI + misc/PositionPicker

javascript 复制代码
positionPicker = new PositionPicker({ mode: 'dragMap', map })
positionPicker.start()
positionPicker.on('success', ...) // → onPositionSelected(GCJ02)

mode: 'dragMap':拖地图、中心不动

进入选址时 marker.setClickable(false),避免误点设备。

6.5 定位

AMap.Geolocation + complete 事件更新 locationMarkererror → 逻辑层 Toast。

7. 高德方案优缺点

优点

  • 国内文档、示例、社区成熟
  • GCJ02 与国标、微信/高德定位一致,少一层转换错误
  • PolygonMarkerPositionPicker 封装高,开发快
  • 可用 PolygonEditor 做顶点编辑(插件已引入)

缺点

  • 强依赖高德 Key + 安全密钥,商业条款与配额需单独评估
  • 自定义底图(天地图 + Mapbox)仍绑在高德引擎上,架构略「拧」
  • clearMap()、多实例 Editor 容易造成状态难控
  • App WebView 里同时拉高德 UI、AMapUI、外部瓦片,包体与网络请求较多

8. 落地检查清单

  • Key / securityJsCode / 域名白名单(H5)/ 包名(App)
  • 确认存入地图的坐标系与接口一致(GCJ02)
  • 手绘完成、选址、拖拽提交三条链路都做 GCJ02 输出
  • zoomchange 切换底图时测试 17.5 临界闪烁
  • 删除模式与名称 Marker、polygon 点击去重(FLOOR_POLYGON_CLICK_DEDUP_MS
相关推荐
2501_916008896 小时前
Mac 上生成 AppStoreInfo.plist 文件,App Store 上架
android·macos·ios·小程序·uni-app·iphone·webview
__zRainy__7 小时前
uni-app 全局容器实战系列(四):全局容器动态调用设计
uni-app
2501_916007471 天前
iOS开发中抓取HTTPS请求的完整解决方法与步骤详解
android·网络协议·ios·小程序·https·uni-app·iphone
00后程序员张1 天前
Windows 下怎么生成 AppStoreInfo.plist?不依赖 Xcode 的方法
ide·macos·ios·小程序·uni-app·iphone·xcode
__zRainy__1 天前
uni-app 全局容器实战系列(二):Vite 虚拟模块
windows·uni-app
__zRainy__1 天前
uni-app 全局容器实战系列(一):全局容器的实现
uni-app·vite
安生生申1 天前
uni-app 连接 JDY-31 蓝牙串口模块实践
c语言·前端·javascript·stm32·单片机·嵌入式硬件·uni-app
小离a_a1 天前
uniapp小程序封装圆环显示比例数据
android·小程序·uni-app
__zRainy__1 天前
uni-app 全局容器实战系列(三):全局 NavBar 和 TabBar 组件设计
uni-app