【地图】【二】构建强大的Editor类(百度篇)

  1. 1. 原因
  2. 2. 原理
  3. 3. 特性
  4. 4. 百度实例
  5. 5. 总结

文章所有涉及到的内容均可以在 https://gitee.com/zhoyq/examples/tree/master/mapExt 中获取。本文会先后以百度地图v3.0和高德地图v1.4.5为基础进行进行开发。

原因

百度地图可以在对象上直接启动和关闭编辑,比较方便。由于之前写的曲线覆盖物没有在对象上挂载编辑方法所以针对曲线覆盖物写了这个编辑器类,并且适配了所有覆盖物,以简化编辑操作。

原理

使用原有覆盖物,在其基础上创建一个新的覆盖物,同步更新数据。

特性

一次编辑多个覆盖物,不区分覆盖物类型。

百度实例

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
  // 程序里用到一些别名 自己比较熟悉的 也可以不用这一步 同时修改那部分代码即可
// 增加一些方法名的别名
BMap.Map.prototype.bind = BMap.Map.prototype.addEventListener;
BMap.Map.prototype.unbind = BMap.Map.prototype.removeEventListener;

BMap.Marker.prototype.bind = BMap.Marker.prototype.addEventListener;
BMap.Marker.prototype.unbind = BMap.Marker.prototype.removeEventListener;

BMap.Polygon.prototype.bind = BMap.Polygon.prototype.addEventListener;
BMap.Polygon.prototype.unbind = BMap.Polygon.prototype.removeEventListener;

BMap.Circle.prototype.bind = BMap.Circle.prototype.addEventListener;
BMap.Circle.prototype.unbind = BMap.Circle.prototype.removeEventListener;

BMap.Polyline.prototype.bind = BMap.Polyline.prototype.addEventListener;
BMap.Polyline.prototype.unbind = BMap.Polyline.prototype.removeEventListener;

// 控制点对象
// 用于存储生成的控制点信息
// 内部使用类 一般不会在外部调用
function ControlPoint(obj,type,map,num,count,cp,ref){
this._obj = obj; // 所属对象
this._type = type; // 类型
this._map = map; // 所属地图对象
this._key = num; // 这个值和数组里的位置对应
this._keyNum = count;//总数
if(cp){
this._entity = cp; // 控制点
this._map.addOverlay(this._entity);
this._entity.hide();
}
if(ref){
this._ref = ref; // 参考
this._map.addOverlay(this._ref);
this._ref.hide();
}
var me = this;
if(me._ref&&me._entity){
function __ddd(e){
var path = me._ref.getPath();
path[me._key] = me._entity.getPosition();
me._ref.setPath(path);
}
me._entity.bind('dragstart',__ddd);
me._entity.bind('dragging',__ddd);
me._entity.bind('dragend',__ddd);
}
}

// 圆形的控制对象
function ControlCircle(obj,type,map,num,count,ref,center,point){ // center,point 是圆形控制器点
this._obj = obj; // 所属对象
this._type = type; // 类型
this._map = map; // 所属地图对象
this._key = num; // 这个值和数组里的位置对应
this._keyNum = count;//总数
if(ref){
this._ref = ref; // 参考
this._map.addOverlay(this._ref);
this._ref.hide();
}
if(center){
this._center = center;
this._map.addOverlay(this._center);
this._center.hide();
}
if(point){
this._point = point;
this._map.addOverlay(this._point);
this._point.hide();
}
var me = this;
if(center&&point&&ref){
function __cdd(e){
// 移动中心 获取中心位置 获取两点距离 重设圆心半径
var buf = me._center.getPosition();
var dis = BMapLib.GeoUtils.getDistance(me._center.getPosition(),me._point.getPosition());
me._ref.setCenter(buf);
me._ref.setRadius(dis);
}
function __pdd(e){
// 移动边界 获取距离 重设半径即可
var dis = BMapLib.GeoUtils.getDistance(me._center.getPosition(),me._point.getPosition());
me._ref.setRadius(dis);
}
me._center.bind('dragstart',__cdd);
me._center.bind('dragging',__cdd);
me._center.bind('dragend',__cdd);
me._point.bind('dragstart',__pdd);
me._point.bind('dragging',__pdd);
me._point.bind('dragend',__pdd);
}
}

