百度地图上绘制复杂图形

什么是图层

如果你曾经使用过p图软件,对图层的概念应该不会陌生。简单来说,就是在原来的画布上叠加一个新的画布,这个新的画布就是一个新的图层。上面的图层自然会覆盖下面的图层,你可以设置图层的级别以及透明度来实现图层叠加,绘制想要的图像。

canvas绘图

在讨论自定义图层前,我们需要了解canvas画图基本方法,利用百度地图提供的canvas图层接口绘制自定义图形。

使用js绘图前,你需要新建一个画布,即在html中添加一个canvas标签。

1
2
<canvas id="myCanvas"  width="800" height="600">
</canvas>

获取canvas画布容器,并使用getContext() 方法返回一个用于在画布上绘图的二维环境,接下来你可以使用手册中的图形来绘制二维图形。

1
2
var c=document.getElementById("myCanvas")
var ctx=c.getContext("2d")

在绘制前,给画笔设置颜色,你可以设置线条颜色 strokeStyle 或者填充颜色 fillStyle,然后绘制图形,以方形为例子。

1
2
ctx.fillStyle="#0000ff"
ctx.fillRect(20,20,150,100)

一个简单的图形绘制好了,你可以查阅手册,运用不同的图形组合来绘制更为复杂的图形,你也可以通过设置阴影和发光等特效让图形看起来更美观。

百度地图自定义图层

在百度地图v3.0版本类参考中,我们可以找到覆盖物类下的CanvasLayer,用于在地图上绘制自定义的canvas2D或WebGL图形。

定义一个新的canvas图层。

1
2
3
4
var canvasLayer = new BMap.CanvasLayer({
zIndex: 1,
update: canvasUpdate
})

其中zIndex为该自定义图层的层叠顺序,数值高的为上层,canvasUpdate为具体绘制逻辑。

定义canvasUpdate方法,通过this.canvas获取当前的canvas对象,且每次地图发生拖拽或缩放时,该图层会重新绘制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// 添加薄弱点模式下,全部站点绿色椭圆标注
var weaknodeallstationeLayer = new BMap.CanvasLayer({zIndex: 12,update: weaknodeallstationupdate});
function weaknodeallstationupdate() {
var c = this.canvas
var ctx = c.getContext("2d")
if (!ctx) {
return;
}
var zr = zrender.init(c)
if(allstation!=''){
zr.clear()
var p=allstation
for(i=0;i<p.length;i++){
var pixel = map.pointToPixel(new BMap.Point(p[i].lng,p[i].lat))
var c1='rgba(36,168,6,0.3)'
var c2='rgba(156,253,130,0.2)'
var c3='rgba(178,252,162,0.1)'
var ellipse1 = new zrender.Ellipse({
progressive: true,
shape: {
cx: pixel.x,
cy: pixel.y,
rx: ellipse1RX,
ry: ellipse1RY
},
id: p[i].node,
lng: p[i].lng,
lat: p[i].lat,
style: {
fill: c1,
lineWidth: 1*proportion
},
clickable: true
}).on('click', function (e) {
getStationInfo(this.id)
var stationLng = this.lng
var stationLat = this.lat
var stationPoint = new BMap.Point(stationLng,stationLat)
map.centerAndZoom(stationPoint, mapzoom+1);
var pixel = map.pointToPixel(stationPoint)
var winX = pixel.x
var winY = pixel.y
$(".station-level").hide()
setTimeout(function(){
$(".tc").show().css('top',winY-20).css('left',winX+10)
},200)
})
var ellipse2 = new zrender.Ellipse({
progressive: true,
shape: {
cx: pixel.x,
cy: pixel.y,
rx: ellipse2RX,
ry: ellipse2RY
},
id: p[i].node,
lng: p[i].lng,
lat: p[i].lat,
style: {
fill: c2,
lineWidth: 2*proportion
}
})
var ellipse3 = new zrender.Ellipse({
progressive: true,
shape: {
cx: pixel.x,
cy: pixel.y,
rx: ellipse3RX,
ry: ellipse3RY
},
id: p[i].node,
lng: p[i].lng,
lat: p[i].lat,
style: {
fill: c3,
lineWidth: 1*proportion
}
})
zr.resize()
zr.add(ellipse3)
zr.add(ellipse2)
zr.add(ellipse1)
}
}
}

在编写绘制逻辑的时候,绘制图形需要屏幕坐标作为起始位置和终止位置,我们在使用百度地图时,往往是知道经纬度坐标的,此时需要经纬度坐标转化为屏幕坐标来进行图形的定位。

1
2
3
4
5
var point = new BMap.Point( lng, lat )
var pixel = map.pointToPixel( point )

var winX = pixel.x
var winY = pixel.y

此时可以根据坐标点的屏幕坐标来计算你绘制图形的每个点坐标,绘制复杂图形。

图层绘制后,需要添加到地图中才能生效。canvas图层属于覆盖物类,可通过覆盖物添加到地图中。

1
map.addOverlay(canvasLayer)

此时自定义图层就添加成功了。