当前位置: 首页 > news >正文

别再到处找教程了!手把手教你用uni-app的map组件搞定高德地图定位、撒点和画图

别再到处找教程了!手把手教你用uni-app的map组件搞定高德地图定位、撒点和画图

每次开发地图功能时,你是不是总在各大论坛和博客间来回切换,试图拼凑出一个完整的解决方案?作为过来人,我完全理解这种痛苦。本文将带你一次性解决uni-app中高德地图集成的所有核心问题,从基础配置到高级功能实现,让你彻底告别碎片化学习。

1. 高德地图Key申请与基础配置

在开始编码前,我们需要先获取高德地图的开发者Key。这个Key相当于使用高德地图服务的通行证,没有它,所有地图功能都无法正常工作。

获取Key的具体步骤:

  1. 访问高德开放平台官网并注册开发者账号
  2. 进入"控制台"→"应用管理"→"创建新应用"
  3. 为应用添加"Web服务"和"Web端(JS API)"两个平台
  4. 提交后即可获取到专属的API Key

拿到Key后,我们需要在uni-app项目中配置它。打开manifest.json文件,在"App模块配置"中找到"Map(地图)",勾选"高德地图"并填入你的Key:

"maps": { "amap": { "key": "你的高德地图Key" } }

注意:高德地图的Key有调用次数限制,个人开发者每天有3000次免费调用额度,超出后需要付费。开发阶段建议开启"测试模式"以避免不必要的消耗。

2. 基础地图展示与定位功能实现

让我们从最基础的地图展示开始。uni-app内置的map组件已经封装了高德地图的大部分功能,使用起来非常方便。

基础地图组件代码:

