GMap.Net开发之自定义Marker
上一篇文章介绍了如何在WinForm和WPF中使用GMap控件,这篇介绍下GMap中Marker的使用。
自定义Marker,可以理解为在地图上自定义图标(Custom Marker),先看看GMap的地图和图标的显示方式:

Map控件上可以添加Overlay(图层),可以添加多个图层,先添加的图层在下面显示。
图层上可以添加GMapMarker,当然也可以添加GMapPolygon和GMapRoute,后续介绍。
在地图的使用中常要求的功能就是添加自定义图标,可以点击图标、删除图标、拖动图标、高亮图标等。
下面介绍这些功能的实现(主要是基于WinForm的,WPF的可以参考官方Demo实现):
1、自定义图标,使用官方的Marker:
Bitmap bitmap = Bitmap.FromFile("F:\\Projects\\GMapDemo\\GMapDemo\\Image\\A.png") as Bitmap;
GMapMarker marker = new GMarkerGoogle(point, bitmap);
直接使用GMap.NET.WindowsForms.Markers中的GMarkerGoogle,传入一个Bitmap,就可以使用自定义的图片来做图标。
2、继承GMapMarker,自定义Marker:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GMap.NET;
using GMap.NET.WindowsForms;
using System.Drawing; namespace GMapWinFormDemo
{
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(GMap.NET.PointLatLng p, Image image)
: base(p)
{
Size = new System.Drawing.Size(image.Width, image.Height);
Offset = new System.Drawing.Point(-Size.Width / , -Size.Height / );
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);
g.DrawImage(image, rect); if (Pen != null)
{
g.DrawRectangle(Pen, rect);
} if (OutPen != null)
{
g.DrawEllipse(OutPen, rect);
}
} public override void Dispose()
{
if (Pen != null)
{
Pen.Dispose();
Pen = null;
} if (OutPen != null)
{
OutPen.Dispose();
OutPen = null;
} base.Dispose();
}
}
}
介绍下GMapMarkerImage三个属性的作用:
Image:保存图标的图片。
Pen:在图片外围画DrawRectangle的Pen,当其不为null的时候,会在图片的外围画一个矩形,实现高亮(highlight)的效果。
OutPen:在图片外围画DrawEllipse的Pen,当其不为null的时候,会在图片外围画一个一个椭圆,设置这个值可以实现闪动。
3、移动图标(Move Marker)的实现:
在MapControl中添加如下事件的响应:
mapControl.MouseDown += new MouseEventHandler(mapControl_MouseDown);
mapControl.MouseUp += new MouseEventHandler(mapControl_MouseUp);
mapControl.MouseMove += new MouseEventHandler(mapControl_MouseMove); mapControl.OnMarkerClick += new MarkerClick(mapControl_OnMarkerClick);
mapControl.OnMarkerEnter += new MarkerEnter(mapControl_OnMarkerEnter);
mapControl.OnMarkerLeave += new MarkerLeave(mapControl_OnMarkerLeave);
MouseDown和MouseUp中判断左键是否按下(用左键来移动图标)。
OnMarkerEnter中设置选中的Marker,同时设置Pen的值,实现高亮。
OnMarkerLeave中取消选中的Marker,取消Pen的值,取消高亮。
MouseMove中更新选中选中Marker的Position就可以了。
4、图标闪动的实现:
需要一个定时器:使用的是Form下的Timer,定时器响应的事件:
void blinkTimer_Tick(object sender, EventArgs e)
{
foreach (GMapMarker m in objects.Markers)
{
if (m is GMapMarkerImage)
{
GMapMarkerImage marker = m as GMapMarkerImage;
if (marker.OutPen == null)
marker.OutPen = new Pen(Brushes.Red, );
else
{
marker.OutPen.Dispose();
marker.OutPen = null;
}
}
}
mapControl.Refresh();
}
更新所有Marker的OutPen的值(当然你也可以只更新某个Marker),通过在图标上画圈圈来实现闪动,当然你也可以通过设置Marker的IsVisible属性来实现自己想要的效果。。。
效果图如下:

