高德地图绘制 GPX 路径,gpx 文件详解
重要!
高德地图 js api 文档: https://lbs.amap.com/api/javascript-api-v2/documentation
你所有需要知道的关于 AMap 的所有对象,及其属性、方法、事件都在这里面写明白了。
.gpx
文件是在分享地图路径时最常用的一种数据格式。里面包含了路径点的相关信息,每个点还有可能拥有自己的时间、距离等信息。
一直想自己导出自己的 gpx 路线,然后导入到地图中查看这个路线的具体信息,今天细致看了下,大体找到了方法,分享下。
因为对高德地图的操作已经很熟了,所以再看官方的文档就很轻松,不熟的可以看看我以前关于高德地图的一些文章。
Demo 页面: http://kylebing.cn/tools/map/#/gpx/gpx-viewer
我要实现的结果是类似这样的:
目前是这样的,当然日后会优化。
一、试验
最开始的时候我就用描点的方式显示,结果显示了4000多个点,卡,显示成了这样。
是不是很有立体感,因为这是卡片的堆叠,放大后是这样
显然,这样做是不合适的。我提了个工单给官方,官方给我的回复是:
我看了下这个例子,确实是我需要的,开整。
二、在地图上绘制曲线
先看官方的例子
例子: https://lbs.amap.com/demo/javascript-api-v2/example/overlayers/polyline-draw
官方 API 文档: https://lbs.amap.com/api/javascript-api-v2/documentation#polyline
查看官方文档,关于 AMap.Polyline
的参数如下,具体的请查看官方文档:
我给整理了下可能的参数:
let polyline = new AMap.Polyline({
path: ptArray, // Array<[number, number]>
isOutline: true,
outlineColor: '#ffeeff', // 路线边框颜色
borderWeight: 3, // 路线边框宽度
strokeColor: "#3366FF", // 路线颜色
strokeOpacity: 1, // 路线透明度
strokeWeight: 6, // 路线宽度
strokeStyle: "solid", // solid | dashed
strokeDasharray: [10, 5],// 虚线间隔
lineJoin: 'round', // 折线拐点的绘制样式,默认值为'miter'尖角,其他可选值:'round'圆角、'bevel'斜角
lineCap: 'round', // 折线两端线帽的绘制样式,默认值为'butt'无头,其他可选值:'round'圆头、'square'方头
zIndex: 50,
showDir: true, // 显示方向箭头, 宽度 > 6 时有效
geodesic: false, // 是否显示大地线
extraData: {} // any
})
map.add([polyline]);
map.setFitView();
细致说一下,这里 path
的参数类型是 Array<[lng, lat]>
,如:
[
["117.1028857", "36.6956868"],
["117.1028860", "36.6956897"],
["117.1028859", "36.6956933"],
["117.1028862", "36.6956977"]
]
结果就是这样的,能看到路径发生了偏移,这个我们在后面进行处理。
三、获取 gpx 数据
现在我们需要的就只是获取到 gpx 文件中的 gps 坐标点的数据了。
比如从我高驰 Apex 手表中导出的一条 gpx 的数据内容是这样的:
<?xml version="1.0" encoding="UTF-8"?>
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gpxdata="http://www.cluetrust.com/XML/GPXDATA/1/0" xmlns="http://www.topografix.com/GPX/1/0" xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd http://www.cluetrust.com/XML/GPXDATA/1/0 http://www.cluetrust.com/Schemas/gpxdata10.xsd" creator="Coros Wearables">
<metadata>
<time>2023-11-18T12:08:29Z</time>
<link href="https://www.coros.com">COROS</link>
</metadata>
<trk>
<name>济南市 徒步</name>
<type>running</type>
<trkseg>
<trkpt lat="36.7426527" lon="117.0671413">
<ele>18</ele>
<time>2023-11-18T12:08:53Z</time>
<extensions>
<heartrate>96</heartrate>
<distance>13</distance>
</extensions>
</trkpt>
<trkpt lat="36.7426560" lon="117.0671390">
<ele>18</ele>
<time>2023-11-18T12:08:54Z</time>
<extensions>
<heartrate>96</heartrate>
<distance>13</distance>
</extensions>
</trkpt>
...
1. 分析 gpx 文件内部的数据格式
能看到 gpx 文件不过是个 xml 文件,并且里面有 lng
lat
数据,还有高度信息 ele
。
直到我把路径画出来我也不知道这个 ele
是什么意思,搜了下,结果它是 Elevation 的意思,就是海拔的意思:
能看到它的内部结构是这样的:
https://www.jsont.run/
2. 添加 xml 转义工具
在项目中添加 xml 转义工具,这里用 fast-xml-parser
yarn add fast-xml-parser
# 或
npm i fast-xml-parser
3. 转义数据
页面中 import 它
import {XMLParser, XMLBuilder, XMLValidator} from "fast-xml-parser"
使用它
// 新建 parser
let xmlParser = new XMLParser({
ignoreAttributes: false, // 读取xml节点的属性值,这里需要读取节点属性值,因为经纬度在那上面
attributeNamePrefix : "_"
})
let xmlObj = xmlParser.parse(xmlContentString)
这样的结果就是
单点数据结构是:
{
"ele": 18,
"time": "2023-11-18T12:08:53Z",
"extensions": {
"heartrate": 96,
"distance": 13
},
"_lat": "36.7426527",
"_lon": "117.0671413"
}
这样我们目前需要的数据就是 _lat
_lon
,其它数据可以在日后优化功能的时候使用。
4. 生成需要的 path array
let pointers = this.xmlObj.gpx.trk.trkseg.trkpt
let pathPointers = pointers.map(item => [item._lon, item._lat])
注意: 当然,这里摘取数据点的操作是非常死的,如果想兼容其它 gpx 文件,还需要进一步作相关的判断操作。
再继续第二步的操作,将这值传入就能绘制出路线了。
我的页面中是通过选择 gpx 文件的方式传入的数据,具体如何实现的可以看我已开源的内容。
四、处理偏移量
1. 固定偏移量
关于地图偏移量的问题,我也不知道是怎么产生的。这里只讲一下自己最直接的处理方式:就是将每个点都偏移到当前地图正常的位置。
上面那个 path 值,也就是 Array<[lng, lat]>
还可以是 Array<AMap.LngLat>
,而 AMap.LngLat
就可以进行偏移距离的操作:
let pointers = this.xmlObj.gpx.trk.trkseg.trkpt
let pathPointers = pointers.map(item => {
let lnglat = new AMap.LngLat(item._lon, item._lat)
return lnglat.offset(535,40) // E,N 向东,向北移动距离,单位:米
})
这个偏移量是慢慢试出来的,这样就显示正常了。
比如我载入了两条路线,显示正常:
2. 动态偏移量
从网友那里要了一个 .gpx
文件,再对比我的,直接放到地图上都不会完美的契合。
应该是每个软件、每个硬件设备生成的 .gpx
文件的 gps 都不一样,多少有点偏差。
所以为了解决这个问题,我把向北向东的偏移量改成了可设置的,只需要载入路径之后调整这个数值就可以,结果是实时可见的。
操作中就是这样,很方便。
五、我最终实现的
我目前最终实现的效果是这样:
- 起始|终止 点都用特殊图标展示
- 每隔多少个数据点展示一个Marker,目前显示的是当前点的时间
- 可隐藏|显示图上的 Marker
- 可隐藏|显示路径
- 添加路径的长度、总用时
这里只简单说一下实现过程,具体的实现可以去 Github 上看源码:
https://github.com/KyleBing/map/blob/master/src/page/gpx/GpxViewer.vue文章来源:https://www.toymoban.com/news/detail-805841.html
-
起始|终止 点都用特殊图标展示
将 gpx 路径点的[0]
和[length-1]
两个点作特殊标记,就是标记它是 start 和 end 点,放置在AMap.Marker.extData
中,具体看官方文档,在新建AMap.Marker
的时候有个参数是extData
可以传递附加的数据,它的类型是any
,所以你传什么都可以。在展示点的时候,判断一下是否为特殊点,如果是,就添加特殊的 icon - 每隔多少个数据点展示一个 Marker,目前显示的是当前点的时间。
-
可隐藏|显示图上的 Marker
判断 marker 是否为特殊点,开始和结束的两个点将始终显示。这里用到的是AMap.Marker
的hide()
和show()
方法 -
可隐藏|显示路径
这里用到的是AMap.Polyline
的hide()
和show()
方法 -
路径总用时、长度
用到的是AMap.polyline
的getLength()
方法,返回的是路径的长度,单位是米,这个方法还可以接收一个参数,就是计算路径长度的时候是否考虑地形高度。如果需要就填true
六、演示项目地址:
路书: http://kylebing.cn/tools/map/#/gpx/gpx-viewer
github: https://github.com/KyleBing/map文章来源地址https://www.toymoban.com/news/detail-805841.html
到了这里,关于高德地图绘制 GPX 数据路线的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!