web技術分享| 【高德地圖】實現自定義的軌跡回放
實現(軌跡回放)方式有兩種:
- 第一種是使用
JS API
和AMap.PolyLine
(折線)等圖形配合實現。 - 第二種是使用
JS API
和AMapUI 元件庫
配合使用,利用PathSimplifier
( 軌跡展示 元件)繪製出行動軌跡。
方案選擇
以上兩種實現方式我們可以根據兩個 因素 來決定哪一種更加適合自己: 節點數量 的多少、 排布的密集度 。
前者適合節點數量較少,排布比較稀鬆,例如,計程車軌跡回放,計程車行駛速度快,週期上報的時間也會相對較長。後者更加針對節點數量巨大、排布密集的路徑,按秒記錄位置的飛機行進軌跡,精細的地理邊界等等。
實現流程
無論選擇兩種方式,我們都需要先收集到客戶端上報的資訊,這些資訊可以自定義,通常我們會包含: 經緯度、速度、逆編碼之後的地理位置、方向、海拔 等基本地理資訊,同時我們也可以加入一些 自定義 的資訊,例如:人員資訊(頭像暱稱等)、出行資訊(訂單等)。
實現的流程:
- 客戶端按(時間)週期上報地理資訊以及自定義資訊。
- 服務端按時間軸儲存客戶上報的資訊。
- 按(時間等)條件查詢出使用者的軌跡,並通過簡化演算法去除一部分節點(例如,節點距離十分微小、或者多個點都在同一條直線、3點之間,其中一點略有偏差無法繪製成直線等等),最終獲得適合繪製的路徑(陣列)。
- 根據路徑去繪製使用者的行動軌跡。
路徑簡化演算法(可選)
客戶端上報的資料是按時間週期上報的,也就是說每個時間都對應了一個經緯度,經緯度在地圖上就是一個又一個點,將這些點連線時,我們會得到 N 多條折線,為了繪製的軌跡更加美觀,行動路線更加明確平滑,通常我們需要一個演算法來簡化折線。
例如:
-
A
點和B
點,兩者距離不到1
畫素,則可以去掉B
點,只留A
點。 -
A
,B
,C
三點在一條直線上,或者,B
點僅僅稍微偏離A
點和C
點構成的線段,那麼B
點就可以去掉。
這裡官方也推薦了一種演算法庫 simplify.js
供大家參考,這裡不做過多的闡述。
實現示例
車輛軌跡回放
這裡我們使用第一種方式來實現 - 利用 JS API
和 AMap.PolyLine
。
實現原理:
- 在地圖上繪製 車輛標記 (
AMap.Marker
)。 - 利用
AMap.PolyLine
繪製出兩條軌跡: 歷史軌跡 和 駕駛途徑過的軌跡 ,以顏色區分。 - 按照一定的速度使車輛前進,並監聽
Maker
移動的事件,在事件回撥中,將車輛(Marker
)位置設定為地圖中心點,給使用者視覺主觀上一種車輛在前進的感覺,同時延長 駕駛途徑過的軌跡 。 -
對於實現場景比較複雜的,需要進行自定義處理的比如:
- 檢視每個節點的資料 ,我們可以把每個節點給繪製出來,節點被點選時顯示該節點的資料。
- 移動倍速播放 ,首先按上報的時間間隔來播放,選擇倍速之後,改變
MarKer
移動的duration
。 - 其他自定義。
自定義 API
我們可以讓車輛:
- 開始移動
- 暫停移動
- 恢復移動
- 停止移動
程式碼示例
AMap.plugin('AMap.MoveAnimation', function(){ var marker, lineArr = [[116.478935,39.997761],[116.478939,39.997825],[116.478912,39.998549],[116.478912,39.998549],[116.478998,39.998555],[116.478998,39.998555],[116.479282,39.99856],[116.479658,39.998528],[116.480151,39.998453],[116.480784,39.998302],[116.480784,39.998302],[116.481149,39.998184],[116.481573,39.997997],[116.481863,39.997846],[116.482072,39.997718],[116.482362,39.997718],[116.483633,39.998935],[116.48367,39.998968],[116.484648,39.999861]]; var map = new AMap.Map("container", { resizeEnable: true, center: [116.397428, 39.90923], zoom: 17 }); marker = new AMap.Marker({ map: map, position: [116.478935,39.997761], icon: "http://a.amap.com/jsapi_demos/static/demo-center-v2/car.png", offset: new AMap.Pixel(-13, -26), }); // 繪製歷史軌跡 var polyline = new AMap.Polyline({ map: map, path: lineArr, showDir:true, strokeColor: "#28F", //線顏色 // strokeOpacity: 1, //線透明度 strokeWeight: 6, //線寬 // strokeStyle: "solid" //線樣式 }); // 駕駛途徑過的軌跡 var passedPolyline = new AMap.Polyline({ map: map, strokeColor: "#AF5", //線顏色 strokeWeight: 6, //線寬 }); // 監聽車輛移動事件 marker.on('moving', function (e) { // 延長駕駛途徑過的軌跡 passedPolyline.setPath(e.passedPath); // 將車輛位置設定為地圖中心點 map.setCenter(e.target.getPosition(),true) }); map.setFitView(); // 開始移動 window.startAnimation = function startAnimation () { marker.moveAlong(lineArr, { // 每一段的時長 duration: 500,//可根據實際採集時間間隔設定 // JSAPI2.0 是否延道路自動設定角度在 moveAlong 裡設定 autoRotation: true, }); }; // 暫停移動 window.pauseAnimation = function () { marker.pauseMove(); }; // 恢復移動 window.resumeAnimation = function () { marker.resumeMove(); }; // 停止移動 window.stopAnimation = function () { marker.stopMove(); }; });
參考連結: http://lbs.amap.com/demo/jsapi-v2/example/marker/replaying-historical-running-data
飛機航班的軌跡回放
使用 JS API
和 AMapUI 元件庫
配合使用,利用 PathSimplifier
( 軌跡展示 元件)繪製出行動軌跡,這種方案比較簡單,只需要進行一些配置即可,例如說方案一中的倍速播放就需要計算,同時還存在不能動態改變倍速的弊端,但是方案二卻不會存在。
實現原理:
- 在地圖上繪製 飛機標記 (
AMap.Marker
)。 - 利用
AMap.PolyLine
繪製出兩條軌跡: 歷史軌跡 和 駕駛途徑過的軌跡 ,以顏色區分。 - 配置軌跡的顏色,動畫的速度等等。
- 對於實現場景比較複雜的,需要進行自定義處理的,可以在
PathSimplifier
提供的回撥中進行配置及處理。
示例程式碼
//載入PathSimplifier,loadUI的路徑引數為模組名中 'ui/' 之後的部分 AMapUI.load(['ui/misc/PathSimplifier'], function(PathSimplifier) { if (!PathSimplifier.supportCanvas) { alert('當前環境不支援 Canvas!'); return; } //啟動頁面 initPage(PathSimplifier); }); function initPage(PathSimplifier) { //建立元件例項 var pathSimplifierIns = new PathSimplifier({ zIndex: 100, map: map, //所屬的地圖例項 getPath: function(pathData, pathIndex) { //返回軌跡資料中的節點座標資訊,[AMap.LngLat, AMap.LngLat...] 或者 [[lng|number,lat|number],...] return pathData.path; }, getHoverTitle: function(pathData, pathIndex, pointIndex) { //返回滑鼠懸停時顯示的資訊 if (pointIndex >= 0) { //滑鼠懸停在某個軌跡節點上 return pathData.name + ',點:' + pointIndex + '/' + pathData.path.length; } //滑鼠懸停在節點之間的連線上 return pathData.name + ',點數量' + pathData.path.length; }, renderOptions: { //軌跡線的樣式 pathLineStyle: { strokeStyle: 'red', lineWidth: 6, dirArrowStyle: true } } }); //這裡構建兩條簡單的軌跡,僅作示例 pathSimplifierIns.setData([{ name: '軌跡0', path: [ [100.340417, 27.376994], [108.426354, 37.827452], [113.392174, 31.208439], [124.905846, 42.232876] ] }, { name: '大地線', //建立一條包括500個插值點的大地線 path: PathSimplifier.getGeodesicPath([116.405289, 39.904987], [87.61792, 43.793308], 500) }]); //建立一個巡航器 var navg0 = pathSimplifierIns.createPathNavigator(0, //關聯第1條軌跡 { loop: true, //迴圈播放 speed: 1000000 }); navg0.start(); }
參考連結: http://lbs.amap.com/demo/amap-ui/demos/amap-ui-pathsimplifier/index
- 不要在 Python 中使用迴圈,這些方法其實更棒!
- 分享 6 個 Vue3 開發必備的 VSCode 外掛
- 微服務架構的外部 API 整合模式
- 前端該如何優雅地 Mock 資料
- 微服務架構的通訊設計模式
- 我做了一個線上白板(二)
- 3 款非常實用的 Node.js 版本管理工具
- 636. 函式的獨佔時間 : 簡單棧運用模擬題
- TCP 學習筆記(三) 可靠傳輸
- 一文讀懂微服務架構的分解設計
- Python中常用最神祕的函式! lambda 函式深度總結!
- 技術分享| 小程式實現音影片通話
- Birdseye 極其強大的Python除錯工具
- Android技術分享| 影片通話開發流程(一)
- 細胞影象資料的主動學習
- React報錯之Cannot find name
- 智慧合約安全——私有資料訪問
- 30 個數據工程必備的Python 包
- 萬字長文Python面試題,建議先收藏
- 6個可解釋AI (XAI)的Python框架推薦