標籤:自己 運行 定時 動態改變 add http try 方向 實現
一、簡單的思路
要實現車輛運行軌跡,我們可能需要一個定時觸發的機制用來更新Marker的位置,除了位置移動,我們可能還需要動態改變車輛的方向,如:
首先,位置移動是最簡單的,關鍵是方向的動態改變如何?,稍作觀察即可看出,汽車的方向總是和路線的切點平行,看來我們得寫個方法用來求路線上任意點的切線了。可能對於有些大神來說這也並不棘手,無非是花點時間寫個演算法而已,但我覺得僅憑我自己的本事可能做不到,所以我打算藉助現有的程式碼程式庫來實現上述的功能。在wpf中,路徑動畫是很常用的,而它正好和這裡的需求相符合,我們是不是能利用它來實現上述的功能呢?
二、路徑動畫demo
部落格園有很多關於wpf路徑動畫的隨筆,如果你還未曾瞭解過,可以看這裡的一篇:http://www.cnblogs.com/zhouyinhui/archive/2007/07/31/837893.html,裡面很詳細的介紹了路徑動畫的使用方法,並且附帶了demo可供下載,我建議先看完這篇隨筆後再往下閱讀。為了方便的在動畫執行過程中獲得運動對象的位置座標和旋轉角度,我選擇了這篇隨筆中介紹的DoubleAnimationUsingPath的方法,我們需要在此基礎上訂閱任意一個Transform執行個體的Changed事件,以便車輛在改變位置時能通知我們:
var translate = new TranslateTransform();var rotate = new RotateTransform();var group = new TransformGroup();translate.Changed += (s, e) =>{
//在這裡擷取小車的位置座標和旋轉角度};
上面的代碼中,我給TranslateTransfor的執行個體訂閱了事件,現在,小車的位置就是new Point(translate.X, translate.Y),小車的旋轉角度就是rotate.Angle,好了,該要的東西我們都有了,下面就要在GMap中實現了。
三、自訂Marker
首先,你看到這篇隨筆就代表你對GMap還是有一定瞭解的,那麼自然也知道Marker是個啥,不知道的可以利用搜尋引擎瞭解一下,或者參考這篇隨筆:http://www.cnblogs.com/luxiaoxun/p/3475355.html,我在這裡就不介紹了。在地圖上的小車其實就是個我們自訂的Marker,我們姑且稱為CarGMapMarker,在CarGMapMarker內部我們需要維護一個Canvas子類(因為繼承了Canvas),這個Canvas是Path的容器,然後我們還需要一個Border來當作運動的物體,其實這些過程都是為了類比http://www.cnblogs.com/zhouyinhui/archive/2007/07/31/837893.html中建立的情形,接著我們還需要一個事件public event EventHandler<Tuple<double, Point>> PositionChanged,用來通知我們自訂的Marker:喂!我內部維護的那個Border位置和角度改變了,他們分別是xxxxxxxx。而通知的代碼就寫在二中談到的Changed事件觸發方法中:
var translate = new TranslateTransform();var rotate = new RotateTransform();var group = new TransformGroup();translate.Changed += (s, e) =>{ OnPositionChanged(new Tuple<double, Point>(rotate.Angle, new Point(translate.X, translate.Y)));};
然後我們只要在自訂Marker中訂閱這個Canvas子類的PositionChanged事件,並從e中擷取一個元組,元組的Item1就是角度,Item2就是座標,我們可以利用角度改變Marker圖片的方向,利用座標改變MarkerPosition的值。
不過在此之前我們Canvas子類中的Path還沒有給它的Data屬性賦值,產生這個Data其實很簡單,就是把小車需要經過的關鍵點用線連起來就可以了,直接上方法:
public void SetPoints(List<Point> list){ var geometry = new PathGeometry(); var fi = new PathFigure {StartPoint = list.First() }; foreach (var item in list.Skip(1)) { fi.Segments.Add(new LineSegment(item, false)); } geometry.Figures.Add(fi);}
這裡要注意的是需要把list的第一個座標賦值給PathFigure的StartPoint屬性,剩餘的座標再一一相串連。最後,只要把這個geometry賦值給Canvas子類中Path的Data屬性即可,你可以用方法賦值,也可以在Canvas子類中寫個屬性賦值,隨你,我這裡使用了後者。
四、圖片處理
下面要說的是旋轉小車的圖片,Marker中的圖片用的是Bitmap,旋轉Bitmap的方法網上有很多,我們有時候可以奉行拿來主義,搜一個拿來用吧。要注意的是,小車的初始狀態車頭是要朝上的,因為朝上就是0度,和座標系吻合。
除此之外還有一個坑需要注意,在GMap中Marker預設都是處於目標點上方的,而不是中心點,可以用以下的圖片來理解:
,錨點最低點會在路線上,而不是錨點的中心在路線上,如果直接把錨點的圖片替換成汽車會如何?會這樣子:
你問為什麼車沒有旋轉?好的,那麼我就讓她旋轉一下,和該點的切線平行好了,Bitmap旋轉是圍繞中心點旋轉的,那麼旋轉後效果就是這樣子的:
雖然和切線平行了,但是小車完全脫離了路線,怎麼辦?往下移唄!移多少?高度的一半!光是這樣還不夠,我們還需要保證小車圖片的高度和寬度都要相等,即要是個正方形才可以,至於為什麼,博友們可以自己想想。
最後的效果如下:
如何較為方便的在GMap.Net中實現車輛運行軌跡