GMap.NET有兩個版本,分別是WinForm和WPF的版本,WinForm版本的教程很多。這次主要介紹的WPF版本的操作。
要下載GMap.NET請點擊這裏,這個最好下載下來,可以參考裏面的Demo來學習。下載下來後,用visual studio打開SourceCode裏面的sln文件。打開的時候可能需要讓你下載什麼東西,這個有點不記得了,但是關於數據庫的那個應該不用下載。
1、導入dll
1-1、第一種方法
按照下圖打開NuGet包管理器,然後輸入Gmap.net進行搜索,點擊想要安裝的dll,然後選擇項目,點擊安裝即可。
1-2、第二種方法
這種方法就是運行下載下來的源代碼,然後再拷貝Debug下面生成的dll文件。這樣的做法更加靈活,可以自己更改代碼。
2、導入GMapControl控件
2-1、再工具箱空白處右鍵“選項”然後選中GMapControl,點擊確定。即可在工具箱中使用GMapControl控件。
3、導入高德地圖
高德的地圖和google地圖使用的座標一致,可以切換使用,但是據說百度的又增加了偏移。
3-1、普通地圖
using GMap.NET;
using GMap.NET.MapProviders;
using GMap.NET.Projections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace jiemian3.CustomMap
{
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;
}
}
static AMapProvider()
{
Instance = new AMapProvider();
}
public override PureImage GetTileImage(GPoint pos, int zoom)
{
try
{
string url = MakeTileImageUrl(pos, zoom, LanguageStr);
return GetTileImageUsingHttp(url);
}
catch (Exception ex)
{
return null;
}
}
string MakeTileImageUrl(GPoint pos, int zoom, string language)
{
var num = (pos.X + pos.Y) % 4 + 1;
//string url = string.Format(UrlFormat, num, pos.X, pos.Y, zoom);
string url = string.Format(UrlFormat, pos.X, pos.Y, zoom);
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";
static readonly string UrlFormat = "http://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={0}&y={1}&z={2}";
}
}
3-2、高德衛星地圖,但是高德衛星地圖(官網的地圖)的數據不完整
using GMap.NET;
using GMap.NET.MapProviders;
using GMap.NET.Projections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace jiemian3.CustomMap
{
public class AMapSateliteProvider : AMapProviderBase
{
private readonly Guid id = new Guid("FCA94AF4-3467-47c6-BDA2-6F52E4A145BC");
public static readonly AMapSateliteProvider Instance = new AMapSateliteProvider();
//private readonly string name = Resources.Strings.AMapSatellite;
private readonly string name = "AMapSatellite";
private static readonly string UrlFormat = "http://webst04.is.autonavi.com/appmaptile?x={0}&y={1}&z={2}&lang=zh_cn&size=1&scale=1&style=6";
public override PureImage GetTileImage(GPoint pos, int zoom)
{
string url = this.MakeTileImageUrl(pos, zoom, GMapProvider.LanguageStr);
return base.GetTileImageUsingHttp(url);
}
private string MakeTileImageUrl(GPoint pos, int zoom, string language)
{
string str = string.Format(UrlFormat, pos.X, pos.Y, zoom);
Console.WriteLine("url:" + str);
return str;
}
public override Guid Id
{
get
{
return this.id;
}
}
public override string Name
{
get
{
return this.name;
}
}
}
}
4、自定義Marker
winform版的自己GMap提供了第三方的marker,但是WPF的需要自己寫。可以參考源代碼項目中Demo目錄下面的“Demo.WindowsPresentation”,WPF所有的代碼都可以參考這個Demo。我直接把“Demo.WindowsPresentation”裏面對應的代碼粘貼到下面。
因爲這些代碼再一個單獨的文件夾下面,所以注意命名空間和路徑,自己做調整。
CustomMarkerRed.xaml
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Demo.WindowsPresentation.CustomMarkers.CustomMarkerRed"
Height="40" Width="30" Opacity="10">
<Image Name="icon" Source="red-dot.png" VerticalAlignment="Center" HorizontalAlignment="Center" />
</UserControl>
CustomMarkerRed.xaml.cs
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using GMap.NET.WindowsPresentation;
namespace Demo.WindowsPresentation.CustomMarkers
{
/// <summary>
/// Interaction logic for CustomMarkerDemo.xaml
/// </summary>
public partial class CustomMarkerRed
{
Popup Popup;
Label Label;
GMapMarker Marker;
MainWindow MainWindow;
public CustomMarkerRed(MainWindow window, GMapMarker marker, string title)
{
this.InitializeComponent();
this.MainWindow = window;
this.Marker = marker;
Popup = new Popup();
Label = new Label();
this.Loaded += new RoutedEventHandler(CustomMarkerDemo_Loaded);
this.SizeChanged += new SizeChangedEventHandler(CustomMarkerDemo_SizeChanged);
this.MouseEnter += new MouseEventHandler(MarkerControl_MouseEnter);
this.MouseLeave += new MouseEventHandler(MarkerControl_MouseLeave);
this.MouseMove += new MouseEventHandler(CustomMarkerDemo_MouseMove);
this.MouseLeftButtonUp += new MouseButtonEventHandler(CustomMarkerDemo_MouseLeftButtonUp);
this.MouseLeftButtonDown += new MouseButtonEventHandler(CustomMarkerDemo_MouseLeftButtonDown);
Popup.Placement = PlacementMode.Mouse;
{
Label.Background = Brushes.Blue;
Label.Foreground = Brushes.White;
Label.BorderBrush = Brushes.WhiteSmoke;
Label.BorderThickness = new Thickness(2);
Label.Padding = new Thickness(5);
Label.FontSize = 22;
Label.Content = title;
}
Popup.Child = Label;
}
void CustomMarkerDemo_Loaded(object sender, RoutedEventArgs e)
{
if(icon.Source.CanFreeze)
{
icon.Source.Freeze();
}
}
void CustomMarkerDemo_SizeChanged(object sender, SizeChangedEventArgs e)
{
Marker.Offset = new Point(-e.NewSize.Width/2, -e.NewSize.Height);
}
void CustomMarkerDemo_MouseMove(object sender, MouseEventArgs e)
{
if(e.LeftButton == MouseButtonState.Pressed && IsMouseCaptured)
{
Point p = e.GetPosition(MainWindow.MainMap);
Marker.Position = MainWindow.MainMap.FromLocalToLatLng((int) p.X, (int) p.Y);
}
}
void CustomMarkerDemo_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if(!IsMouseCaptured)
{
Mouse.Capture(this);
}
}
void CustomMarkerDemo_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if(IsMouseCaptured)
{
Mouse.Capture(null);
}
}
void MarkerControl_MouseLeave(object sender, MouseEventArgs e)
{
Marker.ZIndex -= 10000;
Popup.IsOpen = false;
}
void MarkerControl_MouseEnter(object sender, MouseEventArgs e)
{
Marker.ZIndex += 10000;
Popup.IsOpen = true;
}
}
}
在主界面中使用
currentMarker = new GMapMarker(MainMap.Position);
{
currentMarker.Shape = new CustomMarkerRed(this, currentMarker, "custom position marker");
currentMarker.Offset = new System.Windows.Point(-15, -15);
currentMarker.ZIndex = int.MaxValue;
MainMap.Markers.Add(currentMarker);
}
圖片如下:
5、繪製多邊形
下面只公佈部分代碼和思想,如果有不懂的可以提問。有些不方面提供。
5-1、多邊形
使用dll中提供的GMapPolygon類。
List<PointLatLng> points = new List<PointLatLng>();
//在這塊添加一些points
GMapPolygon polygon = new GMapPolygon(points);
polygon.ZIndex = 10; //設置Zindex,顯示的優先級(層)
polygon.RegenerateShape(gmap); //gmap就是地圖控件
//下面這個比較重要,是設置樣式。
(polygon.Shape as Path).Stroke = Brushes.GreenYellow;
(polygon.Shape as Path).StrokeThickness = 5;
(polygon.Shape as Path).Effect = null;
gmap.Markers.Add(polygon);
5-2、折線(路徑)
使用GMapRoute類,基本和上面的一樣。
List<PointLatLng> points = new List<PointLatLng>();
//在這塊添加一些points
GMapRoute route = new GMapRoute(points);//
route.ZIndex = 10;
route.RegenerateShape(gmap);
(route.Shape as Path).Stroke = Brushes.Blue;
(route.Shape as Path).StrokeThickness = 5;
(route.Shape as Path).Effect = null;
gmap.Markers.Add(route);
5-3、根據鼠標畫矩形
這個需要自己寫一些鼠標事件。這個自己發揮吧,代碼有點亂,自己思考也不難。因爲一些原因,這部分代碼不能全部公佈,多多理解。
下面的代碼是畫矩形的,只是沒有鼠標事件的代碼。已經很接近了。
PointLatLng startpoint = mainmarker.Position;
List<PointLatLng> list_points = new List<PointLatLng>();
if (startpoint.Lat > current_point.Lat)
{
if (startpoint.Lng < current_point.Lng)
{
//右下
list_points.Add(startpoint);
list_points.Add(new PointLatLng(startpoint.Lat, current_point.Lng));
list_points.Add(current_point);
list_points.Add(new PointLatLng(current_point.Lat, startpoint.Lng));
}
else
{
//左下
list_points.Add(startpoint);
list_points.Add(new PointLatLng(current_point.Lat, startpoint.Lng));
list_points.Add(current_point);
list_points.Add(new PointLatLng(startpoint.Lat, current_point.Lng));
}
}
else
{
if (startpoint.Lng < current_point.Lng)
{
//右上
list_points.Add(startpoint);
list_points.Add(new PointLatLng(startpoint.Lat, current_point.Lng));
list_points.Add(current_point);
list_points.Add(new PointLatLng(current_point.Lat, startpoint.Lng));
}
else
{
//左上
list_points.Add(startpoint);
list_points.Add(new PointLatLng(current_point.Lat, startpoint.Lng));
list_points.Add(current_point);
list_points.Add(new PointLatLng(startpoint.Lat, current_point.Lng));
}
}
double lat = (startpoint.Lat+current_point.Lat) / 2;
double lng = (startpoint.Lng + current_point.Lng) / 2;
double heightlat = Math.Abs(current_point.Lat-startpoint.Lat);
double widthlng = Math.Abs(current_point.Lng-startpoint.Lng);
rectLatLng = RectLatLng.FromLTRB(startpoint.Lng,startpoint.Lat,current_point.Lng,current_point.Lat);
rectangle = new GMapPolygon(list_points);
rectangle.ZIndex = Rectangle_index;
rectangle.RegenerateShape(gmap);
(rectangle.Shape as Path).Stroke = Brushes.GreenYellow;
(rectangle.Shape as Path).StrokeThickness = 5;
(rectangle.Shape as Path).Effect = null;
gmap.Markers.Add(rectangle);
5-4、根據鼠標畫圓形
上面的矩形還好是GMAP自己控件畫的,但是圓形沒有,也不能根據點畫,因爲有無數個點。最主要的是畫的圓形要能夠更具地圖縮放。這部分還是參考Demo中的代碼。思路是:使用一個XMAL控件,裏面是一個圓,設置屬性是填充的,然後改變邊框即可改變圓的大小。首先根據鼠標移動位置和中心點的經緯度座標轉化成界面座標,然後計算半徑,畫圓。
Circle.xaml
<UserControl x:Class="Demo.WindowsPresentation.CustomMarkers.Circle"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300" Background="Transparent">
<Grid>
<Ellipse Stroke="Red" Fill="AliceBlue" Opacity="0.44" />
</Grid>
</UserControl>
Circle.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using GMap.NET;
namespace Demo.WindowsPresentation.CustomMarkers
{
/// <summary>
/// Interaction logic for Circle.xaml
/// </summary>
public partial class Circle : UserControl
{
public Circle()
{
InitializeComponent();
}
public PointLatLng Center;
public PointLatLng Bound;
}
}
畫圓的代碼
PointLatLng center = mainmarker.Position;
circle = new GMapMarker(center);
circle_shape = new Circle();
circle_shape.Center = center;
circle_shape.Bound = current_point;
circle_shape.Tag = circle;
circle_shape.IsHitTestVisible = false;
UpdateCircle(circle_shape);//下面的代碼
circle.Shape = circle_shape;
circle.ZIndex = Circle_index;
gmap.Markers.Add(circle);
更新圓的大小的代碼,這塊每次在地圖加載的時候調用就可以讓圓不斷變化大小。
private void UpdateCircle(Circle c)
{
var pxCenter = gmap.FromLatLngToLocal(c.Center);
var pxBounds = gmap.FromLatLngToLocal(c.Bound);
Console.WriteLine(pxCenter + " " + pxBounds);
double a = (double)(pxBounds.X - pxCenter.X);
double b = (double)(pxBounds.Y - pxCenter.Y);
//半徑
var pxCircleRadius = Math.Sqrt(a * a + b * b);
Console.WriteLine("半徑爲:" + pxCircleRadius);
c.Width = pxCircleRadius * 2;
c.Height = pxCircleRadius * 2;
(c.Tag as GMapMarker).Offset = new System.Windows.Point(-c.Width / 2, -c.Height / 2);
}
6、Zindex
WPF中沒有GMapOverlay,但是可以使用Zindex來設置虛擬的。Zindex越大的顯示就越靠上。