全部代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using GMap.NET;
using GMap.NET.WindowsForms;
using GMap.NET.MapProviders;
using GMap.NET.WindowsForms.Markers; namespace GMapWinFormDemo
{
public partial class MainForm : Form
{
private GMapOverlay objects = new GMapOverlay("objects"); //放置marker的图层
private GMapMarkerImage currentMarker;
private bool isLeftButtonDown = false; private Timer blinkTimer = new Timer(); public MainForm()
{
InitializeComponent(); try
{
System.Net.IPHostEntry e = System.Net.Dns.GetHostEntry("ditu.google.cn");
}
catch
{
mapControl.Manager.Mode = AccessMode.CacheOnly;
MessageBox.Show("No internet connection avaible, going to CacheOnly mode.", "GMap.NET Demo", MessageBoxButtons.OK, MessageBoxIcon.Warning);
} mapControl.CacheLocation = Environment.CurrentDirectory + "\\GMapCache\\"; //缓存位置
mapControl.MapProvider = GMapProviders.GoogleChinaMap; //google china 地图
mapControl.MinZoom = ; //最小比例
mapControl.MaxZoom = ; //最大比例
mapControl.Zoom = ; //当前比例
mapControl.ShowCenter = false; //不显示中心十字点
mapControl.DragButton = System.Windows.Forms.MouseButtons.Left; //左键拖拽地图
mapControl.Position = new PointLatLng(32.064,118.704); //地图中心位置:南京 mapControl.OnMapZoomChanged += new MapZoomChanged(mapControl_OnMapZoomChanged);
mapControl.MouseClick += new MouseEventHandler(mapControl_MouseClick);
mapControl.MouseDown += new MouseEventHandler(mapControl_MouseDown);
mapControl.MouseUp += new MouseEventHandler(mapControl_MouseUp);
mapControl.MouseMove += new MouseEventHandler(mapControl_MouseMove); mapControl.OnMarkerClick += new MarkerClick(mapControl_OnMarkerClick);
mapControl.OnMarkerEnter += new MarkerEnter(mapControl_OnMarkerEnter);
mapControl.OnMarkerLeave += new MarkerLeave(mapControl_OnMarkerLeave); mapControl.Overlays.Add(objects);
} void mapControl_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left && isLeftButtonDown)
{
if (currentMarker != null)
{
PointLatLng point = mapControl.FromLocalToLatLng(e.X, e.Y);
currentMarker.Position = point;
currentMarker.ToolTipText = string.Format("{0},{1}", point.Lat, point.Lng);
}
}
} void mapControl_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
isLeftButtonDown = false;
}
} void mapControl_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
isLeftButtonDown = true;
}
} void mapControl_OnMarkerLeave(GMapMarker item)
{
if (item is GMapMarkerImage)
{
currentMarker = null;
GMapMarkerImage m = item as GMapMarkerImage;
m.Pen.Dispose();
m.Pen = null;
}
} void mapControl_OnMarkerEnter(GMapMarker item)
{
if (item is GMapMarkerImage)
{
currentMarker = item as GMapMarkerImage;
currentMarker.Pen = new Pen(Brushes.Red, );
}
} void mapControl_OnMarkerClick(GMapMarker item, MouseEventArgs e)
{
} void mapControl_MouseClick(object sender, MouseEventArgs e)
{
if(e.Button == System.Windows.Forms.MouseButtons.Right)
{
//objects.Markers.Clear();
PointLatLng point = mapControl.FromLocalToLatLng(e.X,e.Y);
//GMapMarker marker = new GMarkerGoogle(point, GMarkerGoogleType.green);
Bitmap bitmap = Bitmap.FromFile("F:\\Projects\\GMapDemo\\GMapDemo\\Image\\A.png") as Bitmap;
//GMapMarker marker = new GMarkerGoogle(point, bitmap);
GMapMarker marker = new GMapMarkerImage(point, bitmap);
marker.ToolTipMode = MarkerTooltipMode.OnMouseOver;
marker.ToolTipText = string.Format("{0},{1}", point.Lat, point.Lng);
objects.Markers.Add(marker);
}
} void mapControl_OnMapZoomChanged()
{
} private void buttonBeginBlink_Click(object sender, EventArgs e)
{
blinkTimer.Interval = ;
blinkTimer.Tick += new EventHandler(blinkTimer_Tick);
blinkTimer.Start();
} void blinkTimer_Tick(object sender, EventArgs e)
{
foreach (GMapMarker m in objects.Markers)
{
if (m is GMapMarkerImage)
{
GMapMarkerImage marker = m as GMapMarkerImage;
if (marker.OutPen == null)
marker.OutPen = new Pen(Brushes.Red, );
else
{
marker.OutPen.Dispose();
marker.OutPen = null;
}
}
}
mapControl.Refresh();
} private void buttonStopBlink_Click(object sender, EventArgs e)
{
blinkTimer.Stop();
foreach (GMapMarker m in objects.Markers)
{
if (m is GMapMarkerImage)
{
GMapMarkerImage marker = m as GMapMarkerImage;
marker.OutPen.Dispose();
marker.OutPen = null;
}
}
mapControl.Refresh();
}
}
}
项目地址:https://github.com/luxiaoxun/MapDownloader
GMap.Net开发之自定义Marker的更多相关文章
- iOS开发之自定义表情键盘(组件封装与自动布局)
下面的东西是编写自定义的表情键盘,话不多说,开门见山吧!下面主要用到的知识有MVC, iOS开发中的自动布局,自定义组件的封装与使用,Block回调,CoreData的使用.有的小伙伴可能会问写一个自 ...
- android开发之自定义组件
android开发之自定义组件 一:自定义组件: 我认为,自定义组件就是android给我们提供的的一个空白的可以编辑的图片,它帮助我们实现的我们想要的界面,也就是通过自定义组件我们可以把我们要登入的 ...
- 手机3D游戏开发:自定义Joystick的相关设置和脚本源码
Joystick在手游开发中非常常见,也就是在手机屏幕上的虚拟操纵杆,但是Unity3D自带的Joystick贴图比较原始,所以经常有使用自定义贴图的需求. 下面就来演示一下如何实现自定义JoySti ...
- PHPCMS V9二次开发便捷自定义后台入口文件夹
phpcms v9二次开发便捷自定义后台入口文件夹 最新发布的phpcms v9由于采用了mvc的设计模式,所以它的后台访问地址是固定的,虽然可以通过修改路由配置文件来实现修改,但每次都修改路由配置文 ...
- 详解iOS开发之自定义View
iOS开发之自定义View是本文要将介绍的内容,iOS SDK中的View是UIView,我们可以很方便的自定义一个View.创建一个 Window-based Application程序,在其中添加 ...
- android高德地图网络路径实现自定义marker并点击弹出自定义窗口
android中使用地图的地方随处可见,今天记录一下网络路径生成自定义marker,点击标记弹出自定义的窗口(在这里使用的是高德地图) 在这里我们使用Grilde去加载网络图片,因为这个简直太方便了! ...
- 如何开发使用自定义文件的OEM应用程序
有关创建和使用自定义数据文件的详细信息,请参阅DISM应用程序包(.appx或.appxbundle)服务命令行选项. 了解如何开发使用自定义文件的应用程序,将信息从OEM传递到应用程序. 对于您为O ...
- [转载]开发 Spring 自定义视图和视图解析器
原文出处 http://www.ibm.com/developerworks/cn/java/j-lo-springview/ 概述 Spring 3.0 默认包含了多种视图和视图解析器,比如 JSP ...
- Android集成高德地图如何自定义marker
高德地图自定义Marker 高德地图默认的marker样式是这种 一般的修改样式是通过icon接口来调整 MarkerOptions markerOptions = new MarkerOptions ...
随机推荐
- MySQL Errcode 13 with SELECT INTO OUTFILE Can't create/write to file
这是由于权限问题导致的,最主要的问题是搞清楚权限是如何设置的.Ubuntu 使用 AppArmor 作为程序权限限制, Fedora 使用 selinux 作为程序权限限制. 在linux中,以往的权 ...
- Ubuntu 16.04播放器Rhythmbox乱码解决
使用Rhythmbox进行音乐播放的时候,歌曲名称专辑歌手名称都出现乱码,查看了网上很多教程,要不就是将音频转码,要不就是修改用户环境编码配置.前一种方法对音频有改动,后一种可能无效还有可能会影响系统 ...
- ubuntu14.04 server安装gnome-desktop
You can install the default Ubuntu desktop by executing the following: sudo apt-get install ubuntu-d ...
- 【leetcode】Convert Sorted List to Binary Search Tree
Convert Sorted List to Binary Search Tree Given a singly linked list where elements are sorted in as ...
- python virtualenv环境运行django
python virtualenv环境运行django 安装前准备 检查pip版本与python版本是否一致 [root@localhost bin]# whereis pip pip: /usr/b ...
- Unity Assets目录下的特殊文件夹名称
1.隐藏文件夹以.开头的文件夹会被Unity忽略.在这种文件夹中的资源不会被导入,脚本不会被编译.也不会出现在Project视图中.2.Standard Assets在这个文件夹中的脚本最先被编译.这 ...
- ios 转发一篇对于6 plus的分辨率模式的说明
http://segmentfault.com/q/1010000002545515 分为兼容模式和高分辨率模式. 兼容模式 当你的 app 没有提供 3x 的 LaunchImage 时,系统默认进 ...
- PHP输出Excel两种方法
2016年3月23日 16:43:51 星期三 第一种: 输出html+css格式, 打开后用Excel软件的"另存为"功能保存为正规的表格格式 public function e ...
- Linux下安装Flask开发框架
Flask是开发pythonweb的一个轻量级框架,适合初学者使用,当有了熟练的web基础后,再继续学习高级框架的开发,Linux一般安装好之后都会有python开发环境,给开发带来方便,下面是Fla ...
- sqlserver insert 存储过程
-- 根据表中数据生成insert语句的存储过程Create Proc proc_insert (@tablename varchar(256)) as ...