使用 GMap.NET 实现添加标注、移动标注功能。(WPF版)
前言
在WPF嵌入地圖,有兩種方式: 瀏覽器方式;控件方式。
1)瀏覽器方式就是使用瀏覽器控件WebBrowser,設置好網址就行了。這種方式與地圖的交互不太直接,需要懂html、javascript。對于不懂web編程的開發者來說,有點困難。
2)控件方式就是使用第三方控件;不需要處了解web相關知識,使用起來比較直接,易于理解。GMap.net 類庫就實現了這種控件。
GMap.net 簡介
GMap.NET 是一個強大、免費、跨平臺、開源的.NET控件,它在Windows Forms 和WPF環境中能夠通過Google, Yahoo!, Bing, OpenStreetMap, ArcGIS, Pergo, SigPac等實現尋找路徑、地理編碼以及地圖展示功能,并支持緩存和運行在Mobile環境中。
GMap.NET多年前已經存在,最初主要支持WinForm。WPF出現的較晚;但是,現在這個控件也可用于WPF開發。不過,網上相關WPF開發的例子較少。因為工作需要,最近使用這個控件開發了gis相關項目,把開發過程中的使用技巧寫出來,以供參考!
其中部分代碼參考了別人的文章,稍作修改!
程序界面:
將GMap.net加入項目
使用NuGet,搜索GMap.net就可以找到該控件:
?
添加地圖
GMap.net是國外開發的,不過也能很好的支持國內地圖。這個控件是開放的,只要按照要求完成相關設置,就可以把各類地圖加進來。
要理解這些設置,就需要先理解地圖的基本知識。我在這里就不多述。簡單一句話句話就是:地圖其實就多個圖片拼接而來的;你需要告訴控件,如何根據地理坐標和縮放級別獲取對應的圖片就行。
以高德地圖為例,看看如何設置:
需要重寫GMapProvider這個類,代碼如下:
public abstract class AMapProviderBase : GMapProvider{public AMapProviderBase(){MaxZoom = null;RefererUrl = "http://www.amap.com/";Copyright = string.Format("?{0} 高德 Corporation, ?{0} NAVTEQ, ?{0} Image courtesy of NASA", DateTime.Today.Year);}public override PureProjection Projection{get { return MercatorProjection.Instance; }}GMapProvider[] overlays;public override GMapProvider[] Overlays{get{if (overlays == null){overlays = new GMapProvider[] { this };//只有本圖層 }return overlays;}}}public class AMapProvider : AMapProviderBase{public static readonly AMapProvider Instance;readonly Guid id = new Guid("EF3DD303-3F74-4938-BF40-232D0595EE88");public override Guid Id{get { return id; }}readonly string name = "AMap";public override string Name{get{return name;}}private AMapProvider(){}static AMapProvider(){Instance = new AMapProvider();}//根據坐標和縮放,獲取對應的圖片。public override PureImage GetTileImage(GPoint pos, int zoom){string url = MakeTileImageUrl(pos, zoom, LanguageStr);return GetTileImageUsingHttp(url);}string MakeTileImageUrl(GPoint pos, int zoom, string language){//http://webrd04.is.autonavi.com/appmaptile?x=5&y=2&z=3&lang=zh_cn&size=1&scale=1&style=7string url = string.Format(UrlFormat, pos.X, pos.Y, zoom);Console.WriteLine("url:" + url);return url;}static readonly string UrlFormat = "http://webrd04.is.autonavi.com/appmaptile?x={0}&y={1}&z={2}&lang=zh_cn&size=1&scale=1&style=7";}最重要的函數就是?public override PureImage GetTileImage(GPoint pos, int zoom),地圖就是同一縮放比例的圖片堆砌而來。
使用控件
?在窗口中添加控件:主窗口代碼如下
<Window x:Class="GMapTest.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:gmap="clr-namespace:GMap.NET.WindowsPresentation;assembly=GMap.NET.WindowsPresentation"xmlns:local="clr-namespace:GMapTest" Loaded="Window_Loaded"mc:Ignorable="d" Background="#5A9EA5" Title="MainWindow" Height="450" Width="800"><Grid><Grid.ColumnDefinitions><ColumnDefinition Width="31*"/><ColumnDefinition Width="167*"/></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition Height="Auto"></RowDefinition><RowDefinition></RowDefinition></Grid.RowDefinitions><StackPanel Margin="5" Orientation="Horizontal" Grid.ColumnSpan="2"><CheckBox x:Name="checkMoveFlag" Margin="5,2,2,2" Click="CheckMoveFlag_Click">標注可移動</CheckBox><CheckBox x:Name="checkAddFlag" Margin="10,2,2,2">添加標注</CheckBox></StackPanel><GroupBox Grid.Row="1" Margin="0" Grid.ColumnSpan="2"><gmap:GMapControl x:Name="MainMap" MaxZoom="24" MinZoom="1" RenderOptions.BitmapScalingMode="NearestNeighbor" UseLayoutRounding="True" SnapsToDevicePixels="True"></gmap:GMapControl></GroupBox></Grid> </Window>使用設置RenderOptions.BitmapScalingMode="NearestNeighbor",可使圖片顯示較為清晰。
添加標注
標注稱之為Marker。控件有一個屬性?public ObservableCollection<GMapMarker> Markers { get; }用于存放標注。添加標注就是設置好GMapMarker相關屬性就行。代碼如下:
BitmapImage _pinSrcImage;Image CreatePinImage(GMapMarker marker){Image img = new Image();img.Tag = marker;img.Width = 32;img.Height = 32;if (_pinSrcImage == null){//多個標注共用一個圖像源,節省內存。_pinSrcImage = new BitmapImage(new Uri("pack://application:,,,/AMap/red-dot.png", UriKind.Absolute));_pinSrcImage.Freeze();}img.Source = _pinSrcImage;//鼠標熱點位置marker.Offset = new Point(-img.Width / 2, -img.Height / 2);return img;}private void AddMaker(PointLatLng pt){GMapMarker marker = new GMapMarker(pt);marker.Shape = CreatePinImage(marker);//將圖層添加到地圖this.MainMap.Markers.Add(marker);}?移動標注
首先需要檢測鼠標是否點擊了標注部分。需要在MouseDown事件中,通過WPF視覺樹輔助函數來判斷(VisualTreeHelper.HitTest)。其次在MouseMove函數中,將標注移動到新的坐標點。這里是通過鼠標左鍵移動;要實現此操作,設置控件拖動方式為?MainMap.DragButton = MouseButton.Right; 暨設置地圖拖動方式為鼠標右鍵,防止與標注移動相沖突。
關聯控件事件:
MainMap.MouseMove += MainMap_MouseMove;MainMap.MouseDown += MainMap_MouseDown;MainMap.MouseLeftButtonUp += MainMap_MouseLeftButtonUp;
判斷鼠標是否點擊了標注部分
GMapMarker _currentElement;private void MainMap_MouseDown(object sender, MouseButtonEventArgs e){if (checkMoveFlag.IsChecked == false){return;}//判斷是否點擊了標注if (_currentElement == null){Point pt = e.GetPosition(MainMap);PointLatLng point = MainMap.FromLocalToLatLng((int)pt.X, (int)pt.Y);PointHitTestParameters parameters = new PointHitTestParameters(pt);VisualTreeHelper.HitTest(MainMap, null, HitTestCallback, parameters);}}//右鍵彈起,設置標注變量為空private void MainMap_MouseLeftButtonUp(object sender, MouseButtonEventArgs e){_currentElement = null;}private HitTestResultBehavior HitTestCallback(HitTestResult result){Image image = result.VisualHit as Image;if (image != null){_currentElement = image.Tag as GMapMarker;return HitTestResultBehavior.Stop;}return HitTestResultBehavior.Continue;}MouseMove事件中,移動標注
private void MainMap_MouseMove(object sender, MouseEventArgs e){if (checkMoveFlag.IsChecked == true &&e.LeftButton == MouseButtonState.Pressed&& _currentElement != null){//獲取坐標Point pt = e.GetPosition(MainMap);//轉換成地理坐標PointLatLng point = MainMap.FromLocalToLatLng((int)pt.X, (int)pt.Y);_currentElement.Position = point;}}后記:
?winform和WPF是開發桌面程序的兩大框架。其中WPF是最新框架,具有很多顛覆性的概念。好多人感覺WPF的概念難以理解,同時感覺到GMap.net對WPF的封裝也不夠好,使用起來不如winform版好用。WPF版的GMap.net相比與winform版,確實省略了一些功能。這是因為WPF本身就很強大靈活,GMap.net再加上這些功能就多此一舉。“”標注檢測”就是一例,winform版有直接檢測標注的回調函數,WPF版就省略了。WPF是可以通過視覺樹HitTest函數來檢查,這種檢測方法更靈活。
轉載于:https://www.cnblogs.com/yuanchenhui/p/GMapTest.html
總結
以上是生活随笔為你收集整理的使用 GMap.NET 实现添加标注、移动标注功能。(WPF版)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Fragment 退出动画导致fragm
- 下一篇: mysql 锁表查询和解锁操作