最近幾個月跑了不少步品洛,試用了很多不同的APP树姨,導(dǎo)致軌跡、跑量什么的各自為政桥状,因此萌生了寫個程序把所有跑步的軌跡都畫在一張地圖上的想法。
第一步硝清,先把各個地方能導(dǎo)出軌跡的都導(dǎo)出來辅斟。看了一下.FIT .TPX .GPX中芦拿,以GPX文件結(jié)構(gòu)最簡單士飒,下面就是一段.gpx文件的記錄點格式,于是把軌跡都導(dǎo)成.gpx文件蔗崎。
第二步酵幕,讀取GPX文件數(shù)據(jù)
人生苦短,我用Python——用Python讀入這些GPX軌跡信息缓苛,處理后再畫在地圖上芳撒,應(yīng)該是最容易的做法了。Python本身接近自然語言未桥,豐富的第三方庫讓寫程序就像用英文和計算機(jī)對話一樣笔刹。
直接使用Python自帶的xml庫完成讀取,注意要剔除lat和lon為0的數(shù)據(jù)點冬耿,因為GPX是用這種方法來標(biāo)記暫停的舌菜。
import xml.dom.minidom as xdom
gpxPath = 'test.gpx'
dom_tree = xdom.parse(gpxPath)
collection = dom_tree.documentElement
trkpts = collection.getElementsByTagName("trkpt")
lats, lons = [], []
for trkpt in trkpts:
lat = trkpt.getAttribute("lat")
lon = trkpt.getAttribute("lon")
if lat=='0' or lon=='0':
continue
lats.append(float(lat))
lons.append(float(lon))
datas = {'lat': lats, 'lon': lons}
第三步,將數(shù)據(jù)畫在地圖上
前面進(jìn)行的一切順利亦镶,沒想到在畫地圖的時候卡住了日月。
建筑師出身袱瓮,對圖面的要求不能太低。而Python的地圖庫里面幾乎沒有好看的地圖爱咬,而且使用起來都頗為麻煩尺借。在嘗試了Basemap、Plotly台颠、Folium之后褐望,最終選擇使用高德地圖,方便好用串前。
高德地圖JavaScrip API快速入門
在正式開始開發(fā)地圖應(yīng)用之前,您需要做如下幾步:
- 申請JSAPI的開發(fā)者key
申請地址:http://lbs.amap.com/dev/key - 引入高德地圖JavaScript API文件:
<script type="text/javascript" src="http://webapi.amap.com/maps?v=1.3&key=您申請的key值"></script>
- 創(chuàng)建地圖容器
在頁面body里你想展示地圖的地方創(chuàng)建一個div 容器瘫里,并指定id標(biāo)識:
<div id="container"></div>
- 指定容器大小
按照需要設(shè)定地圖容器的大小,確保大小合適,比如用CSS這樣設(shè)置它:
#container {width:300px; height: 180px; }
接下來要寫個網(wǎng)頁用來讀取本地的數(shù)據(jù)文件荡碾。因為之前已經(jīng)使用Python完成了GPX數(shù)據(jù)讀取谨读,所以先改寫一下,輸出JS可以方便讀取的JSON文件坛吁。
import os
fileDir, fileName = os.path.split(gpxPath)
jsonDir = os.path.join(fileDir, 'jsons')
if not os.path.exists(jsonDir):
os.mkdir(jsonDir)
jsonPath = os.path.join(jsonDir, fileName) + '.json'
with open(jsonPath, 'w') as f:
f.write(json.dumps(datas))
同時為了方便的處理多條數(shù)據(jù)劳殖,把上面Python的部分寫成一個procXml函數(shù),然后在命令行中將要轉(zhuǎn)換的文件作為參數(shù)傳入拨脉。
import sys
def main():
if len(sys.argv) < 2:
print 'Specify the gpx file path'
return
fileList = sys.argv[1:]
for p in fileList:
if os.path.isfile(p):
gpxPath = os.path.abspath(p)
print 'Processing'+str(gpxPath)
try:
procXml(p)
print 'Coresponding JSON file was generated.'
except:
print '=====Somthing was wrong哆姻!====='
if __name__ == '__main__':
main()
保存為gpx2json.py,將從跑步軟件中導(dǎo)出的GPX文件都放在同目錄下的gpxs文件夾中玫膀,然后在命令行中輸入以下命令進(jìn)行批量轉(zhuǎn)換:
python gpx2json.py gpxs/*
軌跡處理完畢后的json文件會放到gpxs/json/下矛缨,馬上就要讀取本地的json文件并調(diào)用高德地圖的API畫軌跡了,已經(jīng)接近完成了呢帖旨。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<script src="https://code.jquery.com/jquery-3.1.1.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>
<script type="text/javascript" src="http://webapi.amap.com/maps?v=1.3&key=cgbvip@gmail.com"></script>
<title>-*- iRunMap -*-</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
<input id="file-upload" type="file" multiple>
<input id ="clear" type="button" value='clear'>
</form>
<div id="container" style="width:1200px;height:800px;">
</div>
<script src="drawPath.js"></script>
</body>
</html>
保存為index.html箕昭。框架已經(jīng)搭好解阅,就差最后的drawPath.js了落竹。
看了一下高德的API,mapStyle選擇dark货抄,黑色的背景地圖非呈稣伲酷炫。為了更清楚的顯示軌跡信息碉熄,直接隱掉路網(wǎng)桨武、建筑等圖層,features設(shè)置為bg(純背景)锈津。用HTML5提供的ObjectURL獲得本地文件的地址呀酸。
'use strict';
var map = new AMap.Map('container', {
zoom: 12,
center: [121, 31],
mapStyle: 'dark',
features: ['bg']
});
$(document).ready(function(){
$('#clear').on('click', (function(){
map.clearMap();
}));
$('#file-upload').on('change', function(){
for(var i=0,f;f=this.files[i];i++){
var fPath = window.URL.createObjectURL(f);
$.getJSON(fPath, function(data){
var lineArr = new Array();
for(var i=0;i<data.lat.length;i++){
lineArr.push(new AMap.LngLat(data.lon[i],data.lat[i]));
}
var polyline =new AMap.Polyline({
path: lineArr,
strokeColor: "#00ff00",
strokeOpacity: 0.5,
strokeWeight: 3,
strokeStyle: "solid",
});
polyline.setMap(map);
});
}
});
});
Duang的一下就完成了!打開文件上傳所有GPX文件琼梆,一直在復(fù)旦大學(xué)和上海西南某高校附近徘徊呢性誉,真是冤家窿吩。
查看源碼