绘制复杂的标记
本节内容可以参考CaseStudy目录下的文件"地图.Table"的示例三十一。
本节使用了一些GDI+的知识,如果忘记了,可以参考:GDI+快速入门
本节的任务是实现手工"勾选"城市,且为被勾选的城市绘制一个特别的标记:

1、将Map控件的"地图来源"属性设置为"None"
2、将窗口的AfterLoad事件代码设置为:
Dim
map As
GeoMap = e.Form.Controls("Map1").GeoMap
Dim layer
As
New
VectorLayer()
map.Layers.Add(layer)
layer.Style.Stroke.Color = Color.Gray
layer.LabelVisibility = LabelVisibility.AutoHide
layer.LabelStyle.ForeColor = Color.Green
'绘制省级行政区域
For
Each
dr As
DataRow In
DataTables("行政区域").Select("level=
1")
layer.Items.Add(map.CreatePolygon(dr("geometry"),
5))
Next
'绘制城市
Vars("MarkIndex")
= 0 '用一个Var变量记录自定义形状的当前序号
For
Each
dr As
DataRow In
DataTables("市").DataRows
Dim
mark As
New
VectorPlacemark()
mark.Tag = dr("市")
'将城市名作为标记的Tag
mark.Geometry =
New
GeoPoint(dr("经度"),
dr("纬度"))
mark.Marker.Shape = MarkerShape.Circle
'默认标记为圆圈
mark.Marker.Caption = dr("市")
If
dr("标记")
Then
mark.Marker.LabelPosition = LabelPosition.Bottom
'自定义标记的标题位置靠下
Vars("MarkIndex")
= Vars("MarkIndex")
+ 1 '递增序号
mark.Marker.Size =
New
SizeF(20, 27.32f)
'设置标记大小
mark.Marker.Shape = MarkerShape.Custom
'指定标记采用使用自定义形状
Dim
ShapeTag As
String
= CExp("{'name':'{0}','index':{1}}",
dr("市"),
Vars("MarkIndex"))
'用json格式传递城市名和序号
mark.Marker.CustomShape = map.CreateMarkShape(ShapeTag)
'创建自定义形状,将城市名和序号作为形状的tag
mark.Style.Stroke.Color = Color.DarkGray
'设置边框颜色
mark.Style.BackColor = Color.FromArgb(192, 128 + Rand.Next(127), 128 +
Rand.Next(127), 128 + Rand.Next(127))
'生成随机背景色
Else
mark.Marker.LabelPosition = LabelPosition.Right
'普通标记的标题靠右
mark.Marker.Size =
New
Size(8, 8) '设置普通标记的大小
End
If
If
dr("省会")
= False
And
dr("标记")
= False
Then
mark.Lod =
New
Lod(0, 0, 4, 20)
'未勾选的非省会城市在缩放比例达到4以后才显示
End
If
layer.Items.Add(mark)
Next
提示:这里演示了如何用json传递多个数据,关于json可参考: json解析
3、将Map控件的MouseClick事件代码设置为:
Dim
map
As
GeoMap = e.Sender.GeoMap
Dim
ifo
As
HitTestInfo = map.HitTest(e.Sender.MousePosition)
If
ifo
IsNot
Nothing
AndAlso
ifo.Vector
IsNot
Nothing
Then
If
TypeOf
ifo.Vector
Is
VectorPlacemark
Then
Dim
mark
As
VectorPlacemark = ifo.Vector
Dim
dr
As
DataRow = DataTables("市").Find("市
= '"
& mark.Tag &
"'")
If
dr
IsNot
Nothing
Then
dr("标记")
=
Not
dr("标记")|
If
dr("标记")
Then
mark.Marker.LabelPosition = LabelPosition.Bottom
'标题靠下
mark.Marker.Size =
New
SizeF(20, 27.32f)
Vars("MarkIndex")
= Vars("MarkIndex")
+ 1
'递增序号
Dim
ShapeTag
As
String
= CExp("{'name':'{0}','index':{1}}",
dr("市"),
Vars("MarkIndex"))
'用json格式传递城市名和序号
mark.Marker.Shape = MarkerShape.Custom
'指定采用标记使用自定形状
mark.Marker.CustomShape = map.CreateMarkShape(ShapeTag)
'创建自定义形状,将城市名和序号作为tag
mark.Style.Stroke.Color = Color.DarkGray
'设置边框颜色
mark.Style.BackColor = Color.FromArgb(192, 128 + Rand.Next(127),
128 + Rand.Next(127), 128 + Rand.Next(127))
'生成随机背景色
mark.Lod =
New
Lod(0, 0, 0, 20)
'始终显示已经勾选的城市
Else
'未勾选的标记恢复默认设置:
mark.Marker.LabelPosition = LabelPosition.Right
mark.Marker.Size =
New
SizeF(8, 8)
mark.Marker.Shape = MarkerShape.Circle
mark.Marker.CustomShape =
Nothing
mark.Style.Stroke.Color = Color.Gray
mark.style.BackColor = Color.Transparent
If
dr("省会")
=
True
Then
mark.Lod =
New
Lod(0, 0, 0, 20)
'省会城市始终显示
Else
mark.Lod =
New
Lod(0, 0, 4, 20)
'未勾选的非省会城市,缩放比例达到4才显示
End
If
End
If
End
If
End
If
End
If
4、将Map控件的GetDrawingBounds事件代码设置为:
e.Bounds = New RectangleF(e.Bounds.X , e.Bounds.Y - e.Bounds.Height/2, e.Bounds.Width, e.Bounds.Height)
提示:
GetDrawingBounds事件用于设置标记形状的绘制区域,这里将绘制区域向上移动了50%的高度,使得绘制的箭头恰好指向坐标点。
GetDrawingBounds事件的e参数和OwerDrawMark事件相同,但建议仅在这个事件修改e参数的Bounds,也就是设置绘制区域的位置和大小。
5、将Map控件的OwerDrawMark事件代码设置为:
Dim
jo
As
JObject = JObject.Parse(e.ShapeTag)
Dim
city
As
String
= jo("name")
'获得城市名,可以用于从数据表中找到对应的数据
Dim
index
As
Integer
= jo("index")
'获得自定义标记的序号
'要绘制的形状比较复杂,所以下面的绘制代码使用了GraphicsPath,理解不了
也没有关系,直接套用就行:
Dim
path
As
New
GraphicsPath()
Dim
rect
As
RectangleF =
New
RectangleF(e.bounds.Location,
New
SizeF(20, 20))
path.AddArc(rect, 120, 300)
rect =
New
RectangleF(e.bounds.Right - 10, e.bounds.Bottom - 10, 20, 20)
path.AddArc(rect, - 120, - 60)
rect =
New
RectangleF(e.bounds.Left - 10, e.bounds.Bottom - 10, 20, 20)
path.AddArc(rect, 0, - 60)
Using
path
Using
brush
As
New
SolidBrush(e.style.BackColor)
e.Graphics.FillPath(brush, path)
End
Using
Using
pen
As
New
Pen(e.style.Stroke.Color, e.style.Stroke.Width)
e.Graphics.DrawPath(pen, path)
End
Using
rect =
New
RectangleF(e.bounds.Location,
New
SizeF(20, 20))
Using
brush
As
New
SolidBrush(e.style.ForeColor)
Using
sf
As
New
StringFormat()
sf.Alignment = StringAlignment.Center
sf.LineAlignment = StringAlignment.Center
e.Graphics.DrawString(index.ToString(), e.style.Font, brush, rect,
sf)
End
Using
End
Using
End
Using
提示:
用GDI+绘制复杂的形状很灵活,但如果形状较为复杂,则需要你具备一些几何知识,对于普通用户可以考虑接用绘图软件绘制形状,保存为一个图片文件,然后:
1、在Map控件中直接使用图片文件作为标记,参考:使用图片标记,下一节就会使用图片实现类似的标记功能。
2、或在OwerDrawMark事件中用DrawImage方法为标记绘制图片 和(或)标题,这是最灵活的。