<template> <view> <map id="myMap" style="width: 100%; height: 80vh" :latitude="latitude" :longitude="longitude" :show-location="true" ></map> </view> </template> <script> export default { data() { return { latitude: 39.90469, // 默认北京中心坐标 longitude: 116.40717 } }, mounted() { this.initMap() }, methods: { initMap() { this.mapContext = uni.createMapContext('myMap', this) } } } </script>

这段代码已经可以展示一个基础地图,但还没有实现真正的定位功能。要实现定位,我们需要调用uni-app的定位API:

methods: { getLocation() { uni.getLocation({ type: 'gcj02', // 必须使用gcj02坐标系 success: (res) => { this.latitude = res.latitude this.longitude = res.longitude this.mapContext.moveToLocation({ latitude: res.latitude, longitude: res.longitude }) }, fail: (err) => { console.error('定位失败:', err) uni.showToast({ title: '定位失败,请检查权限设置', icon: 'none' }) } }) } }

常见问题排查:

  • 定位失败:检查是否已获取定位权限,iOS需要在manifest.json中配置权限描述
  • 坐标偏移:确保使用gcj02坐标系,这是高德地图使用的标准
  • 真机无效:部分Android手机需要开启GPS才能准确定位

3. 高级地图功能实现

3.1 撒点功能实现

撒点(标记位置)是地图应用的核心功能之一。uni-app的map组件通过markers属性实现这一功能。

完整撒点实现代码:

data() { return { markers: [] } }, methods: { addMarkers() { // 示例数据 - 实际项目中可能来自API const locations = [ {id: 1, latitude: 39.91469, longitude: 116.40717, title: '王府井'}, {id: 2, latitude: 39.91569, longitude: 116.40817, title: '故宫'}, {id: 3, latitude: 39.91669, longitude: 116.40917, title: '天安门'} ] this.markers = locations.map(item => ({ id: item.id, latitude: item.latitude, longitude: item.longitude, title: item.title, iconPath: '/static/location.png', // 自定义图标 width: 30, height: 30, callout: { // 点击标记时显示的气泡 content: item.title, color: '#ffffff', fontSize: 14, borderRadius: 10, bgColor: '#007AFF', padding: 5, display: 'ALWAYS' } })) } }

自定义标记图标技巧:

  1. 准备透明背景的PNG图标,建议尺寸60×60像素
  2. 将图标放入项目的static目录
  3. 在marker配置中指定iconPath属性
  4. 通过widthheight调整显示大小

3.2 绘制路线与区域

绘制路线实现:

data() { return { polyline: [] } }, methods: { drawRoute() { this.polyline = [{ points: [ {latitude: 39.91469, longitude: 116.40717}, {latitude: 39.91569, longitude: 116.40817}, {latitude: 39.91669, longitude: 116.40917} ], color: '#00BFFF', // 线条颜色 width: 6, // 线条宽度 dottedLine: false, // 是否虚线 arrowLine: true // 是否带箭头 }] } }

绘制区域实现:

data() { return { polygons: [] } }, methods: { drawArea() { this.polygons = [{ points: [ {latitude: 39.91469, longitude: 116.40717}, {latitude: 39.91569, longitude: 116.40817}, {latitude: 39.91669, longitude: 116.40917} ], strokeWidth: 2, // 边框宽度 strokeColor: '#FF0000', // 边框颜色 fillColor: '#00BFFF33' // 填充颜色(带透明度) }] } }

重要提示:绘制区域至少需要3个点才能形成闭合图形,否则会报错。

4. 性能优化与高级技巧

4.1 地图性能优化

随着标记点和图形增多,地图性能可能会下降。以下是一些优化建议:

  • 分批加载:当有大量标记点时,不要一次性全部加载
  • 按需渲染:只显示当前视野范围内的标记点
  • 简化图形:减少多边形和折线的点数
  • 使用图片覆盖:对于复杂图形,考虑使用图片覆盖代替矢量绘制

示例代码:分批加载标记点

methods: { loadMarkersInView() { this.mapContext.getRegion({ success: (res) => { const visibleMarkers = this.allMarkers.filter(marker => marker.latitude >= res.southwest.latitude && marker.latitude <= res.northeast.latitude && marker.longitude >= res.southwest.longitude && marker.longitude <= res.northeast.longitude ) this.markers = visibleMarkers } }) } }

4.2 坐标转换处理

高德地图使用的是GCJ-02坐标系,而GPS设备通常返回WGS-84坐标。如果你需要处理原始GPS数据,必须进行坐标转换。

坐标转换工具函数:

// 坐标转换工具函数 function transformFromWGSToGCJ(latitude, longitude) { const a = 6378245.0 const ee = 0.00669342162296594323 if (outOfChina(latitude, longitude)) { return {latitude, longitude} } let dLat = transformLat(longitude - 105.0, latitude - 35.0) let dLon = transformLon(longitude - 105.0, latitude - 35.0) const radLat = latitude / 180.0 * Math.PI let magic = Math.sin(radLat) magic = 1 - ee * magic * magic const sqrtMagic = Math.sqrt(magic) dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * Math.PI) dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * Math.PI) return { latitude: latitude + dLat, longitude: longitude + dLon } } function outOfChina(lat, lon) { return lon < 72.004 || lon > 137.8347 || lat < 0.8293 || lat > 55.8271 } function transformLat(x, y) { let ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x)) ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0 ret += (20.0 * Math.sin(y * Math.PI) + 40.0 * Math.sin(y / 3.0 * Math.PI)) * 2.0 / 3.0 ret += (160.0 * Math.sin(y / 12.0 * Math.PI) + 320 * Math.sin(y * Math.PI / 30.0)) * 2.0 / 3.0 return ret } function transformLon(x, y) { let ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x)) ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0 ret += (20.0 * Math.sin(x * Math.PI) + 40.0 * Math.sin(x / 3.0 * Math.PI)) * 2.0 / 3.0 ret += (150.0 * Math.sin(x / 12.0 * Math.PI) + 300.0 * Math.sin(x / 30.0 * Math.PI)) * 2.0 / 3.0 return ret }

4.3 自定义地图样式

高德地图支持自定义地图样式,让你的应用与众不同。你可以通过以下步骤实现:

  1. 访问高德地图的自定义样式平台创建新样式
  2. 获取样式ID后,在uni-app中通过map组件的setting属性应用

示例代码:

<map id="myMap" style="width: 100%; height: 80vh" :latitude="latitude" :longitude="longitude" :setting="mapSetting" ></map>
data() { return { mapSetting: { style: 'amap://styles/你的样式ID' // 从高德地图自定义平台获取 } } }

5. 实战案例:门店地图展示系统

让我们把这些知识点整合到一个实际案例中 - 一个门店地图展示系统。这个系统需要展示多个门店位置,支持路线规划和服务区域划分。

核心功能实现:

  1. 门店数据加载与展示
async loadStores() { try { const res = await uni.request({ url: '你的API地址/stores', method: 'GET' }) this.stores = res.data this.renderStoreMarkers() } catch (error) { console.error('加载门店数据失败:', error) uni.showToast({ title: '加载门店数据失败', icon: 'none' }) } }, renderStoreMarkers() { this.markers = this.stores.map(store => ({ id: store.id, latitude: store.latitude, longitude: store.longitude, title: store.name, iconPath: '/static/store.png', width: 40, height: 40, callout: { content: `${store.name}\n营业时间:${store.businessHours}`, color: '#333333', fontSize: 12, borderRadius: 4, bgColor: '#FFFFFF', padding: 5, display: 'ALWAYS' } })) }
  1. 路线规划功能
methods: { planRoute(start, end) { // 使用高德地图路径规划API uni.request({ url: 'https://restapi.amap.com/v3/direction/driving', data: { key: '你的高德地图Key', origin: `${start.longitude},${start.latitude}`, destination: `${end.longitude},${end.latitude}`, strategy: 0 // 0:速度优先 }, success: (res) => { if (res.data.status === '1') { const path = res.data.route.paths[0] this.drawRoute(path.steps) } } }) }, drawRoute(steps) { const points = [] steps.forEach(step => { const polyline = step.polyline.split(';') polyline.forEach(point => { const [longitude, latitude] = point.split(',') points.push({ latitude: parseFloat(latitude), longitude: parseFloat(longitude) }) }) }) this.polyline = [{ points: points, color: '#1890FF', width: 6, arrowLine: true }] } }
  1. 服务区域可视化
methods: { showServiceArea(storeId) { const store = this.stores.find(s => s.id === storeId) if (store && store.serviceArea) { this.polygons = [{ points: store.serviceArea, strokeWidth: 2, strokeColor: '#FF6A00', fillColor: '#FF6A0033' }] // 调整地图视野以包含整个服务区域 this.mapContext.includePoints({ points: store.serviceArea, padding: [50, 50, 50, 50] }) } } }

在实际项目中,我遇到过几个值得注意的问题:首先是地图初始化时的性能问题,特别是在低端安卓设备上,解决方案是延迟加载非关键地图元素;其次是坐标转换的精度问题,建议使用官方提供的转换服务而非纯前端计算;最后是标记点过多时的卡顿问题,采用聚类标记技术可以有效改善。

http://www.jsqmd.com/news/717193/

相关文章:

  • 【Python电商实时风控决策实战指南】:20年专家亲授3大高并发场景下的毫秒级决策引擎搭建秘籍
  • EFLA注意力机制:优化挑战与训练策略解析
  • 突破AI对话长度限制:构建无限上下文记忆系统的工程实践
  • LLM命名风格对Grimdark叙事影响的实验研究
  • 第15集:时序数据库选型实战!InfluxDB vs TDengine vs Prometheus 到底选谁
  • 构建私有化AI编程助手:codex-server-bridge桥接器设计与实战
  • Bilibili评论数据采集神器:一键获取完整评论信息,轻松实现数据自由
  • NoFences:免费开源的Windows桌面分区神器,终极解决图标杂乱问题
  • 突破AI上下文限制:chatgpt-infinity实现长文本自动化处理
  • 万亿参数模型Ring-1T:MoE架构与强化学习突破
  • 深入解析nococli:基于Node.js的零配置CLI工具设计与实现
  • gptree:高效向AI助手提供项目上下文的命令行工具
  • 单变量时间序列预测:网格搜索优化基础方法
  • Dalaix:一键本地部署大语言模型的Windows桌面工具
  • 为什么你的浏览器视频下载总是失败?Video DownloadHelper伴侣应用来帮你
  • 量化模型优化器选型指南与性能对比
  • 大型语言模型知识召回瓶颈解析与优化策略
  • 别再纠结了!从零到一,手把手教你根据项目需求选对监控工具(Zabbix vs Prometheus实战对比)
  • Claude Code:AI智能体如何重塑开发工作流,从命令行到智能协作
  • ARM开发板硬件接口与寄存器配置实战指南
  • 揭秘SharePoint在线评分系统的奥秘
  • 告别环境变量困扰:手把手教你将gcc-arm-8.3工具链永久添加到Linux系统路径(含多用户配置)
  • 智能家居监控技能部署指南:从规则引擎到自动化联动
  • UnityExplorer终极指南:如何在游戏中实时调试和修改Unity应用
  • Podinfo:云原生微服务样板间,从部署到集成的完整实践指南
  • OK Skills:AI编程代理的模块化技能库,提升开发效率与自动化水平
  • 从绕线机到3D打印机:伺服电机三种控制模式(脉冲/模拟/通信)的实战场景全解析
  • 详解C++编程中的变量相关知识
  • 37岁程序员转行大模型:挑战与机遇并存,你需要知道的关键策略
  • LVGL 启动流程全解析:RT-Thread 下的界面渲染链路