DrawingManager.js___百度地图API
-
1 /**2 * @fileoverview 百度地图的鼠标绘制工具,对外开放。3 * 允许用户在地图上点击完成鼠标绘制的功能。4 * 使用者可以自定义所绘制结果的相关样式,例如线宽、颜色、测线段距离、面积等等。5 * 主入口类是<a href="symbols/BMapLib.DrawingManager.html">DrawingManager</a>,6 * 基于Baidu Map API 1.4。7 *8 * @author Baidu Map Api Group 9 * @version 1.410 */11 12 /** 13 * @namespace BMap的所有library类均放在BMapLib命名空间下14 */15 var BMapLib = window.BMapLib = BMapLib || {};16 17 /**18 * 定义常量, 绘制的模式19 * @final {Number} DrawingType20 */21 var BMAP_DRAWING_MARKER = "marker", // 鼠标画点模式22 BMAP_DRAWING_POLYLINE = "polyline", // 鼠标画线模式23 BMAP_DRAWING_CIRCLE = "circle", // 鼠标画圆模式24 BMAP_DRAWING_RECTANGLE = "rectangle", // 鼠标画矩形模式25 BMAP_DRAWING_POLYGON = "polygon"; // 鼠标画多边形模式26 27 (function() {28 29 /**30 * 声明baidu包31 */32 var baidu = baidu || {guid : "$BAIDU$"};33 (function() {34 // 一些页面级别唯一的属性,需要挂载在window[baidu.guid]上35 window[baidu.guid] = {};36 37 /**38 * 将源对象的所有属性拷贝到目标对象中39 * @name baidu.extend40 * @function41 * @grammar baidu.extend(target, source)42 * @param {Object} target 目标对象43 * @param {Object} source 源对象44 * @returns {Object} 目标对象45 */46 baidu.extend = function (target, source) {47 for (var p in source) {48 if (source.hasOwnProperty(p)) {49 target[p] = source[p];50 }51 } 52 return target;53 };54 55 /**56 * @ignore57 * @namespace58 * @baidu.lang 对语言层面的封装,包括类型判断、模块扩展、继承基类以及对象自定义事件的支持。59 * @property guid 对象的唯一标识60 */61 baidu.lang = baidu.lang || {};62 63 /**64 * 返回一个当前页面的唯一标识字符串。65 * @function66 * @grammar baidu.lang.guid()67 * @returns {String} 当前页面的唯一标识字符串68 */69 baidu.lang.guid = function() {70 return "TANGRAM__" + (window[baidu.guid]._counter ++).toString(36);71 };72 73 window[baidu.guid]._counter = window[baidu.guid]._counter || 1;74 75 /**76 * 所有类的实例的容器77 * key为每个实例的guid78 */79 window[baidu.guid]._instances = window[baidu.guid]._instances || {};80 81 /**82 * Tangram继承机制提供的一个基类,用户可以通过继承baidu.lang.Class来获取它的属性及方法。83 * @function84 * @name baidu.lang.Class85 * @grammar baidu.lang.Class(guid)86 * @param {string} guid 对象的唯一标识87 * @meta standard88 * @remark baidu.lang.Class和它的子类的实例均包含一个全局唯一的标识guid。89 * guid是在构造函数中生成的,因此,继承自baidu.lang.Class的类应该直接或者间接调用它的构造函数。<br>90 * baidu.lang.Class的构造函数中产生guid的方式可以保证guid的唯一性,及每个实例都有一个全局唯一的guid。91 */92 baidu.lang.Class = function(guid) {93 this.guid = guid || baidu.lang.guid();94 window[baidu.guid]._instances[this.guid] = this;95 };96 97 window[baidu.guid]._instances = window[baidu.guid]._instances || {};98 99 /** 100 * 判断目标参数是否string类型或String对象 101 * @name baidu.lang.isString 102 * @function 103 * @grammar baidu.lang.isString(source) 104 * @param {Any} source 目标参数 105 * @shortcut isString 106 * @meta standard 107 * 108 * @returns {boolean} 类型判断结果 109 */ 110 baidu.lang.isString = function (source) { 111 return '[object String]' == Object.prototype.toString.call(source); 112 }; 113 114 /** 115 * 判断目标参数是否为function或Function实例 116 * @name baidu.lang.isFunction 117 * @function 118 * @grammar baidu.lang.isFunction(source) 119 * @param {Any} source 目标参数 120 * @returns {boolean} 类型判断结果 121 */ 122 baidu.lang.isFunction = function (source) { 123 return '[object Function]' == Object.prototype.toString.call(source); 124 }; 125 126 /** 127 * 重载了默认的toString方法,使得返回信息更加准确一些。 128 * @return {string} 对象的String表示形式 129 */ 130 baidu.lang.Class.prototype.toString = function(){ 131 return "[object " + (this._className || "Object" ) + "]"; 132 }; 133 134 /** 135 * 释放对象所持有的资源,主要是自定义事件。 136 * @name dispose 137 * @grammar obj.dispose() 138 */ 139 baidu.lang.Class.prototype.dispose = function(){ 140 delete window[baidu.guid]._instances[this.guid]; 141 for(var property in this){ 142 if (!baidu.lang.isFunction(this[property])) { 143 delete this[property]; 144 } 145 } 146 this.disposed = true; 147 }; 148 149 /** 150 * 自定义的事件对象。 151 * @function 152 * @name baidu.lang.Event 153 * @grammar baidu.lang.Event(type[, target]) 154 * @param {string} type 事件类型名称。为了方便区分事件和一个普通的方法,事件类型名称必须以"on"(小写)开头。 155 * @param {Object} [target]触发事件的对象 156 * @meta standard 157 * @remark 引入该模块,会自动为Class引入3个事件扩展方法:addEventListener、removeEventListener和dispatchEvent。 158 * @see baidu.lang.Class 159 */ 160 baidu.lang.Event = function (type, target) { 161 this.type = type; 162 this.returnValue = true; 163 this.target = target || null; 164 this.currentTarget = null; 165 }; 166 167 /** 168 * 注册对象的事件监听器。引入baidu.lang.Event后,Class的子类实例才会获得该方法。 169 * @grammar obj.addEventListener(type, handler[, key]) 170 * @param {string} type 自定义事件的名称 171 * @param {Function} handler 自定义事件被触发时应该调用的回调函数 172 * @param {string} [key] 为事件监听函数指定的名称,可在移除时使用。如果不提供,方法会默认为它生成一个全局唯一的key。 173 * @remark 事件类型区分大小写。如果自定义事件名称不是以小写"on"开头,该方法会给它加上"on"再进行判断,即"click"和"onclick"会被认为是同一种事件。 174 */ 175 baidu.lang.Class.prototype.addEventListener = function (type, handler, key) { 176 if (!baidu.lang.isFunction(handler)) { 177 return; 178 } 179 !this.__listeners && (this.__listeners = {}); 180 var t = this.__listeners, id; 181 if (typeof key == "string" && key) { 182 if (/[^\w\-]/.test(key)) { 183 throw("nonstandard key:" + key); 184 } else { 185 handler.hashCode = key; 186 id = key; 187 } 188 } 189 type.indexOf("on") != 0 && (type = "on" + type); 190 typeof t[type] != "object" && (t[type] = {}); 191 id = id || baidu.lang.guid(); 192 handler.hashCode = id; 193 t[type][id] = handler; 194 }; 195 196 /** 197 * 移除对象的事件监听器。引入baidu.lang.Event后,Class的子类实例才会获得该方法。 198 * @grammar obj.removeEventListener(type, handler) 199 * @param {string} type 事件类型 200 * @param {Function|string} handler 要移除的事件监听函数或者监听函数的key 201 * @remark 如果第二个参数handler没有被绑定到对应的自定义事件中,什么也不做。 202 */ 203 baidu.lang.Class.prototype.removeEventListener = function (type, handler) { 204 if (baidu.lang.isFunction(handler)) { 205 handler = handler.hashCode; 206 } else if (!baidu.lang.isString(handler)) { 207 return; 208 } 209 !this.__listeners && (this.__listeners = {}); 210 type.indexOf("on") != 0 && (type = "on" + type); 211 var t = this.__listeners; 212 if (!t[type]) { 213 return; 214 } 215 t[type][handler] && delete t[type][handler]; 216 }; 217 218 /** 219 * 派发自定义事件,使得绑定到自定义事件上面的函数都会被执行。引入baidu.lang.Event后,Class的子类实例才会获得该方法。 220 * @grammar obj.dispatchEvent(event, options) 221 * @param {baidu.lang.Event|String} event Event对象,或事件名称(1.1.1起支持) 222 * @param {Object} options 扩展参数,所含属性键值会扩展到Event对象上(1.2起支持) 223 * @remark 处理会调用通过addEventListenr绑定的自定义事件回调函数之外,还会调用直接绑定到对象上面的自定义事件。 224 * 例如:<br> 225 * myobj.onMyEvent = function(){}<br> 226 * myobj.addEventListener("onMyEvent", function(){}); 227 */ 228 baidu.lang.Class.prototype.dispatchEvent = function (event, options) { 229 if (baidu.lang.isString(event)) { 230 event = new baidu.lang.Event(event); 231 } 232 !this.__listeners && (this.__listeners = {}); 233 options = options || {}; 234 for (var i in options) { 235 event[i] = options[i]; 236 } 237 var i, t = this.__listeners, p = event.type; 238 event.target = event.target || this; 239 event.currentTarget = this; 240 p.indexOf("on") != 0 && (p = "on" + p); 241 baidu.lang.isFunction(this[p]) && this[p].apply(this, arguments); 242 if (typeof t[p] == "object") { 243 for (i in t[p]) { 244 t[p][i].apply(this, arguments); 245 } 246 } 247 return event.returnValue; 248 }; 249 250 /** 251 * 为类型构造器建立继承关系 252 * @name baidu.lang.inherits 253 * @function 254 * @grammar baidu.lang.inherits(subClass, superClass[, className]) 255 * @param {Function} subClass 子类构造器 256 * @param {Function} superClass 父类构造器 257 * @param {string} className 类名标识 258 * @remark 使subClass继承superClass的prototype, 259 * 因此subClass的实例能够使用superClass的prototype中定义的所有属性和方法。<br> 260 * 这个函数实际上是建立了subClass和superClass的原型链集成,并对subClass进行了constructor修正。<br> 261 * <strong>注意:如果要继承构造函数,需要在subClass里面call一下,具体见下面的demo例子</strong> 262 * @shortcut inherits 263 * @meta standard 264 * @see baidu.lang.Class 265 */ 266 baidu.lang.inherits = function (subClass, superClass, className) { 267 var key, proto, 268 selfProps = subClass.prototype, 269 clazz = new Function(); 270 clazz.prototype = superClass.prototype; 271 proto = subClass.prototype = new clazz(); 272 for (key in selfProps) { 273 proto[key] = selfProps[key]; 274 } 275 subClass.prototype.constructor = subClass; 276 subClass.superClass = superClass.prototype; 277 278 if ("string" == typeof className) { 279 proto._className = className; 280 } 281 }; 282 283 /** 284 * @ignore 285 * @namespace baidu.dom 操作dom的方法。 286 */ 287 baidu.dom = baidu.dom || {}; 288 289 /** 290 * 从文档中获取指定的DOM元素 291 * 292 * @param {string|HTMLElement} id 元素的id或DOM元素 293 * @meta standard 294 * @return {HTMLElement} DOM元素,如果不存在,返回null,如果参数不合法,直接返回参数 295 */ 296 baidu._g = baidu.dom._g = function (id) { 297 if (baidu.lang.isString(id)) { 298 return document.getElementById(id); 299 } 300 return id; 301 }; 302 303 /** 304 * 从文档中获取指定的DOM元素 305 * @name baidu.dom.g 306 * @function 307 * @grammar baidu.dom.g(id) 308 * @param {string|HTMLElement} id 元素的id或DOM元素 309 * @meta standard 310 * 311 * @returns {HTMLElement|null} 获取的元素,查找不到时返回null,如果参数不合法,直接返回参数 312 */ 313 baidu.g = baidu.dom.g = function (id) { 314 if ('string' == typeof id || id instanceof String) { 315 return document.getElementById(id); 316 } else if (id && id.nodeName && (id.nodeType == 1 || id.nodeType == 9)) { 317 return id; 318 } 319 return null; 320 }; 321 322 /** 323 * 在目标元素的指定位置插入HTML代码 324 * @name baidu.dom.insertHTML 325 * @function 326 * @grammar baidu.dom.insertHTML(element, position, html) 327 * @param {HTMLElement|string} element 目标元素或目标元素的id 328 * @param {string} position 插入html的位置信息,取值为beforeBegin,afterBegin,beforeEnd,afterEnd 329 * @param {string} html 要插入的html 330 * @remark 331 * 332 * 对于position参数,大小写不敏感<br> 333 * 参数的意思:beforeBegin<span>afterBegin this is span! beforeEnd</span> afterEnd <br /> 334 * 此外,如果使用本函数插入带有script标签的HTML字符串,script标签对应的脚本将不会被执行。 335 * 336 * @shortcut insertHTML 337 * @meta standard 338 * 339 * @returns {HTMLElement} 目标元素 340 */ 341 baidu.insertHTML = baidu.dom.insertHTML = function (element, position, html) { 342 element = baidu.dom.g(element); 343 var range,begin; 344 345 if (element.insertAdjacentHTML) { 346 element.insertAdjacentHTML(position, html); 347 } else { 348 // 这里不做"undefined" != typeof(HTMLElement) && !window.opera判断,其它浏览器将出错?! 349 // 但是其实做了判断,其它浏览器下等于这个函数就不能执行了 350 range = element.ownerDocument.createRange(); 351 // FF下range的位置设置错误可能导致创建出来的fragment在插入dom树之后html结构乱掉 352 // 改用range.insertNode来插入html, by wenyuxiang @ 2010-12-14. 353 position = position.toUpperCase(); 354 if (position == 'AFTERBEGIN' || position == 'BEFOREEND') { 355 range.selectNodeContents(element); 356 range.collapse(position == 'AFTERBEGIN'); 357 } else { 358 begin = position == 'BEFOREBEGIN'; 359 range[begin ? 'setStartBefore' : 'setEndAfter'](element); 360 range.collapse(begin); 361 } 362 range.insertNode(range.createContextualFragment(html)); 363 } 364 return element; 365 }; 366 367 /** 368 * 为目标元素添加className 369 * @name baidu.dom.addClass 370 * @function 371 * @grammar baidu.dom.addClass(element, className) 372 * @param {HTMLElement|string} element 目标元素或目标元素的id 373 * @param {string} className 要添加的className,允许同时添加多个class,中间使用空白符分隔 374 * @remark 375 * 使用者应保证提供的className合法性,不应包含不合法字符,className合法字符参考:http://www.w3.org/TR/CSS2/syndata.html。 376 * @shortcut addClass 377 * @meta standard 378 * 379 * @returns {HTMLElement} 目标元素 380 */ 381 baidu.ac = baidu.dom.addClass = function (element, className) { 382 element = baidu.dom.g(element); 383 var classArray = className.split(/\s+/), 384 result = element.className, 385 classMatch = " " + result + " ", 386 i = 0, 387 l = classArray.length; 388 389 for (; i < l; i++){ 390 if ( classMatch.indexOf( " " + classArray[i] + " " ) < 0 ) { 391 result += (result ? ' ' : '') + classArray[i]; 392 } 393 } 394 395 element.className = result; 396 return element; 397 }; 398 399 /** 400 * @ignore 401 * @namespace baidu.event 屏蔽浏览器差异性的事件封装。 402 * @property target 事件的触发元素 403 * @property pageX 鼠标事件的鼠标x坐标 404 * @property pageY 鼠标事件的鼠标y坐标 405 * @property keyCode 键盘事件的键值 406 */ 407 baidu.event = baidu.event || {}; 408 409 /** 410 * 事件监听器的存储表 411 * @private 412 * @meta standard 413 */ 414 baidu.event._listeners = baidu.event._listeners || []; 415 416 /** 417 * 为目标元素添加事件监听器 418 * @name baidu.event.on 419 * @function 420 * @grammar baidu.event.on(element, type, listener) 421 * @param {HTMLElement|string|window} element 目标元素或目标元素id 422 * @param {string} type 事件类型 423 * @param {Function} listener 需要添加的监听器 424 * @remark 425 * 1. 不支持跨浏览器的鼠标滚轮事件监听器添加<br> 426 * 2. 改方法不为监听器灌入事件对象,以防止跨iframe事件挂载的事件对象获取失败 427 * @shortcut on 428 * @meta standard 429 * @see baidu.event.un 430 * 431 * @returns {HTMLElement|window} 目标元素 432 */ 433 baidu.on = baidu.event.on = function (element, type, listener) { 434 type = type.replace(/^on/i, ''); 435 element = baidu._g(element); 436 var realListener = function (ev) { 437 // 1. 这里不支持EventArgument, 原因是跨frame的事件挂载 438 // 2. element是为了修正this 439 listener.call(element, ev); 440 }, 441 lis = baidu.event._listeners, 442 filter = baidu.event._eventFilter, 443 afterFilter, 444 realType = type; 445 type = type.toLowerCase(); 446 // filter过滤 447 if(filter && filter[type]){ 448 afterFilter = filter[type](element, type, realListener); 449 realType = afterFilter.type; 450 realListener = afterFilter.listener; 451 } 452 // 事件监听器挂载 453 if (element.addEventListener) { 454 element.addEventListener(realType, realListener, false); 455 } else if (element.attachEvent) { 456 element.attachEvent('on' + realType, realListener); 457 } 458 459 // 将监听器存储到数组中 460 lis[lis.length] = [element, type, listener, realListener, realType]; 461 return element; 462 }; 463 464 /** 465 * 为目标元素移除事件监听器 466 * @name baidu.event.un 467 * @function 468 * @grammar baidu.event.un(element, type, listener) 469 * @param {HTMLElement|string|window} element 目标元素或目标元素id 470 * @param {string} type 事件类型 471 * @param {Function} listener 需要移除的监听器 472 * @shortcut un 473 * @meta standard 474 * 475 * @returns {HTMLElement|window} 目标元素 476 */ 477 baidu.un = baidu.event.un = function (element, type, listener) { 478 element = baidu._g(element); 479 type = type.replace(/^on/i, '').toLowerCase(); 480 481 var lis = baidu.event._listeners, 482 len = lis.length, 483 isRemoveAll = !listener, 484 item, 485 realType, realListener; 486 487 //如果将listener的结构改成json 488 //可以节省掉这个循环,优化性能 489 //但是由于un的使用频率并不高,同时在listener不多的时候 490 //遍历数组的性能消耗不会对代码产生影响 491 //暂不考虑此优化 492 while (len--) { 493 item = lis[len]; 494 495 // listener存在时,移除element的所有以listener监听的type类型事件 496 // listener不存在时,移除element的所有type类型事件 497 if (item[1] === type 498 && item[0] === element 499 && (isRemoveAll || item[2] === listener)) { 500 realType = item[4]; 501 realListener = item[3]; 502 if (element.removeEventListener) { 503 element.removeEventListener(realType, realListener, false); 504 } else if (element.detachEvent) { 505 element.detachEvent('on' + realType, realListener); 506 } 507 lis.splice(len, 1); 508 } 509 } 510 return element; 511 }; 512 513 /** 514 * 获取event事件,解决不同浏览器兼容问题 515 * @param {Event} 516 * @return {Event} 517 */ 518 baidu.getEvent = baidu.event.getEvent = function (event) { 519 return window.event || event; 520 } 521 522 /** 523 * 获取event.target,解决不同浏览器兼容问题 524 * @param {Event} 525 * @return {Target} 526 */ 527 baidu.getTarget = baidu.event.getTarget = function (event) { 528 var event = baidu.getEvent(event); 529 return event.target || event.srcElement; 530 } 531 532 /** 533 * 阻止事件的默认行为 534 * @name baidu.event.preventDefault 535 * @function 536 * @grammar baidu.event.preventDefault(event) 537 * @param {Event} event 事件对象 538 * @meta standard 539 */ 540 baidu.preventDefault = baidu.event.preventDefault = function (event) { 541 var event = baidu.getEvent(event); 542 if (event.preventDefault) { 543 event.preventDefault(); 544 } else { 545 event.returnValue = false; 546 } 547 }; 548 549 /** 550 * 停止事件冒泡传播 551 * @param {Event} 552 */ 553 baidu.stopBubble = baidu.event.stopBubble = function (event) { 554 event = baidu.getEvent(event); 555 event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true; 556 } 557 558 })(); 559 560 /** 561 * @exports DrawingManager as BMapLib.DrawingManager 562 */ 563 var DrawingManager = 564 /** 565 * DrawingManager类的构造函数 566 * @class 鼠标绘制管理类,实现鼠标绘制管理的<b>入口</b>。 567 * 实例化该类后,即可调用该类提供的open 568 * 方法开启绘制模式状态。 569 * 也可加入工具栏进行选择操作。 570 * 571 * @constructor 572 * @param {Map} map Baidu map的实例对象 573 * @param {Json Object} opts 可选的输入参数,非必填项。可输入选项包括:<br /> 574 * {"<b>isOpen</b>" : {Boolean} 是否开启绘制模式 575 * <br />"<b>enableDrawingTool</b>" : {Boolean} 是否添加绘制工具栏控件,默认不添加 576 * <br />"<b>drawingToolOptions</b>" : {Json Object} 可选的输入参数,非必填项。可输入选项包括 577 * <br /> "<b>anchor</b>" : {ControlAnchor} 停靠位置、默认左上角 578 * <br /> "<b>offset</b>" : {Size} 偏移值。 579 * <br /> "<b>scale</b>" : {Number} 工具栏的缩放比例,默认为1 580 * <br /> "<b>drawingModes</b>" : {DrawingType<Array>} 工具栏上可以选择出现的绘制模式,将需要显示的DrawingType以数组型形式传入,如[BMAP_DRAWING_MARKER, BMAP_DRAWING_CIRCLE] 将只显示画点和画圆的选项 581 * <br />"<b>enableCalculate</b>" : {Boolean} 绘制是否进行测距(画线时候)、测面(画圆、多边形、矩形) 582 * <br />"<b>markerOptions</b>" : {CircleOptions} 所画的点的可选参数,参考api中的<a href="http://developer.baidu.com/map/reference/index.php?title=Class:%E6%80%BB%E7%B1%BB/%E8%A6%86%E7%9B%96%E7%89%A9%E7%B1%BB">对应类</a> 583 * <br />"<b>circleOptions</b>" : {CircleOptions} 所画的圆的可选参数,参考api中的<a href="http://developer.baidu.com/map/reference/index.php?title=Class:%E6%80%BB%E7%B1%BB/%E8%A6%86%E7%9B%96%E7%89%A9%E7%B1%BB">对应类</a> 584 * <br />"<b>polylineOptions</b>" : {CircleOptions} 所画的线的可选参数,参考api中的<a href="http://developer.baidu.com/map/reference/index.php?title=Class:%E6%80%BB%E7%B1%BB/%E8%A6%86%E7%9B%96%E7%89%A9%E7%B1%BB">对应类</a> 585 * <br />"<b>polygonOptions</b>" : {PolygonOptions} 所画的多边形的可选参数,参考api中的<a href="http://developer.baidu.com/map/reference/index.php?title=Class:%E6%80%BB%E7%B1%BB/%E8%A6%86%E7%9B%96%E7%89%A9%E7%B1%BB">对应类</a> 586 * <br />"<b>rectangleOptions</b>" : {PolygonOptions} 所画的矩形的可选参数,参考api中的<a href="http://developer.baidu.com/map/reference/index.php?title=Class:%E6%80%BB%E7%B1%BB/%E8%A6%86%E7%9B%96%E7%89%A9%E7%B1%BB">对应类</a> 587 * 588 * @example <b>参考示例:</b><br /> 589 * var map = new BMap.Map("container");<br />map.centerAndZoom(new BMap.Point(116.404, 39.915), 15);<br /> 590 * var myDrawingManagerObject = new BMapLib.DrawingManager(map, {isOpen: true, 591 * drawingType: BMAP_DRAWING_MARKER, enableDrawingTool: true, 592 * enableCalculate: false, 593 * drawingToolOptions: { 594 * anchor: BMAP_ANCHOR_TOP_LEFT, 595 * offset: new BMap.Size(5, 5), 596 * drawingTypes : [ 597 * BMAP_DRAWING_MARKER, 598 * BMAP_DRAWING_CIRCLE, 599 * BMAP_DRAWING_POLYLINE, 600 * BMAP_DRAWING_POLYGON, 601 * BMAP_DRAWING_RECTANGLE 602 * ] 603 * }, 604 * polylineOptions: { 605 * strokeColor: "#333" 606 * }); 607 */ 608 BMapLib.DrawingManager = function(map, opts){ 609 if (!map) { 610 return; 611 } 612 instances.push(this); 613 614 opts = opts || {}; 615 616 this._initialize(map, opts); 617 } 618 619 // 通过baidu.lang下的inherits方法,让DrawingManager继承baidu.lang.Class 620 baidu.lang.inherits(DrawingManager, baidu.lang.Class, "DrawingManager"); 621 622 /** 623 * 开启地图的绘制模式 624 * 625 * @example <b>参考示例:</b><br /> 626 * myDrawingManagerObject.open(); 627 */ 628 DrawingManager.prototype.open = function() { 629 // 判断绘制状态是否已经开启 630 if (this._isOpen == true){ 631 return true; 632 } 633 closeInstanceExcept(this); 634 635 this._open(); 636 } 637 638 /** 639 * 关闭地图的绘制状态 640 * 641 * @example <b>参考示例:</b><br /> 642 * myDrawingManagerObject.close(); 643 */ 644 DrawingManager.prototype.close = function() { 645 646 // 判断绘制状态是否已经开启 647 if (this._isOpen == false){ 648 return true; 649 } 650 651 this._close(); 652 } 653 654 /** 655 * 设置当前的绘制模式,参数DrawingType,为5个可选常量: 656 * <br/>BMAP_DRAWING_MARKER 画点 657 * <br/>BMAP_DRAWING_CIRCLE 画圆 658 * <br/>BMAP_DRAWING_POLYLINE 画线 659 * <br/>BMAP_DRAWING_POLYGON 画多边形 660 * <br/>BMAP_DRAWING_RECTANGLE 画矩形 661 * @param {DrawingType} DrawingType 662 * @return {Boolean} 663 * 664 * @example <b>参考示例:</b><br /> 665 * myDrawingManagerObject.setDrawingMode(BMAP_DRAWING_POLYLINE); 666 */ 667 DrawingManager.prototype.setDrawingMode = function(drawingType) { 668 //与当前模式不一样时候才进行重新绑定事件 669 if (this._drawingType != drawingType) { 670 closeInstanceExcept(this); 671 this._setDrawingMode(drawingType); 672 } 673 } 674 675 /** 676 * 获取当前的绘制模式 677 * @return {DrawingType} 绘制的模式 678 * 679 * @example <b>参考示例:</b><br /> 680 * alert(myDrawingManagerObject.getDrawingMode()); 681 */ 682 DrawingManager.prototype.getDrawingMode = function() { 683 return this._drawingType; 684 } 685 686 /** 687 * 打开距离或面积计算 688 * 689 * @example <b>参考示例:</b><br /> 690 * myDrawingManagerObject.enableCalculate(); 691 */ 692 DrawingManager.prototype.enableCalculate = function() { 693 this._enableCalculate = true; 694 this._addGeoUtilsLibrary(); 695 } 696 697 /** 698 * 关闭距离或面积计算 699 * 700 * @example <b>参考示例:</b><br /> 701 * myDrawingManagerObject.disableCalculate(); 702 */ 703 DrawingManager.prototype.disableCalculate = function() { 704 this._enableCalculate = false; 705 } 706 707 /** 708 * 鼠标绘制完成后,派发总事件的接口 709 * @name DrawingManager#overlaycomplete 710 * @event 711 * @param {Event Object} e 回调函数会返回event参数,包括以下返回值: 712 * <br />{"<b>drawingMode</b> : {DrawingType} 当前的绘制模式 713 * <br />"<b>overlay</b>:{Marker||Polyline||Polygon||Circle} 对应的绘制模式返回对应的覆盖物 714 * <br />"<b>calculate</b>:{Number} 需要开启计算模式才会返回这个值,当绘制线的时候返回距离、绘制多边形、圆、矩形时候返回面积,单位为米, 715 * <br />"<b>label</b>:{Label} 计算面积时候出现在Map上的Label对象 716 * 717 * @example <b>参考示例:</b> 718 * myDrawingManagerObject.addEventListener("overlaycomplete", function(e) { 719 * alert(e.drawingMode); 720 * alert(e.overlay); 721 * alert(e.calculate); 722 * alert(e.label); 723 * }); 724 */ 725 726 /** 727 * 绘制点完成后,派发的事件接口 728 * @name DrawingManager#markercomplete 729 * @event 730 * @param {Marker} overlay 回调函数会返回相应的覆盖物, 731 * <br />{"<b>overlay</b> : {Marker} 732 * 733 * @example <b>参考示例:</b> 734 * myDrawingManagerObject.addEventListener("circlecomplete", function(e, overlay) { 735 * alert(overlay); 736 * }); 737 */ 738 739 /** 740 * 绘制圆完成后,派发的事件接口 741 * @name DrawingManager#circlecomplete 742 * @event 743 * @param {Circle} overlay 回调函数会返回相应的覆盖物, 744 * <br />{"<b>overlay</b> : {Circle} 745 */ 746 747 /** 748 * 绘制线完成后,派发的事件接口 749 * @name DrawingManager#polylinecomplete 750 * @event 751 * @param {Polyline} overlay 回调函数会返回相应的覆盖物, 752 * <br />{"<b>overlay</b> : {Polyline} 753 */ 754 755 /** 756 * 绘制多边形完成后,派发的事件接口 757 * @name DrawingManager#polygoncomplete 758 * @event 759 * @param {Polygon} overlay 回调函数会返回相应的覆盖物, 760 * <br />{"<b>overlay</b> : {Polygon} 761 */ 762 763 /** 764 * 绘制矩形完成后,派发的事件接口 765 * @name DrawingManager#rectanglecomplete 766 * @event 767 * @param {Polygon} overlay 回调函数会返回相应的覆盖物, 768 * <br />{"<b>overlay</b> : {Polygon} 769 */ 770 771 /** 772 * 初始化状态 773 * @param {Map} 地图实例 774 * @param {Object} 参数 775 */ 776 DrawingManager.prototype._initialize = function(map, opts) { 777 778 /** 779 * map对象 780 * @private 781 * @type {Map} 782 */ 783 this._map = map; 784 785 /** 786 * 配置对象 787 * @private 788 * @type {Object} 789 */ 790 this._opts = opts; 791 792 /** 793 * 当前的绘制模式, 默认是绘制点 794 * @private 795 * @type {DrawingType} 796 */ 797 this._drawingType = opts.drawingMode || BMAP_DRAWING_MARKER; 798 799 /** 800 * 是否添加添加鼠标绘制工具栏面板 801 */ 802 if (opts.enableDrawingTool) { 803 var drawingTool = new DrawingTool(this, opts.drawingToolOptions); 804 this._drawingTool = drawingTool; 805 map.addControl(drawingTool); 806 } 807 808 //是否计算绘制出的面积 809 if (opts.enableCalculate === true) { 810 this.enableCalculate(); 811 } else { 812 this.disableCalculate(); 813 } 814 815 /** 816 * 是否已经开启了绘制状态 817 * @private 818 * @type {Boolean} 819 */ 820 this._isOpen = !!(opts.isOpen === true); 821 if (this._isOpen) { 822 this._open(); 823 } 824 825 this.markerOptions = opts.markerOptions || {}; 826 this.circleOptions = opts.circleOptions || {}; 827 this.polylineOptions = opts.polylineOptions || {}; 828 this.polygonOptions = opts.polygonOptions || {}; 829 this.rectangleOptions = opts.rectangleOptions || {}; 830 831 }, 832 833 /** 834 * 开启地图的绘制状态 835 * @return {Boolean},开启绘制状态成功,返回true;否则返回false。 836 */ 837 DrawingManager.prototype._open = function() { 838 839 this._isOpen = true; 840 841 //添加遮罩,所有鼠标操作都在这个遮罩上完成 842 if (!this._mask) { 843 this._mask = new Mask(); 844 } 845 this._map.addOverlay(this._mask); 846 this._setDrawingMode(this._drawingType); 847 848 } 849 850 /** 851 * 设置当前的绘制模式 852 * @param {DrawingType} 853 */ 854 DrawingManager.prototype._setDrawingMode = function(drawingType) { 855 856 this._drawingType = drawingType; 857 858 /** 859 * 开启编辑状态时候才重新进行事件绑定 860 */ 861 if (this._isOpen) { 862 //清空之前的自定义事件 863 this._mask.__listeners = {}; 864 865 switch (drawingType) { 866 case BMAP_DRAWING_MARKER: 867 this._bindMarker(); 868 break; 869 case BMAP_DRAWING_CIRCLE: 870 this._bindCircle(); 871 break; 872 case BMAP_DRAWING_POLYLINE: 873 case BMAP_DRAWING_POLYGON: 874 this._bindPolylineOrPolygon(); 875 break; 876 case BMAP_DRAWING_RECTANGLE: 877 this._bindRectangle(); 878 break; 879 } 880 } 881 882 /** 883 * 如果添加了工具栏,则也需要改变工具栏的样式 884 */ 885 if (this._drawingTool && this._isOpen) { 886 this._drawingTool.setStyleByDrawingMode(drawingType); 887 } 888 } 889 890 /** 891 * 关闭地图的绘制状态 892 * @return {Boolean},关闭绘制状态成功,返回true;否则返回false。 893 */ 894 DrawingManager.prototype._close = function() { 895 896 this._isOpen = false; 897 898 if (this._mask) { 899 this._map.removeOverlay(this._mask); 900 } 901 902 /** 903 * 如果添加了工具栏,则关闭时候将工具栏样式设置为拖拽地图 904 */ 905 if (this._drawingTool) { 906 this._drawingTool.setStyleByDrawingMode("hander"); 907 } 908 } 909 910 /** 911 * 绑定鼠标画点的事件 912 */ 913 DrawingManager.prototype._bindMarker = function() { 914 915 var me = this, 916 map = this._map, 917 mask = this._mask; 918 919 /** 920 * 鼠标点击的事件 921 */ 922 var clickAction = function (e) { 923 // 往地图上添加marker 924 var marker = new BMap.Marker(e.point, me.markerOptions); 925 map.addOverlay(marker); 926 me._dispatchOverlayComplete(marker); 927 } 928 929 mask.addEventListener('click', clickAction); 930 } 931 932 /** 933 * 绑定鼠标画圆的事件 934 */ 935 DrawingManager.prototype._bindCircle = function() { 936 937 var me = this, 938 map = this._map, 939 mask = this._mask, 940 circle = null, 941 centerPoint = null; //圆的中心点 942 943 /** 944 * 开始绘制圆形 945 */ 946 var startAction = function (e) { 947 centerPoint = e.point; 948 circle = new BMap.Circle(centerPoint, 0, me.circleOptions); 949 map.addOverlay(circle); 950 mask.enableEdgeMove(); 951 mask.addEventListener('mousemove', moveAction); 952 baidu.on(document, 'mouseup', endAction); 953 } 954 955 /** 956 * 绘制圆形过程中,鼠标移动过程的事件 957 */ 958 var moveAction = function(e) { 959 circle.setRadius(me._map.getDistance(centerPoint, e.point)); 960 } 961 962 /** 963 * 绘制圆形结束 964 */ 965 var endAction = function (e) { 966 var calculate = me._calculate(circle, e.point); 967 me._dispatchOverlayComplete(circle, calculate); 968 centerPoint = null; 969 mask.disableEdgeMove(); 970 mask.removeEventListener('mousemove', moveAction); 971 baidu.un(document, 'mouseup', endAction); 972 } 973 974 /** 975 * 鼠标点击起始点 976 */ 977 var mousedownAction = function (e) { 978 baidu.preventDefault(e); 979 baidu.stopBubble(e); 980 if (centerPoint == null) { 981 startAction(e); 982 } 983 } 984 985 mask.addEventListener('mousedown', mousedownAction); 986 } 987 988 /** 989 * 画线和画多边形相似性比较大,公用一个方法 990 */ 991 DrawingManager.prototype._bindPolylineOrPolygon = function() { 992 993 var me = this, 994 map = this._map, 995 mask = this._mask, 996 points = [], //用户绘制的点 997 drawPoint = null; //实际需要画在地图上的点 998 overlay = null, 999 isBinded = false; 1000 1001 /** 1002 * 鼠标点击的事件 1003 */ 1004 var startAction = function (e) { 1005 points.push(e.point); 1006 drawPoint = points.concat(points[points.length - 1]); 1007 if (points.length == 1) { 1008 if (me._drawingType == BMAP_DRAWING_POLYLINE) { 1009 overlay = new BMap.Polyline(drawPoint, me.polylineOptions); 1010 } else if (me._drawingType == BMAP_DRAWING_POLYGON) { 1011 overlay = new BMap.Polygon(drawPoint, me.polygonOptions); 1012 } 1013 map.addOverlay(overlay); 1014 } else { 1015 overlay.setPath(drawPoint); 1016 } 1017 if (!isBinded) { 1018 isBinded = true; 1019 mask.enableEdgeMove(); 1020 mask.addEventListener('mousemove', mousemoveAction); 1021 mask.addEventListener('dblclick', dblclickAction); 1022 } 1023 } 1024 1025 /** 1026 * 鼠标移动过程的事件 1027 */ 1028 var mousemoveAction = function(e) { 1029 overlay.setPositionAt(drawPoint.length - 1, e.point); 1030 } 1031 1032 /** 1033 * 鼠标双击的事件 1034 */ 1035 var dblclickAction = function (e) { 1036 baidu.stopBubble(e); 1037 isBinded = false; 1038 mask.disableEdgeMove(); 1039 mask.removeEventListener('mousemove', mousemoveAction); 1040 mask.removeEventListener('dblclick', dblclickAction); 1041 overlay.setPath(points); 1042 var calculate = me._calculate(overlay, points.pop()); 1043 me._dispatchOverlayComplete(overlay, calculate); 1044 points.length = 0; 1045 drawPoint.length = 0; 1046 } 1047 1048 mask.addEventListener('click', startAction); 1049 1050 //双击时候不放大地图级别 1051 mask.addEventListener('dblclick', function(e){ 1052 baidu.stopBubble(e); 1053 }); 1054 } 1055 1056 /** 1057 * 绑定鼠标画矩形的事件 1058 */ 1059 DrawingManager.prototype._bindRectangle = function() { 1060 1061 var me = this, 1062 map = this._map, 1063 mask = this._mask, 1064 polygon = null, 1065 startPoint = null; 1066 1067 /** 1068 * 开始绘制矩形 1069 */ 1070 var startAction = function (e) { 1071 baidu.stopBubble(e); 1072 baidu.preventDefault(e); 1073 startPoint = e.point; 1074 var endPoint = startPoint; 1075 polygon = new BMap.Polygon(me._getRectanglePoint(startPoint, endPoint), me.rectangleOptions); 1076 map.addOverlay(polygon); 1077 mask.enableEdgeMove(); 1078 mask.addEventListener('mousemove', moveAction); 1079 baidu.on(document, 'mouseup', endAction); 1080 } 1081 1082 /** 1083 * 绘制矩形过程中,鼠标移动过程的事件 1084 */ 1085 var moveAction = function(e) { 1086 polygon.setPath(me._getRectanglePoint(startPoint, e.point)); 1087 } 1088 1089 /** 1090 * 绘制矩形结束 1091 */ 1092 var endAction = function (e) { 1093 var calculate = me._calculate(polygon, polygon.getPath()[2]); 1094 me._dispatchOverlayComplete(polygon, calculate); 1095 startPoint = null; 1096 mask.disableEdgeMove(); 1097 mask.removeEventListener('mousemove', moveAction); 1098 baidu.un(document, 'mouseup', endAction); 1099 } 1100 1101 mask.addEventListener('mousedown', startAction); 1102 } 1103 1104 /** 1105 * 添加显示所绘制图形的面积或者长度 1106 * @param {overlay} 覆盖物 1107 * @param {point} 显示的位置 1108 */ 1109 DrawingManager.prototype._calculate = function (overlay, point) { 1110 var result = { 1111 data : 0, //计算出来的长度或面积 1112 label : null //显示长度或面积的label对象 1113 }; 1114 if (this._enableCalculate && BMapLib.GeoUtils) { 1115 var type = overlay.toString(); 1116 //不同覆盖物调用不同的计算方法 1117 switch (type) { 1118 case "[object Polyline]": 1119 result.data = BMapLib.GeoUtils.getPolylineDistance(overlay); 1120 break; 1121 case "[object Polygon]": 1122 result.data = BMapLib.GeoUtils.getPolygonArea(overlay); 1123 break; 1124 case "[object Circle]": 1125 var radius = overlay.getRadius(); 1126 result.data = Math.PI * radius * radius; 1127 break; 1128 } 1129 //一场情况处理 1130 if (!result.data || result.data < 0) { 1131 result.data = 0; 1132 } else { 1133 //保留2位小数位 1134 result.data = result.data.toFixed(2); 1135 } 1136 result.label = this._addLabel(point, result.data); 1137 } 1138 return result; 1139 } 1140 1141 /** 1142 * 开启测距和测面功能需要依赖于GeoUtils库 1143 * 所以这里判断用户是否已经加载,若未加载则用js动态加载 1144 */ 1145 DrawingManager.prototype._addGeoUtilsLibrary = function () { 1146 if (!BMapLib.GeoUtils) { 1147 var script = document.createElement('script'); 1148 script.setAttribute("type", "text/javascript"); 1149 script.setAttribute("src", 'http://api.map.baidu.com/library/GeoUtils/1.2/src/GeoUtils_min.js'); 1150 document.body.appendChild(script); 1151 } 1152 } 1153 1154 /** 1155 * 向地图中添加文本标注 1156 * @param {Point} 1157 * @param {String} 所以显示的内容 1158 */ 1159 DrawingManager.prototype._addLabel = function (point, content) { 1160 var label = new BMap.Label(content, { 1161 position: point 1162 }); 1163 this._map.addOverlay(label); 1164 return label; 1165 } 1166 1167 /** 1168 * 根据起终点获取矩形的四个顶点 1169 * @param {Point} 起点 1170 * @param {Point} 终点 1171 */ 1172 DrawingManager.prototype._getRectanglePoint = function (startPoint, endPoint) { 1173 return [ 1174 new BMap.Point(startPoint.lng,startPoint.lat), 1175 new BMap.Point(endPoint.lng,startPoint.lat), 1176 new BMap.Point(endPoint.lng,endPoint.lat), 1177 new BMap.Point(startPoint.lng,endPoint.lat) 1178 ]; 1179 } 1180 1181 /** 1182 * 派发事件 1183 */ 1184 DrawingManager.prototype._dispatchOverlayComplete = function (overlay, calculate) { 1185 var options = { 1186 'overlay' : overlay, 1187 'drawingMode' : this._drawingType, 1188 'calculate' : calculate.data || null, 1189 'label' : calculate.label || null 1190 }; 1191 this.dispatchEvent(this._drawingType + 'complete', overlay); 1192 this.dispatchEvent('overlaycomplete', options); 1193 } 1194 1195 /** 1196 * 创建遮罩对象 1197 */ 1198 function Mask(){ 1199 /** 1200 * 鼠标到地图边缘的时候是否自动平移地图 1201 */ 1202 this._enableEdgeMove = false; 1203 } 1204 1205 Mask.prototype = new BMap.Overlay(); 1206 1207 /** 1208 * 这里不使用api中的自定义事件,是为了更灵活使用 1209 */ 1210 Mask.prototype.dispatchEvent = baidu.lang.Class.prototype.dispatchEvent; 1211 Mask.prototype.addEventListener = baidu.lang.Class.prototype.addEventListener; 1212 Mask.prototype.removeEventListener = baidu.lang.Class.prototype.removeEventListener; 1213 1214 Mask.prototype.initialize = function(map){ 1215 var me = this; 1216 this._map = map; 1217 var div = this.container = document.createElement("div"); 1218 var size = this._map.getSize(); 1219 div.style.cssText = "position:absolute;background:url(about:blank);cursor:crosshair;width:" + size.width + "px;height:" + size.height + "px"; 1220 this._map.addEventListener('resize', function(e) { 1221 me._adjustSize(e.size); 1222 }); 1223 this._map.getPanes().floatPane.appendChild(div); 1224 this._bind(); 1225 return div; 1226 }; 1227 1228 Mask.prototype.draw = function() { 1229 var map = this._map, 1230 point = map.pixelToPoint(new BMap.Pixel(0, 0)), 1231 pixel = map.pointToOverlayPixel(point); 1232 this.container.style.left = pixel.x + "px"; 1233 this.container.style.top = pixel.y + "px"; 1234 }; 1235 1236 /** 1237 * 开启鼠标到地图边缘,自动平移地图 1238 */ 1239 Mask.prototype.enableEdgeMove = function() { 1240 this._enableEdgeMove = true; 1241 } 1242 1243 /** 1244 * 关闭鼠标到地图边缘,自动平移地图 1245 */ 1246 Mask.prototype.disableEdgeMove = function() { 1247 clearInterval(this._edgeMoveTimer); 1248 this._enableEdgeMove = false; 1249 } 1250 1251 /** 1252 * 绑定事件,派发自定义事件 1253 */ 1254 Mask.prototype._bind = function() { 1255 1256 var me = this, 1257 map = this._map, 1258 container = this.container, 1259 lastMousedownXY = null, 1260 lastClickXY = null; 1261 1262 /** 1263 * 根据event对象获取鼠标的xy坐标对象 1264 * @param {Event} 1265 * @return {Object} {x:e.x, y:e.y} 1266 */ 1267 var getXYbyEvent = function(e){ 1268 return { 1269 x : e.clientX, 1270 y : e.clientY 1271 } 1272 }; 1273 1274 var domEvent = function(e) { 1275 var type = e.type; 1276 e = baidu.getEvent(e); 1277 point = me.getDrawPoint(e); //当前鼠标所在点的地理坐标 1278 1279 var dispatchEvent = function(type) { 1280 e.point = point; 1281 me.dispatchEvent(e); 1282 } 1283 1284 if (type == "mousedown") { 1285 lastMousedownXY = getXYbyEvent(e); 1286 } 1287 1288 var nowXY = getXYbyEvent(e); 1289 //click经过一些特殊处理派发,其他同事件按正常的dom事件派发 1290 if (type == "click") { 1291 //鼠标点击过程不进行移动才派发click和dblclick 1292 if (Math.abs(nowXY.x - lastMousedownXY.x) < 5 && Math.abs(nowXY.y - lastMousedownXY.y) < 5 ) { 1293 if (!lastClickXY || !(Math.abs(nowXY.x - lastClickXY.x) < 5 && Math.abs(nowXY.y - lastClickXY.y) < 5)) { 1294 dispatchEvent('click'); 1295 lastClickXY = getXYbyEvent(e); 1296 } else { 1297 lastClickXY = null; 1298 } 1299 } 1300 } else { 1301 dispatchEvent(type); 1302 } 1303 } 1304 1305 /** 1306 * 将事件都遮罩层的事件都绑定到domEvent来处理 1307 */ 1308 var events = ['click', 'mousedown', 'mousemove', 'mouseup', 'dblclick'], 1309 index = events.length; 1310 while (index--) { 1311 baidu.on(container, events[index], domEvent); 1312 } 1313 1314 //鼠标移动过程中,到地图边缘后自动平移地图 1315 baidu.on(container, 'mousemove', function(e) { 1316 if (me._enableEdgeMove) { 1317 me.mousemoveAction(e); 1318 } 1319 }); 1320 }; 1321 1322 //鼠标移动过程中,到地图边缘后自动平移地图 1323 Mask.prototype.mousemoveAction = function(e) { 1324 function getClientPosition(e) { 1325 var clientX = e.clientX, 1326 clientY = e.clientY; 1327 if (e.changedTouches) { 1328 clientX = e.changedTouches[0].clientX; 1329 clientY = e.changedTouches[0].clientY; 1330 } 1331 return new BMap.Pixel(clientX, clientY); 1332 } 1333 1334 var map = this._map, 1335 me = this, 1336 pixel = map.pointToPixel(this.getDrawPoint(e)), 1337 clientPos = getClientPosition(e), 1338 offsetX = clientPos.x - pixel.x, 1339 offsetY = clientPos.y - pixel.y; 1340 pixel = new BMap.Pixel((clientPos.x - offsetX), (clientPos.y - offsetY)); 1341 this._draggingMovePixel = pixel; 1342 var point = map.pixelToPoint(pixel), 1343 eventObj = { 1344 pixel: pixel, 1345 point: point 1346 }; 1347 // 拖拽到地图边缘移动地图 1348 this._panByX = this._panByY = 0; 1349 if (pixel.x <= 20 || pixel.x >= map.width - 20 1350 || pixel.y <= 50 || pixel.y >= map.height - 10) { 1351 if (pixel.x <= 20) { 1352 this._panByX = 8; 1353 } else if (pixel.x >= map.width - 20) { 1354 this._panByX = -8; 1355 } 1356 if (pixel.y <= 50) { 1357 this._panByY = 8; 1358 } else if (pixel.y >= map.height - 10) { 1359 this._panByY = -8; 1360 } 1361 if (!this._edgeMoveTimer) { 1362 this._edgeMoveTimer = setInterval(function(){ 1363 map.panBy(me._panByX, me._panByY, {"noAnimation": true}); 1364 }, 30); 1365 } 1366 } else { 1367 if (this._edgeMoveTimer) { 1368 clearInterval(this._edgeMoveTimer); 1369 this._edgeMoveTimer = null; 1370 } 1371 } 1372 } 1373 1374 /* 1375 * 调整大小 1376 * @param {Size} 1377 */ 1378 Mask.prototype._adjustSize = function(size) { 1379 this.container.style.width = size.width + 'px'; 1380 this.container.style.height = size.height + 'px'; 1381 }; 1382 1383 /** 1384 * 获取当前绘制点的地理坐标 1385 * 1386 * @param {Event} e e对象 1387 * @return Point对象的位置信息 1388 */ 1389 Mask.prototype.getDrawPoint = function(e) { 1390 1391 var map = this._map, 1392 trigger = baidu.getTarget(e), 1393 x = e.offsetX || e.layerX || 0, 1394 y = e.offsetY || e.layerY || 0; 1395 if (trigger.nodeType != 1) trigger = trigger.parentNode; 1396 while (trigger && trigger != map.getContainer()) { 1397 if (!(trigger.clientWidth == 0 && 1398 trigger.clientHeight == 0 && 1399 trigger.offsetParent && trigger.offsetParent.nodeName == 'TD')) { 1400 x += trigger.offsetLeft || 0; 1401 y += trigger.offsetTop || 0; 1402 } 1403 trigger = trigger.offsetParent; 1404 } 1405 var pixel = new BMap.Pixel(x, y); 1406 var point = map.pixelToPoint(pixel); 1407 return point; 1408 1409 } 1410 1411 /** 1412 * 绘制工具面板,自定义控件 1413 */ 1414 function DrawingTool(drawingManager, drawingToolOptions) { 1415 this.drawingManager = drawingManager; 1416 1417 drawingToolOptions = this.drawingToolOptions = drawingToolOptions || {}; 1418 // 默认停靠位置和偏移量 1419 this.defaultAnchor = BMAP_ANCHOR_TOP_LEFT; 1420 this.defaultOffset = new BMap.Size(10, 10); 1421 1422 //默认所有工具栏都显示 1423 this.defaultDrawingModes = [ 1424 BMAP_DRAWING_MARKER, 1425 BMAP_DRAWING_CIRCLE, 1426 BMAP_DRAWING_POLYLINE, 1427 BMAP_DRAWING_POLYGON, 1428 BMAP_DRAWING_RECTANGLE 1429 ]; 1430 //工具栏可显示的绘制模式 1431 if (drawingToolOptions.drawingModes) { 1432 this.drawingModes = drawingToolOptions.drawingModes; 1433 } else { 1434 this.drawingModes = this.defaultDrawingModes 1435 } 1436 1437 //用户设置停靠位置和偏移量 1438 if (drawingToolOptions.anchor) { 1439 this.setAnchor(drawingToolOptions.anchor); 1440 } 1441 if (drawingToolOptions.offset) { 1442 this.setOffset(drawingToolOptions.offset); 1443 } 1444 } 1445 1446 // 通过JavaScript的prototype属性继承于BMap.Control 1447 DrawingTool.prototype = new BMap.Control(); 1448 1449 // 自定义控件必须实现自己的initialize方法,并且将控件的DOM元素返回 1450 // 在本方法中创建个div元素作为控件的容器,并将其添加到地图容器中 1451 DrawingTool.prototype.initialize = function(map){ 1452 // 创建一个DOM元素 1453 var container = this.container = document.createElement("div"); 1454 container.className = "BMapLib_Drawing"; 1455 //用来设置外层边框阴影 1456 var panel = this.panel = document.createElement("div"); 1457 panel.className = "BMapLib_Drawing_panel"; 1458 if (this.drawingToolOptions && this.drawingToolOptions.scale) { 1459 this._setScale(this.drawingToolOptions.scale); 1460 } 1461 container.appendChild(panel); 1462 // 添加内容 1463 panel.innerHTML = this._generalHtml(); 1464 //绑定事件 1465 this._bind(panel); 1466 // 添加DOM元素到地图中 1467 map.getContainer().appendChild(container); 1468 // 将DOM元素返回 1469 return container; 1470 } 1471 1472 //生成工具栏的html元素 1473 DrawingTool.prototype._generalHtml = function(map){ 1474 1475 //鼠标经过工具栏上的提示信息 1476 var tips = {}; 1477 tips["hander"] = "拖动地图"; 1478 tips[BMAP_DRAWING_MARKER] = "画点"; 1479 tips[BMAP_DRAWING_CIRCLE] = "画圆"; 1480 tips[BMAP_DRAWING_POLYLINE] = "画折线"; 1481 tips[BMAP_DRAWING_POLYGON] = "画多边形"; 1482 tips[BMAP_DRAWING_RECTANGLE] = "画矩形"; 1483 1484 var getItem = function(className, drawingType) { 1485 return '<a class="' + className + '" drawingType="' + drawingType + '" href="javascript:void(0)" title="' + tips[drawingType] + '" οnfοcus="this.blur()"></a>'; 1486 } 1487 1488 var html = []; 1489 html.push(getItem("BMapLib_box BMapLib_hander", "hander")); 1490 for (var i = 0, len = this.drawingModes.length; i < len; i++) { 1491 var classStr = 'BMapLib_box BMapLib_' + this.drawingModes[i]; 1492 if (i == len-1) { 1493 classStr += ' BMapLib_last'; 1494 } 1495 html.push(getItem(classStr, this.drawingModes[i])); 1496 } 1497 return html.join(''); 1498 } 1499 1500 /** 1501 * 设置工具栏的缩放比例 1502 */ 1503 DrawingTool.prototype._setScale = function(scale){ 1504 var width = 390, 1505 height = 50, 1506 ml = -parseInt((width - width * scale) / 2, 10), 1507 mt = -parseInt((height - height * scale) / 2, 10); 1508 this.container.style.cssText = [ 1509 "-moz-transform: scale(" + scale + ");", 1510 "-o-transform: scale(" + scale + ");", 1511 "-webkit-transform: scale(" + scale + ");", 1512 "transform: scale(" + scale + ");", 1513 "margin-left:" + ml + "px;", 1514 "margin-top:" + mt + "px;", 1515 "*margin-left:0px;", //ie6、7 1516 "*margin-top:0px;", //ie6、7 1517 "margin-left:0px\\0;", //ie8 1518 "margin-top:0px\\0;", //ie8 1519 //ie下使用滤镜 1520 "filter: progid:DXImageTransform.Microsoft.Matrix(", 1521 "M11=" + scale + ",", 1522 "M12=0,", 1523 "M21=0,", 1524 "M22=" + scale + ",", 1525 "SizingMethod='auto expand');" 1526 ].join(''); 1527 } 1528 1529 //绑定工具栏的事件 1530 DrawingTool.prototype._bind = function(panel){ 1531 var me = this; 1532 baidu.on(this.panel, 'click', function (e) { 1533 var target = baidu.getTarget(e); 1534 var drawingType = target.getAttribute('drawingType'); 1535 me.setStyleByDrawingMode(drawingType); 1536 me._bindEventByDraingMode(drawingType); 1537 }); 1538 } 1539 1540 //设置工具栏当前选中的项样式 1541 DrawingTool.prototype.setStyleByDrawingMode = function(drawingType){ 1542 if (!drawingType) { 1543 return; 1544 } 1545 var boxs = this.panel.getElementsByTagName("a"); 1546 for (var i = 0, len = boxs.length; i < len; i++) { 1547 var box = boxs[i]; 1548 if (box.getAttribute('drawingType') == drawingType) { 1549 var classStr = "BMapLib_box BMapLib_" + drawingType + "_hover"; 1550 if (i == len - 1) { 1551 classStr += " BMapLib_last"; 1552 } 1553 box.className = classStr; 1554 } else { 1555 box.className = box.className.replace(/_hover/, ""); 1556 } 1557 } 1558 } 1559 1560 //设置工具栏当前选中的项样式 1561 DrawingTool.prototype._bindEventByDraingMode = function(drawingType){ 1562 var drawingManager = this.drawingManager; 1563 //点在拖拽地图的按钮上 1564 if (drawingType == "hander") { 1565 drawingManager.close(); 1566 } else { 1567 drawingManager.setDrawingMode(drawingType); 1568 drawingManager.open(); 1569 } 1570 } 1571 1572 //用来存储用户实例化出来的drawingmanager对象 1573 var instances = []; 1574 1575 /* 1576 * 关闭其他实例的绘制模式 1577 * @param {DrawingManager} 当前的实例 1578 */ 1579 function closeInstanceExcept(instance) { 1580 var index = instances.length; 1581 while (index--) { 1582 if (instances[index] != instance) { 1583 instances[index].close(); 1584 } 1585 } 1586 } 1587 1588 })(); 1589
DrawingManager.js___百度地图API相关推荐
- C#调用百度地图API入门解决BMap未定义问题
本文主要是最近帮助好友研究JavaScript的百度地图API,同时显示到C# Winform界面.同时遇到了BMap未定义的错误(BMap is not defined)及解决方法.以前写过基于An ...
- baidumap api MySQL_百度地图API
本文我将从如何使用地图API(本文以百度为例,谷歌类似)开始,往后的扩展行的内容详见后续文章. 1.打开链接http://developer.baidu.com/map/jshome.htm 这里有很 ...
- 项目一、调用百度地图api实现电子围栏和报警信息关联
前段时间香克斯去实习去了,由于一些原因只实习了12天,不过第一次实习,觉得还是有必要记录一下.事先声明,这个博客也是获得同意的,目前这个项目完成度还不是很高,有的地方我的想法不成熟的,希望大家多多提意 ...
- 百度地图API(三)电子围栏—地图点击事件创建多边形
百度地图API(四)电子围栏-DrawingManager 分析 电子围栏:顾名思义就是一个多边形,然后终端或者其他什么东西在这个围栏中,如果离开围栏则通知离开了围栏,而做这个电子围栏应该就是鼠标点击 ...
- 【百度地图api】前端 百度地图添加地理围栏
需求:添加教练场区域,在百度地图上选择多边形电子围栏,保存坐标: 主要参考百度地图api: 遇到的小坑:注意绘制百度地图多边形时,传入的坐标数组的结构!!! 相对来说比较简单,百度api已经很详细了. ...
- 【百度地图API】——如何用label制作简易的房产标签
摘要: 最近,API爱好者们纷纷说,自定义marker太复杂了!不仅定义复杂,连所有的dom事件都要自己重新定义.有没有快速简易创建房产标签的方法呢? 答案当然是有的啦~ 我们可以利用label嘛! ...
- 【百度地图API】如何制作班级地理通讯录?LBS通讯录
原文:[百度地图API]如何制作班级地理通讯录?LBS通讯录 摘要:班级通讯录必备的功能,比如人员列表,人员地理位置标注,展示复杂信息窗口,公交和驾车等.一般班级人员都不会超过300个,因为可以高效地 ...
- baidumap api MySQL_百度地图API开发笔记一(基础篇)
什么是百度地图API? 百度地图API是一套由JavaScript语言编写的应用程序接口,它能够帮助您在网站中构建功能丰富.交互性强的地图应用.百度地图API包含了构建地图基本功能的各种接口,提供了诸 ...
- 微信小程序城市定位(百度地图API)
概述 微信小程序提供一些API(地址)用于获取当前用户的地理位置等信息,但无论是wx.getLocation,还是wx.chooseLocation均没有单独的字段表示国家与城市信息,仅有经纬度信息. ...
最新文章
- android 断开蓝牙连接,如何在android中连接和断开扬声器蓝牙
- Selector 概念
- python tkinter选择路径控件_如何使用tkinter在Python中选择目录并存储位置
- [转]Vue基于vue-quill-editor富文本编辑器使用心得
- win10系统打开更新服务器失败,Win10系统中Windows Update服务的启动方法
- 如何制作数据透视表?超详细教程为你解答
- 苹果电脑隐藏桌面图标
- 计算机专业与等差数列的联系,数列期末复习
- Java学习记录——错题总结(十五)
- 鸡兔同笼问题的python解法
- win10 蓝牙耳机 音量太小
- 回首2015年小文codeRoad
- 2021易烊千玺高考成绩查询,2021高考进入倒计时 考生后援团送上祝福
- java 邻接矩阵_Java中的邻接矩阵
- CAD软件绘图如何提高效率 (上)
- [多线程]亚马逊图书排名查询
- TICK回测研究一,每日批量获取行情
- logistic regression识别真假币
- DTSE Tech Talk丨第3期:解密数据隔离方案,让SaaS应用开发更轻松
- 三十而立,从零开始学ios开发(十一):Tab Bars和Pickers