添加GMap引用
下载GMap demo
包含GMap源码以及地图下载器(用于生成GMDB格式离线地图文件)
下载地址:https://archive.codeplex.com/?p=greatmaps
PS:部分网络下载速度较慢,稍后提供下载链接。
尝试一个测试程序
新建用户控件继承GMapControl
重新生成解决方案,拖控件。
只需要几行代码就可以加载谷歌地图
下载离线地图
适合内网环境,程序拷贝到另外的设备也可以直接使用,方便部署;后面还会给出自建地图服务器的方法,以便更高要求的开发需要。
打开官方的demo,运行Demo.WinfowsForms.exe下载地图;低配电脑打开较慢,请耐心等待。
选择谷歌中国地图;右键拖拽,滚轮放大缩小;
按住alt,鼠标左键框选需要下载的地图
右侧点击cache->prefretch selected area;
确认是否截取Zoom级别12的地图;点击是。
一般截取到16或17就够用了;不需要截取的zoom点击否;
prefetch完毕后点击Export导出gmdb文件,也就是离线地图。
使用离线模式读取地图
修改我们的代码
运行程序,可以看到未下载的地图区域是无法显示的,而下载的地图区域已经成功从本地读取了缓存。
加载高德地图
打开GMap源码,可以看到已经有很多MapProvider;可是没有高德,百度等国内地图的Provider;需要我们自己实现MapProvider。
查看源码,看不懂怎么办?没有关系,依葫芦画瓢;首先创建一个AMapProviderBase继承GMapProvider
然后创建AMapProvider继承AMapProviderBase
我们可以观察到这些Provider的实现类都很类似,最大的区别就是UrlFormat不一样;
这个UrlFormat代表什么?
我们复制一个UrlFormat到浏览器看一看:
static readonly string UrlFormat = “http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer/tile/{0}/{1}/{2}”;
观察代码发现{0},{1},{2}分包表示zoom,Y坐标和X坐标;
于是我们修改一下URL:
http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer/tile/1/1/2
这不就是我们要找的瓦片地图吗?
对没错!这个URL就是地图提供商提供的WMTS接口!也就是地图瓦片服务。如果我们拿到了WMTS接口,就意味着我们可以通过GMap访问市面上大部分地图服务器。
这里提供高德的WMTS接口,修改style可以调用不同的地图样式。(在网路上找了很多,这个版本的WMTS貌似是最新的,不过好像没有只显示路名的简图)
完成AMapProvider的编写后,打开GMapProviders类,新增一个高德地图的实例
运行一下,可以看到已经有了高德地图的选项。
下面就可以尽情下载高德地图了
应用程序使用离线地图也需要修改MapProvider
获取WMTS
有了WMTS接口就可以加载任意的地图
捷泰地图暗黑版
捷泰地图暖色版
注意部分地图提供商的服务需要注册申请key
坐标系转化
注意地图使用的坐标系,不同坐标系经纬度会有偏移:
名称 | 解释 |
---|---|
WGS84 | 地心坐标系,国际通用坐标系 |
GCJ02 | 国测局坐标(火星坐标系),WGS84加密后的坐标系;GoogleChina地图、高德地图等国内地图使用 |
BD09 | 百度坐标系,GCJ02再次加密后的坐标系 |
网路上可以搜索到坐标原理以及不同坐标转换的工具类,在此不再赘述。
GMap常用地图操作
GMap地图控件结构:
底图
↓
图层1→markers、routes…
↓
图层2→markers、routes…
//图层
GMapOverlay bgLayer = new GMapOverlay("bgLayer");
mapControl1.Overlays.Add(bgLayer);
mapControl1.Overlays.Remove(bgLayer);
//marker
Bitmap markerGreen = Image.FromFile("path") as Bitmap;
PointLatLng point = new PointLatLng(32.261551, 118.339794);
GMapMarker marker = new GMarkerGoogle(point, markerGreen);
//tooltip
MarkerTooltipMode mode = MarkerTooltipMode.Always;//标注一直显示
Brush tooltipBackColor = new SolidBrush(Color.Transparent);
marker.ToolTip = new GMapToolTip(marker);
marker.ToolTipMode = mode;
marker.ToolTipText = "xx路与xx路";
//tooltip样式
marker.ToolTip.Font = new Font("微软雅黑", 11);
marker.ToolTip.Fill = tooltipBackColor;
marker.ToolTip.Foreground = Brushes.Gray;
marker.ToolTip.Stroke.Brush = tooltipBackColor;
marker.ToolTip.Offset = new System.Drawing.Point(marker.Offset.X - (int)((float)marker.ToolTipText.Length / 2) * 15, marker.Offset.Y + 28);
//marker加到图层
bgLayer.Markers.Add(marker);
//marker点击事件
mapControl1.OnMarkerClick += new MarkerClick(Marker_Click_Event);
//Route线路
List<PointLatLng> points = new List<PointLatLng>();
GMapRoute r = new GMapRoute(points, null);
bgLayer.Routes.Add(r);
自定义Marker,实现图标实时切换,图标闪烁等功能
public class GMapMarkerImage : GMapMarker
{
private Image image;
public Image Image
{
get
{
return image;
}
set
{
image = value;
if (image != null)
{
this.Size = new Size(image.Width, image.Height);
}
}
}
public Pen Pen
{
get;
set;
}
public Pen OutPen
{
get;
set;
}
public GMapMarkerImage(PointLatLng point, Image image) : base(point)
{
Size = new Size(image.Width, image.Height);
Offset = new Point(-Size.Width / 2, -Size.Height / 2);
this.image = image;
Pen = null;
OutPen = null;
}
public override void OnRender(Graphics g)
{
if (image == null)
{
return;
}
Rectangle rect = new Rectangle(LocalPosition.X, LocalPosition.Y, Size.Width, Size.Height);
Rectangle rectBlink = new Rectangle(LocalPosition.X-3, LocalPosition.Y -3, Size.Width+5, Size.Height+5);
g.DrawImage(image, rect);
if (Pen != null)
{
g.DrawRectangle(Pen, rect);
}
if (OutPen != null)
{
g.DrawEllipse(OutPen, rectBlink);
}
}
public void UpdateImage(Image image)
{
this.image = image;
}
public override void Dispose()
{
if (Pen != null)
{
Pen.Dispose();
Pen = null;
}
if (OutPen != null)
{
OutPen.Dispose();
OutPen = null;
}
base.Dispose();
}
}
//切换图片
marker.UpdateImage(bitmapGreen);
//闪烁 用定时器刷新
if (marker.OutPen == null)
{
marker.OutPen = new Pen(Brushes.DeepSkyBlue, 5);
}
else
{
marker.OutPen.Dispose();
marker.OutPen = null;
}
可以实现的效果
自建地图服务器
通过自建地图服务器,可以实现自定义地图边界,手动绘制新增道路,随意调整地图样式,去除不必要的标注等功能。
GeoServer 是 OpenGIS Web 服务器规范的 J2EE 实现,利用 GeoServer 可以方便的发布地图数据,允许用户对特征数据进行更新、删除、插入操作,通过 GeoServer 可以比较容易的在用户之间迅速共享空间地理信息。GeoServer是社区开源项目,可以直接通过社区网站下载。
WEB开发可以通过OpenLayers访问地图服务器。OpenLayers 是一个专为Web GIS 客户端开发提供的JavaScript 类库包,用于实现标准格式发布的地图数据访问。可以在 Web 上创建交互式地图,显示从任何来源加载的地图图块、矢量数据和标记。
安装GeoServer(需要JDK)
浏览器输入http://localhost:8089/geoserver/web/进入管理页面
GeoServer支持多种格式的地图,可以从网路上下载或购买。
推荐地图编辑软件:ArcMap、MapInfo
发布图层
自定义地图样式
WMTS服务
地图预览,比第三方地图服务器简洁了很多,多余的区域不显示,没有杂乱的标注和图标,可以充分个性化。
WMS接口
WMTS接口
“http://{your ip&port}/geoserver/gwc/service/wmts?layer={your mapName}&tilematrixset=EPSG:4326&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image/png&TileMatrix=EPSG:4326:{zoom}&TileCol={X}&TileRow={Y}”;
程序展示