// 曲线的控制对象
function ControlCurve(obj,type,map,num,count,ref,mainPoint,cp1,cp2){
this._obj = obj; // 所属对象
this._type = type; // 类型
this._map = map; // 所属地图对象
this._key = num; // 这个值和数组里的位置对应
this._keyNum = count;//总数
this._lineOpt = {
strokeColor:'#f00',
strokeWeight:2,
strokeOpacity:0.6,
strokeStyle:'dashed'
};
if(ref){
this._ref = ref; // 参考
this._map.addOverlay(this._ref);
this._ref.hide();
}
if(mainPoint){
this._mp = mainPoint;
this._map.addOverlay(this._mp);
this._mp.hide();
}
if(cp1){
this._cp1 = cp1;
this._cp1_mp = new BMap.Polyline([this._mp.getPosition(),this._cp1.getPosition()],this._lineOpt);
this._map.addOverlay(this._cp1);
this._map.addOverlay(this._cp1_mp);
this._cp1_mp.hide();
this._cp1.hide();
}
if(cp2){
this._cp2 = cp2;
this._cp2_mp = new BMap.Polyline([this._mp.getPosition(),this._cp2.getPosition()],this._lineOpt);
this._map.addOverlay(this._cp2);
this._map.addOverlay(this._cp2_mp);
this._cp2_mp.hide();
this._cp2.hide();
}
var me = this;
var preMP = me._mp.getPosition();
var preCP1,preCP2;
if(me._mp){
// 前一个位置和下一个位置
if(me._cp1) preCP1 = me._cp1.getPosition();
if(me._cp2) preCP2 = me._cp2.getPosition();
function __mds(e){
// 获取到点所在的位置
var posi = me._mp.getPosition();
var offsetx = posi.lng - preMP.lng;
var offsety = posi.lat - preMP.lat;
// 如果有cp1 重置cp1的位置 (和点mp联动) 设置cp1_mp的path 设置曲线的path
if(me._cp1) {
me._cp1.setPosition(new BMap.Point(preCP1.lng+offsetx,preCP1.lat+offsety));
me._cp1_mp.setPath([me._mp.getPosition(),me._cp1.getPosition()]);
preCP1 = me._cp1.getPosition();
}
// cp2 同理
if(me._cp2) {
me._cp2.setPosition(new BMap.Point(preCP2.lng+offsetx,preCP2.lat+offsety));
me._cp2_mp.setPath([me._mp.getPosition(),me._cp2.getPosition()]);
preCP2 = me._cp2.getPosition();
}
var cl = me._obj.getCommandList();
if(cl[me._key]._c=='M') cl[me._key]._params[0] = me._mp.getPosition();
if(cl[me._key]._c=='C') cl[me._key]._params[2] = me._mp.getPosition();
if(me._cp1) cl[me._key]._params[1] = me._cp1.getPosition();
if(me._cp2) cl[me._key+1]._params[0] = me._cp2.getPosition();
me._ref.setCommandList(cl);
preMP = me._mp.getPosition();
}
me._mp.bind('dragstart',__mds);
me._mp.bind('dragging',__mds);
me._mp.bind('dragend',__mds);
}
if(me._cp1){
function __cds1(e){
// 获取点的位置 获取命令列表 修改变动部分
me._cp1_mp.setPath([me._mp.getPosition(),me._cp1.getPosition()]);
preCP1 = me._cp1.getPosition();
var cl = me._obj.getCommandList();
cl[me._key]._params[1] = me._cp1.getPosition();
me._ref.setCommandList(cl);
}
me._cp1.bind('dragstart',__cds1);
me._cp1.bind('dragging',__cds1);
me._cp1.bind('dragend',__cds1);
}
if(me._cp2){
function __cds2(e){
me._cp2_mp.setPath([me._mp.getPosition(),me._cp2.getPosition()]);
preCP2 = me._cp2.getPosition();
var cl = me._obj.getCommandList();
cl[me._key+1]._params[0] = me._cp2.getPosition();
me._ref.setCommandList(cl);
}
me._cp2.bind('dragstart',__cds2);
me._cp2.bind('dragging',__cds2);
me._cp2.bind('dragend',__cds2);
}

}
// 编辑器类
function Editor(){
this._cp = new Array();// 控制点
this._defaultIcon = new BMap.Icon('mousetool_point.png',new BMap.Size(10,10));
this._blankIcon = new BMap.Icon('blank.gif',new BMap.Size(1,1));
this._markerOpt = {
icon:this._defaultIcon,
enableDragging:true
};
this._lineOpt = {
strokeColor:'#f00',
strokeWeight:2,
strokeOpacity:0.8,
strokeStyle:'solid'
};
this._circleflag = 0; //圆形的编辑模式 默认是圆形
}
// 添加需要编辑的图形
Editor.prototype.edit = function(obj){
if(obj instanceof BMap.Marker){
var type = "Marker";
var map = obj.getMap();
if(map==null) return ;
var num = 0; // 因为是一个点所以只有一个点
var count = 1;

var controlPoint = new BMap.Marker(obj.getPosition(),this._markerOpt);
controlPoint.setShadow(this._blankIcon);
var cp = new ControlPoint(obj,type,map,num,count,controlPoint);
this._cp.push(cp);
}else if(obj instanceof BMap.Polyline){
var type = "Polyline";
var map = obj.getMap();
if(map==null) return ;
var path = obj.getPath();
var count = path.length;
var num = 0;
var ref = new BMap.Polyline(path,this._lineOpt);
for( ; num<count ; num++ ){
var controlPoint = new BMap.Marker(path[num],this._markerOpt);
controlPoint.setShadow(this._blankIcon);
var cp = new ControlPoint(obj,type,map,num,count,controlPoint,ref);
this._cp.push(cp);
}
}else if(obj instanceof BMap.Polygon && !(obj instanceof BMap.Circle)){
var type = "Polygon";
var map = obj.getMap();
if(map==null) return ;
var path = obj.getPath();
var count = path.length;
var num = 0;
var ref = new BMap.Polygon(path,this._lineOpt);
for( ; num<count ; num++ ){
var controlPoint = new BMap.Marker(path[num],this._markerOpt);
controlPoint.setShadow(this._blankIcon);
var cp = new ControlPoint(obj,type,map,num,count,controlPoint,ref);
this._cp.push(cp);
}
}else if(obj instanceof BMap.Circle){
if(this._circleflag==0){
var type = "Circle";
var map = obj.getMap();
if(map==null) return ;
var point = obj.getPath()[30];
var center = obj.getCenter();
var radius = obj.getRadius();
var ref = new BMap.Circle(center,radius,this._lineOpt);
var count = 0;
var num = 0;
var cp1 = new BMap.Marker(center,this._markerOpt);
var cp2 = new BMap.Marker(point,this._markerOpt);
var cp = new ControlCircle(obj,type,map,num,count,ref,cp1,cp2);
this._cp.push(cp);
}else if(this._circleflag==1){
var type = "Polygon";
var map = obj.getMap();
if(map==null) return ;
var path = obj.getPath();
var count = path.length;
var num = 0;
var ref = new BMap.Polygon(path,this._lineOpt);
for( ; num<count ; num++ ){
var controlPoint = new BMap.Marker(path[num],this._markerOpt);
controlPoint.setShadow(this._blankIcon);
var cp = new ControlPoint(obj,type,map,num,count,controlPoint,ref);
this._cp.push(cp);
}
}
}else if(obj instanceof BMap.Curve){
var type = "Curve";
var map = obj.getMap();
if(map==null) return ;
var cl = obj.getCommandList(); // 命令点
var num = 0;
var count = cl.length;
var ref = new BMap.Curve(cl,{
"stroke-width":2,
"cursor":"pointer",
"stroke":"#f00",
"stroke-opacity":1
});
for(;num<count;num++){
var c = cl[num]; //控制点
// 判断命令
if(c._c=='M'){
var mp = new BMap.Marker(c._params[0],this._markerOpt);// 主要点

if(num+1<count&&cl[num+1]._c=='C'){ // 下一个是C的时候
var cp2 = new BMap.Marker(cl[num+1]._params[0],this._markerOpt);
var cc = new ControlCurve(obj,type,map,num,count,ref,mp,undefined,cp2);
this._cp.push(cc);
}else{ // 下一个不是C的时候 目前只支持M C
var cc = new ControlCurve(obj,type,map,num,count,ref,mp);
this._cp.push(cc);
}
}else if(c._c=='C'){
var mp = new BMap.Marker(c._params[2],this._markerOpt);
var cp1 = new BMap.Marker(c._params[1],this._markerOpt);
if(num+1<count&&cl[num+1]._c=='C'){ // 有下一个并且是C的时候
var cp2 = new BMap.Marker(cl[num+1]._params[0],this._markerOpt);
var cc = new ControlCurve(obj,type,map,num,count,ref,mp,cp1,cp2);
this._cp.push(cc);
}else{
var cc = new ControlCurve(obj,type,map,num,count,ref,mp,cp1);
this._cp.push(cc);
}
}
}
}
};
// 隐藏元图形 以编辑模式显示新的图形
Editor.prototype.open = function(){
for(var i=0;i<this._cp.length;i++){
var cp = this._cp[i];
if(cp._type == 'Marker'){
// 隐藏图形
cp._obj.hide();
//添加控制图形
cp._entity.show();
}else if(cp._type == 'Polyline'){
cp._obj.hide();
cp._entity.show();
cp._ref.show();
}else if(cp._type == 'Polygon'){
cp._obj.hide();
cp._entity.show();
cp._ref.show();
}else if(cp._type == 'Circle'){
cp._obj.hide();
cp._center.show();
cp._point.show();
cp._ref.show();
}else if(cp._type == 'Curve'){
cp._obj.hide();
cp._mp.show();
if(cp._cp1){
cp._cp1.show();
cp._cp1_mp.show();
}
if(cp._cp2){
cp._cp2.show();
cp._cp2_mp.show();
}
cp._ref.show();
}
}
};
// 将编辑好的图形 赋值并重新显示
Editor.prototype.close = function(){
for(var i=0;i<this._cp.length;i++){
var cp = this._cp[i];
if(cp._type == 'Marker'){
cp._obj.setPosition(cp._entity.getPosition());
cp._entity.hide();
cp._obj.show();
}else if(cp._type == 'Polyline'){
cp._obj.setPath(cp._ref.getPath());
cp._entity.hide();
cp._ref.hide();
cp._obj.show();
}else if(cp._type == 'Polygon'){
cp._obj.setPath(cp._ref.getPath());
cp._entity.hide();
cp._ref.hide();
cp._obj.show();
}else if(cp._type == 'Circle'){
cp._obj.setPath(cp._ref.getPath());
cp._center.hide();
cp._point.hide();
cp._ref.hide();
cp._obj.show();
}else if(cp._type == 'Curve'){
cp._obj.setCommandList(cp._ref.getCommandList());
cp._mp.hide();
if(cp._cp1){
cp._cp1.hide();
cp._cp1_mp.hide();
}
if(cp._cp2){
cp._cp2.hide();
cp._cp2_mp.hide();
}
cp._ref.hide();
cp._obj.show();
}
}
};
Editor.prototype.circleEditStyle = function(flag){
this._circleflag = flag;
};
// 需要在编辑之前设置
BMap.BMap_EDITOR_CIRCLE_EDIT_TYPE_1 = 0;
BMap.BMap_EDITOR_CIRCLE_EDIT_TYPE_2 = 1;
BMap.Editor = Editor;

源码 实例

  1. 同样需要注意解决坐标漂移的bug
  2. 需要引用 <script src="http://api.map.baidu.com/library/GeoUtils/1.2/src/GeoUtils.js"></script> 获取坐标几何计算能力

总结

通过增加Editor类,可以不用考虑图形类型,可以方便的直接编辑。如果有什么意见或者建议可以直接发邮件联系我。谢谢。

欢迎访问博客地址:https://www.zhoyq.com