/* eslint-disable */ /** * @fileoverview 百度地图的鼠标绘制工具,对外开放。 * 允许用户在地图上点击完成鼠标绘制的功能。 * 使用者可以自定义所绘制结果的相关样式,例如线宽、颜色、测线段距离、面积等等。 * 主入口类是DrawingManager, * 基于Baidu Map API GL 1.0。 * * @author Baidu Map Api Group * @version 1.0 */ /** * @namespace BMapGL的所有library类均放在BMapGLLib命名空间下 */ var BMapGLLib = window.BMapGLLib = BMapGLLib || {}; /** * 定义常量, 绘制的模式 * @final {Number} DrawingType */ var BMAP_DRAWING_MARKER = "marker", // 鼠标画点模式 BMAP_DRAWING_POLYLINE = "polyline", // 鼠标画线模式 BMAP_DRAWING_CIRCLE = "circle", // 鼠标画圆模式 BMAP_DRAWING_RECTANGLE = "rectangle", // 鼠标画矩形模式 BMAP_DRAWING_POLYGON = "polygon"; // 鼠标画多边形模式 (function() { /** * 声明baidu包 */ var baidu = baidu || { guid: '$BAIDU$' }; (function () { // 一些页面级别唯一的属性,需要挂载在window[baidu.guid]上 window[baidu.guid] = {}; /** * 将源对象的所有属性拷贝到目标对象中 * @name baidu.extend * @function * @grammar baidu.extend(target, source) * @param {Object} target 目标对象 * @param {Object} source 源对象 * @returns {Object} 目标对象 */ baidu.extend = function (target, source) { for (var p in source) { if (source.hasOwnProperty(p)) { target[p] = source[p]; } } return target; }; /** * @ignore * @namespace * @baidu.lang 对语言层面的封装,包括类型判断、模块扩展、继承基类以及对象自定义事件的支持。 * @property guid 对象的唯一标识 */ baidu.lang = baidu.lang || {}; /** * 返回一个当前页面的唯一标识字符串。 * @function * @grammar baidu.lang.guid() * @returns {String} 当前页面的唯一标识字符串 */ baidu.lang.guid = function () { return 'TANGRAM__' + (window[baidu.guid]._counter++).toString(36); }; window[baidu.guid]._counter = window[baidu.guid]._counter || 1; /** * 所有类的实例的容器 * key为每个实例的guid */ window[baidu.guid]._instances = window[baidu.guid]._instances || {}; /** * Tangram继承机制提供的一个基类,用户可以通过继承baidu.lang.Class来获取它的属性及方法。 * @function * @name baidu.lang.Class * @grammar baidu.lang.Class(guid) * @param {string} guid 对象的唯一标识 * @meta standard * @remark baidu.lang.Class和它的子类的实例均包含一个全局唯一的标识guid。 * guid是在构造函数中生成的,因此,继承自baidu.lang.Class的类应该直接或者间接调用它的构造函数。
* baidu.lang.Class的构造函数中产生guid的方式可以保证guid的唯一性,及每个实例都有一个全局唯一的guid。 */ baidu.lang.Class = function (guid) { this.guid = guid || baidu.lang.guid(); window[baidu.guid]._instances[this.guid] = this; }; window[baidu.guid]._instances = window[baidu.guid]._instances || {}; /** * 判断目标参数是否string类型或String对象 * @name baidu.lang.isString * @function * @grammar baidu.lang.isString(source) * @param {Any} source 目标参数 * @shortcut isString * @meta standard * * @returns {boolean} 类型判断结果 */ baidu.lang.isString = function (source) { return '[object String]' == Object.prototype.toString.call(source); }; /** * 判断目标参数是否为function或Function实例 * @name baidu.lang.isFunction * @function * @grammar baidu.lang.isFunction(source) * @param {Any} source 目标参数 * @returns {boolean} 类型判断结果 */ baidu.lang.isFunction = function (source) { return '[object Function]' == Object.prototype.toString.call(source); }; /** * 重载了默认的toString方法,使得返回信息更加准确一些。 * @return {string} 对象的String表示形式 */ baidu.lang.Class.prototype.toString = function () { return '[object ' + (this._className || 'Object') + ']'; }; /** * 释放对象所持有的资源,主要是自定义事件。 * @name dispose * @grammar obj.dispose() */ baidu.lang.Class.prototype.dispose = function () { delete window[baidu.guid]._instances[this.guid]; for (var property in this) { if (!baidu.lang.isFunction(this[property])) { delete this[property]; } } this.disposed = true; }; /** * 自定义的事件对象。 * @function * @name baidu.lang.Event * @grammar baidu.lang.Event(type[, target]) * @param {string} type 事件类型名称。为了方便区分事件和一个普通的方法,事件类型名称必须以"on"(小写)开头。 * @param {Object} [target]触发事件的对象 * @meta standard * @remark 引入该模块,会自动为Class引入3个事件扩展方法:addEventListener、removeEventListener和dispatchEvent。 * @see baidu.lang.Class */ baidu.lang.Event = function (type, target) { this.type = type; this.returnValue = true; this.target = target || null; this.currentTarget = null; }; /** * 注册对象的事件监听器。引入baidu.lang.Event后,Class的子类实例才会获得该方法。 * @grammar obj.addEventListener(type, handler[, key]) * @param {string} type 自定义事件的名称 * @param {Function} handler 自定义事件被触发时应该调用的回调函数 * @param {string} [key] 为事件监听函数指定的名称,可在移除时使用。如果不提供,方法会默认为它生成一个全局唯一的key。 * @remark 事件类型区分大小写。如果自定义事件名称不是以小写"on"开头,该方法会给它加上"on"再进行判断,即"click"和"onclick"会被认为是同一种事件。 */ baidu.lang.Class.prototype.addEventListener = function (type, handler, key) { if (!baidu.lang.isFunction(handler)) { return; } !this.__listeners && (this.__listeners = {}); var t = this.__listeners, id; if (typeof key == 'string' && key) { if (/[^\w\-]/.test(key)) { throw ('nonstandard key:' + key); } else { handler.hashCode = key; id = key; } } type.indexOf('on') != 0 && (type = 'on' + type); typeof t[type] != 'object' && (t[type] = {}); id = id || baidu.lang.guid(); handler.hashCode = id; t[type][id] = handler; }; /** * 移除对象的事件监听器。引入baidu.lang.Event后,Class的子类实例才会获得该方法。 * @grammar obj.removeEventListener(type, handler) * @param {string} type 事件类型 * @param {Function|string} handler 要移除的事件监听函数或者监听函数的key * @remark 如果第二个参数handler没有被绑定到对应的自定义事件中,什么也不做。 */ baidu.lang.Class.prototype.removeEventListener = function (type, handler) { if (baidu.lang.isFunction(handler)) { handler = handler.hashCode; } else if (!baidu.lang.isString(handler)) { return; } !this.__listeners && (this.__listeners = {}); type.indexOf('on') != 0 && (type = 'on' + type); var t = this.__listeners; if (!t[type]) { return; } t[type][handler] && delete t[type][handler]; }; /** * 派发自定义事件,使得绑定到自定义事件上面的函数都会被执行。引入baidu.lang.Event后,Class的子类实例才会获得该方法。 * @grammar obj.dispatchEvent(event, options) * @param {baidu.lang.Event|String} event Event对象,或事件名称(1.1.1起支持) * @param {Object} options 扩展参数,所含属性键值会扩展到Event对象上(1.2起支持) * @remark 处理会调用通过addEventListenr绑定的自定义事件回调函数之外,还会调用直接绑定到对象上面的自定义事件。 * 例如:
* myobj.onMyEvent = function(){}
* myobj.addEventListener("onMyEvent", function(){}); */ baidu.lang.Class.prototype.dispatchEvent = function (event, options) { if (baidu.lang.isString(event)) { event = new baidu.lang.Event(event); } !this.__listeners && (this.__listeners = {}); options = options || {}; for (var i in options) { event[i] = options[i]; } var i, t = this.__listeners, p = event.type; event.target = event.target || this; event.currentTarget = this; p.indexOf('on') != 0 && (p = 'on' + p); baidu.lang.isFunction(this[p]) && this[p].apply(this, arguments); if (typeof t[p] == 'object') { for (i in t[p]) { t[p][i].apply(this, arguments); } } return event.returnValue; }; /** * 为类型构造器建立继承关系 * @name baidu.lang.inherits * @function * @grammar baidu.lang.inherits(subClass, superClass[, className]) * @param {Function} subClass 子类构造器 * @param {Function} superClass 父类构造器 * @param {string} className 类名标识 * @remark 使subClass继承superClass的prototype, * 因此subClass的实例能够使用superClass的prototype中定义的所有属性和方法。
* 这个函数实际上是建立了subClass和superClass的原型链集成,并对subClass进行了constructor修正。
* 注意:如果要继承构造函数,需要在subClass里面call一下,具体见下面的demo例子 * @shortcut inherits * @meta standard * @see baidu.lang.Class */ baidu.lang.inherits = function (subClass, superClass, className) { var key, proto, selfProps = subClass.prototype, clazz = new Function(); clazz.prototype = superClass.prototype; proto = subClass.prototype = new clazz(); for (key in selfProps) { proto[key] = selfProps[key]; } subClass.prototype.constructor = subClass; subClass.superClass = superClass.prototype; if ('string' == typeof className) { proto._className = className; } }; /** * @ignore * @namespace baidu.dom 操作dom的方法。 */ baidu.dom = baidu.dom || {}; /** * 从文档中获取指定的DOM元素 * * @param {string|HTMLElement} id 元素的id或DOM元素 * @meta standard * @return {HTMLElement} DOM元素,如果不存在,返回null,如果参数不合法,直接返回参数 */ baidu._g = baidu.dom._g = function (id) { if (baidu.lang.isString(id)) { return document.getElementById(id); } return id; }; /** * 从文档中获取指定的DOM元素 * @name baidu.dom.g * @function * @grammar baidu.dom.g(id) * @param {string|HTMLElement} id 元素的id或DOM元素 * @meta standard * * @returns {HTMLElement|null} 获取的元素,查找不到时返回null,如果参数不合法,直接返回参数 */ baidu.g = baidu.dom.g = function (id) { if ('string' == typeof id || id instanceof String) { return document.getElementById(id); } else if (id && id.nodeName && (id.nodeType == 1 || id.nodeType == 9)) { return id; } return null; }; /** * 在目标元素的指定位置插入HTML代码 * @name baidu.dom.insertHTML * @function * @grammar baidu.dom.insertHTML(element, position, html) * @param {HTMLElement|string} element 目标元素或目标元素的id * @param {string} position 插入html的位置信息,取值为beforeBegin,afterBegin,beforeEnd,afterEnd * @param {string} html 要插入的html * @remark * * 对于position参数,大小写不敏感
* 参数的意思:beforeBegin<span>afterBegin this is span! beforeEnd</span> afterEnd
* 此外,如果使用本函数插入带有script标签的HTML字符串,script标签对应的脚本将不会被执行。 * * @shortcut insertHTML * @meta standard * * @returns {HTMLElement} 目标元素 */ baidu.insertHTML = baidu.dom.insertHTML = function (element, position, html) { element = baidu.dom.g(element); var range, begin; if (element.insertAdjacentHTML) { element.insertAdjacentHTML(position, html); } else { // 这里不做"undefined" != typeof(HTMLElement) && !window.opera判断,其它浏览器将出错?! // 但是其实做了判断,其它浏览器下等于这个函数就不能执行了 range = element.ownerDocument.createRange(); // FF下range的位置设置错误可能导致创建出来的fragment在插入dom树之后html结构乱掉 // 改用range.insertNode来插入html, by wenyuxiang @ 2010-12-14. position = position.toUpperCase(); if (position == 'AFTERBEGIN' || position == 'BEFOREEND') { range.selectNodeContents(element); range.collapse(position == 'AFTERBEGIN'); } else { begin = position == 'BEFOREBEGIN'; range[begin ? 'setStartBefore' : 'setEndAfter'](element); range.collapse(begin); } range.insertNode(range.createContextualFragment(html)); } return element; }; /** * 为目标元素添加className * @name baidu.dom.addClass * @function * @grammar baidu.dom.addClass(element, className) * @param {HTMLElement|string} element 目标元素或目标元素的id * @param {string} className 要添加的className,允许同时添加多个class,中间使用空白符分隔 * @remark * 使用者应保证提供的className合法性,不应包含不合法字符,className合法字符参考:http://www.w3.org/TR/CSS2/syndata.html。 * @shortcut addClass * @meta standard * * @returns {HTMLElement} 目标元素 */ baidu.ac = baidu.dom.addClass = function (element, className) { element = baidu.dom.g(element); var classArray = className.split(/\s+/), result = element.className, classMatch = ' ' + result + ' ', i = 0, l = classArray.length; for (; i < l; i++) { if (classMatch.indexOf(' ' + classArray[i] + ' ') < 0) { result += (result ? ' ' : '') + classArray[i]; } } element.className = result; return element; }; /** * @ignore * @namespace baidu.event 屏蔽浏览器差异性的事件封装。 * @property target 事件的触发元素 * @property pageX 鼠标事件的鼠标x坐标 * @property pageY 鼠标事件的鼠标y坐标 * @property keyCode 键盘事件的键值 */ baidu.event = baidu.event || {}; /** * 事件监听器的存储表 * @private * @meta standard */ baidu.event._listeners = baidu.event._listeners || []; /** * 为目标元素添加事件监听器 * @name baidu.event.on * @function * @grammar baidu.event.on(element, type, listener) * @param {HTMLElement|string|window} element 目标元素或目标元素id * @param {string} type 事件类型 * @param {Function} listener 需要添加的监听器 * @remark * 1. 不支持跨浏览器的鼠标滚轮事件监听器添加
* 2. 改方法不为监听器灌入事件对象,以防止跨iframe事件挂载的事件对象获取失败 * @shortcut on * @meta standard * @see baidu.event.un * * @returns {HTMLElement|window} 目标元素 */ baidu.on = baidu.event.on = function (element, type, listener) { type = type.replace(/^on/i, ''); element = baidu._g(element); var realListener = function (ev) { // 1. 这里不支持EventArgument, 原因是跨frame的事件挂载 // 2. element是为了修正this listener.call(element, ev); }, lis = baidu.event._listeners, filter = baidu.event._eventFilter, afterFilter, realType = type; type = type.toLowerCase(); // filter过滤 if (filter && filter[type]) { afterFilter = filter[type](element, type, realListener); realType = afterFilter.type; realListener = afterFilter.listener; } // 事件监听器挂载 if (element.addEventListener) { element.addEventListener(realType, realListener, false); } else if (element.attachEvent) { element.attachEvent('on' + realType, realListener); } // 将监听器存储到数组中 lis[lis.length] = [element, type, listener, realListener, realType]; return element; }; /** * 为目标元素移除事件监听器 * @name baidu.event.un * @function * @grammar baidu.event.un(element, type, listener) * @param {HTMLElement|string|window} element 目标元素或目标元素id * @param {string} type 事件类型 * @param {Function} listener 需要移除的监听器 * @shortcut un * @meta standard * * @returns {HTMLElement|window} 目标元素 */ baidu.un = baidu.event.un = function (element, type, listener) { element = baidu._g(element); type = type.replace(/^on/i, '').toLowerCase(); var lis = baidu.event._listeners, len = lis.length, isRemoveAll = !listener, item, realType, realListener; // 如果将listener的结构改成json // 可以节省掉这个循环,优化性能 // 但是由于un的使用频率并不高,同时在listener不多的时候 // 遍历数组的性能消耗不会对代码产生影响 // 暂不考虑此优化 while (len--) { item = lis[len]; // listener存在时,移除element的所有以listener监听的type类型事件 // listener不存在时,移除element的所有type类型事件 if (item[1] === type && item[0] === element && (isRemoveAll || item[2] === listener)) { realType = item[4]; realListener = item[3]; if (element.removeEventListener) { element.removeEventListener(realType, realListener, false); } else if (element.detachEvent) { element.detachEvent('on' + realType, realListener); } lis.splice(len, 1); } } return element; }; /** * 获取event事件,解决不同浏览器兼容问题 * @param {Event} * @return {Event} */ baidu.getEvent = baidu.event.getEvent = function (event) { return window.event || event; }; /** * 获取event.target,解决不同浏览器兼容问题 * @param {Event} * @return {Target} */ baidu.getTarget = baidu.event.getTarget = function (event) { var event = baidu.getEvent(event); return event.target || event.srcElement; }; /** * 阻止事件的默认行为 * @name baidu.event.preventDefault * @function * @grammar baidu.event.preventDefault(event) * @param {Event} event 事件对象 * @meta standard */ baidu.preventDefault = baidu.event.preventDefault = function (event) { var event = baidu.getEvent(event); if (event.preventDefault) { event.preventDefault(); } else { event.returnValue = false; } }; /** * 停止事件冒泡传播 * @param {Event} */ baidu.stopBubble = baidu.event.stopBubble = function (event) { event = baidu.getEvent(event); event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true; }; /** * 判断是否为ie浏览器 * @property ie ie版本号 * @grammar baidu.browser.ie * @meta standard * @shortcut ie * @see baidu.browser.firefox,baidu.browser.safari,baidu.browser.opera,baidu.browser.chrome,baidu.browser.maxthon */ baidu.browser = baidu.browser || {}; if (/msie (\d+\.\d)/i.test(navigator.userAgent)) { //IE 8下,以documentMode为准 //在百度模板中,可能会有$,防止冲突,将$1 写成 \x241 baidu.browser.ie = baidu.ie = document.documentMode || + RegExp['\x241']; } })(); /** * @exports DrawingManager as BMapGLLib.DrawingManager */ var DrawingManager = /** * DrawingManager类的构造函数 * @class 鼠标绘制管理类,实现鼠标绘制管理的入口。 * 实例化该类后,即可调用该类提供的open * 方法开启绘制模式状态。 * 也可加入工具栏进行选择操作。 * * @constructor * @param {Map} map Baidu map的实例对象 * @param {Json Object} opts 可选的输入参数,非必填项。可输入选项包括:
* {"isOpen" : {Boolean} 是否开启绘制模式 *
"enableDrawingTool" : {Boolean} 是否添加绘制工具栏控件,默认不添加 *
"drawingToolOptions" : {Json Object} 可选的输入参数,非必填项。可输入选项包括 *
      "anchor" : {ControlAnchor} 停靠位置、默认左上角 *
      "offset" : {Size} 偏移值。 *
      "scale" : {Number} 工具栏的缩放比例,默认为1 *
      "drawingModes" : {DrawingType} 工具栏上可以选择出现的绘制模式,将需要显示的DrawingType以数组型形式传入,如[BMAP_DRAWING_MARKER, BMAP_DRAWING_CIRCLE] 将只显示画点和画圆的选项 *
"enableCalculate" : {Boolean} 绘制是否进行测距(画线时候)、测面(画圆、多边形、矩形) *
"markerOptions" : {MarkerOptions} 所画的点的可选参数,参考api中的对应类 *
"circleOptions" : {CircleOptions} 所画的圆的可选参数,参考api中的对应类 *
"polylineOptions" : {PolylineOptions} 所画的线的可选参数,参考api中的对应类 *
"polygonOptions" : {PolygonOptions} 所画的多边形的可选参数,参考api中的对应类 *
"rectangleOptions" : {PolygonOptions} 所画的矩形的可选参数,参考api中的对应类 * * @example 参考示例:
* var map = new BMap.Map("container");
map.centerAndZoom(new BMap.Point(116.404, 39.915), 15);
* var myDrawingManagerObject = new BMapGLLib.DrawingManager(map, {isOpen: true, * drawingType: BMAP_DRAWING_MARKER, enableDrawingTool: true, * enableCalculate: false, * drawingToolOptions: { * anchor: BMAP_ANCHOR_TOP_LEFT, * offset: new BMap.Size(5, 5), * drawingModes : [ * BMAP_DRAWING_MARKER, * BMAP_DRAWING_CIRCLE, * BMAP_DRAWING_POLYLINE, * BMAP_DRAWING_POLYGON, * BMAP_DRAWING_RECTANGLE * ] * }, * polylineOptions: { * strokeColor: "#333" * }); */ BMapGLLib.DrawingManager = function (map, opts) { if (!map) { return; } instances.push(this); opts = opts || {}; this.overlays = []; // 用来存储覆盖物 this._initialize(map, opts); }; // 通过baidu.lang下的inherits方法,让DrawingManager继承baidu.lang.Class baidu.lang.inherits(DrawingManager, baidu.lang.Class, 'DrawingManager'); /** * 开启地图的绘制模式 * * @example 参考示例:
* myDrawingManagerObject.open(); */ DrawingManager.prototype.open = function () { // 判断绘制状态是否已经开启 if (this._isOpen == true) { return true; } closeInstanceExcept(this); this._open(); }; /** * 关闭地图的绘制状态 * * @example 参考示例:
* myDrawingManagerObject.close(); */ DrawingManager.prototype.close = function () { // 判断绘制状态是否已经开启 if (this._isOpen == false) { return true; } var me = this; this._close(); me._map.removeOverlay(tip_label); setTimeout(function () { me._map.enableDoubleClickZoom(); }, 2000); }; /** * 设置当前的绘制模式,参数DrawingType,为5个可选常量: *
BMAP_DRAWING_MARKER 画点 *
BMAP_DRAWING_CIRCLE 画圆 *
BMAP_DRAWING_POLYLINE 画线 *
BMAP_DRAWING_POLYGON 画多边形 *
BMAP_DRAWING_RECTANGLE 画矩形 * @param {DrawingType} DrawingType * @return {Boolean} * * @example 参考示例:
* myDrawingManagerObject.setDrawingMode(BMAP_DRAWING_POLYLINE); */ DrawingManager.prototype.setDrawingMode = function (drawingType) { // 与当前模式不一样时候才进行重新绑定事件 if (this._drawingType != drawingType) { closeInstanceExcept(this); this._setDrawingMode(drawingType); } }; /** * 获取当前的绘制模式 * @return {DrawingType} 绘制的模式 * * @example 参考示例:
* alert(myDrawingManagerObject.getDrawingMode()); */ DrawingManager.prototype.getDrawingMode = function () { return this._drawingType; }; /** * 打开距离或面积计算 * * @example 参考示例:
* myDrawingManagerObject.enableCalculate(); */ DrawingManager.prototype.enableCalculate = function () { this._enableCalculate = true; this._addGeoUtilsLibrary(); // 异步调用GeoUtils }; /** * 关闭距离或面积计算 * * @example 参考示例:
* myDrawingManagerObject.disableCalculate(); */ DrawingManager.prototype.disableCalculate = function () { this._enableCalculate = false; }; /** * 打开吸附功能 */ DrawingManager.prototype.enableSorption = function() { this._enableSorption = true; }; /** * 关闭吸附功能 */ DrawingManager.prototype.disableSorption = function() { this._enableSorption = false; }; /** * 打开gpc功能 */ DrawingManager.prototype.enableGpc = function() { this._enableGpc = true; this._addGPCLibrary(); // 异步调用gpc }; /** * 关闭gpc功能 */ DrawingManager.prototype.disableGpc = function() { this._enableGpc = false; }; /** * 获取所有绘制的覆盖物 */ DrawingManager.prototype.getOverlays = function() { return this.overlays; }; DrawingManager.prototype.addOverlayData = function(overlay) { return this.overlays.push(overlay); }; DrawingManager.prototype.setOverlaysData = function(overlays) { return this.overlays = overlays; }; /** * 清除指定覆盖物数据 */ DrawingManager.prototype.clearOverlayData = function(overlay) { var map = this._map; for (var i = 0; i < this.overlays.length; i++) { if (this.overlays[i] === overlay) { this.overlays.splice(i, 1); return overlay; } } }; /** * 清除指定覆盖物 */ DrawingManager.prototype.clearOverlay = function(overlay) { var map = this._map; var overlay = this.clearOverlayData(overlay); if (overlay) { map.removeOverlay(overlay); } }; /** * 清除所有绘制的覆盖物 */ DrawingManager.prototype.clearOverlays = function() { var map = this._map; this.overlays.forEach(function (overlay) { map.removeOverlay(overlay); }); this.overlays.length = 0; }; /** * 鼠标绘制完成后,派发总事件的接口 * @name DrawingManager#overlaycomplete * @event * @param {Event Object} e 回调函数会返回event参数,包括以下返回值: *
{"drawingMode : {DrawingType} 当前的绘制模式 *
"overlay:{Marker||Polyline||Polygon||Circle} 对应的绘制模式返回对应的覆盖物 *
"calculate:{Number} 需要开启计算模式才会返回这个值,当绘制线的时候返回距离、绘制多边形、圆、矩形时候返回面积,单位为米, *
"label:{Label} 计算面积时候出现在Map上的Label对象 * * @example 参考示例: * myDrawingManagerObject.addEventListener("overlaycomplete", function(e) { * alert(e.drawingMode); * alert(e.overlay); * alert(e.calculate); * alert(e.label); * }); */ /** * 绘制点完成后,派发的事件接口 * @name DrawingManager#markercomplete * @event * @param {Marker} overlay 回调函数会返回相应的覆盖物, *
{"overlay : {Marker} * * @example 参考示例: * myDrawingManagerObject.addEventListener("circlecomplete", function(e, overlay) { * alert(overlay); * }); */ /** * 绘制圆完成后,派发的事件接口 * @name DrawingManager#circlecomplete * @event * @param {Circle} overlay 回调函数会返回相应的覆盖物, *
{"overlay : {Circle} */ /** * 绘制线完成后,派发的事件接口 * @name DrawingManager#polylinecomplete * @event * @param {Polyline} overlay 回调函数会返回相应的覆盖物, *
{"overlay : {Polyline} */ /** * 绘制多边形完成后,派发的事件接口 * @name DrawingManager#polygoncomplete * @event * @param {Polygon} overlay 回调函数会返回相应的覆盖物, *
{"overlay : {Polygon} */ /** * 绘制矩形完成后,派发的事件接口 * @name DrawingManager#rectanglecomplete * @event * @param {Polygon} overlay 回调函数会返回相应的覆盖物, *
{"overlay : {Polygon} */ /** * 初始化状态 * @param {Map} 地图实例 * @param {Object} 参数 */ DrawingManager.prototype._initialize = function (map, opts) { /** * map对象 * @private * @type {Map} */ this._map = map; /** * 配置对象 * @private * @type {Object} */ this._opts = opts; /** * 当前的绘制模式, 默认是绘制点 * @private * @type {DrawingType} */ this._drawingType = opts.drawingMode || BMAP_DRAWING_MARKER; /** * 是否添加添加鼠标绘制工具栏面板 */ if (opts.enableDrawingTool) { this.enableDrawingTool(); } if (opts.sorptionDistance !== undefined) { this.setSorptionDistance(opts.sorptionDistance); } // 是否计算绘制出的面积 if (opts.enableCalculate === true) { this.enableCalculate(); } else { this.disableCalculate(); } // 是否开启超限提示 if (opts.enableLimit === true) { var limit = opts.limitOptions; this.limit = limit; } // 是否开启吸附功能 if (opts.enableSorption === true) { this.enableSorption(); } else { this.disableSorption(); } // 是否开启gpc功能 if (opts.enableGpc === true) { this.enableGpc(); } else { this.disableGpc(); } /** * 是否已经开启了绘制状态 * @private * @type {Boolean} */ this._isOpen = !!(opts.isOpen === true); if (this._isOpen) { this._open(); } this.setPolygonOptions(opts.polygonOptions); this.setMarkerOptions(opts.markerOptions); this.setCircleOptions(opts.circleOptions); this.setPolylineOptions(opts.polylineOptions); this.setRectangleOptions(opts.rectangleOptions); this.setLabelOptions(opts.labelOptions); this.controlButton = opts.controlButton == 'right' ? 'right' : 'left'; }; DrawingManager.prototype.enableDrawingTool = function() { var opts = this._opts; if (!this._drawingTool) { var drawingTool = new DrawingTool(this, opts.drawingToolOptions); this._drawingTool = drawingTool; } this._map.addControl(this._drawingTool); }; DrawingManager.prototype.disableDrawingTool = function() { if (this._drawingTool) { this._map.removeControl(this._drawingTool); } }; DrawingManager.prototype.setSorptionDistance = function(distance) { this._sorptionDistance = distance || 0; }; DrawingManager.prototype.setPolygonOptions = function(options) { this.polygonOptions = options || {}; }; DrawingManager.prototype.setMarkerOptions = function(options) { this.markerOptions = options || {}; }; DrawingManager.prototype.setCircleOptions = function(options) { this.circleOptions = options || {}; }; DrawingManager.prototype.setPolylineOptions = function(options) { this.polylineOptions = options || {}; }; DrawingManager.prototype.setRectangleOptions = function(options) { this.rectangleOptions = options || {}; }; DrawingManager.prototype.setLabelOptions = function(options) { this.labelOptions = options || {}; }; /** * 开启地图的绘制状态 * @return {Boolean},开启绘制状态成功,返回true;否则返回false。 */ DrawingManager.prototype._open = function () { this._isOpen = true; // 添加遮罩,所有鼠标操作都在这个遮罩上完成 if (!this._mask) { this._mask = new Mask(); } this._map.addOverlay(this._mask); this._setDrawingMode(this._drawingType); }; /** * 设置当前的绘制模式 * @param {DrawingType} */ DrawingManager.prototype._setDrawingMode = function (drawingType) { this._drawingType = drawingType; /** * 开启编辑状态时候才重新进行事件绑定 */ if (this._isOpen) { // 清空之前的自定义事件 this._mask.__listeners = {}; switch (drawingType) { case BMAP_DRAWING_MARKER: this._bindMarker(); break; case BMAP_DRAWING_CIRCLE: this._bindCircle(); break; case BMAP_DRAWING_POLYLINE: case BMAP_DRAWING_POLYGON: this._bindPolylineOrPolygon(); break; case BMAP_DRAWING_RECTANGLE: this._bindRectangle(); break; } } /** * 如果添加了工具栏,则也需要改变工具栏的样式 */ if (this._drawingTool && this._isOpen) { this._drawingTool.setStyleByDrawingMode(drawingType); } }; /** * 关闭地图的绘制状态 * @return {Boolean},关闭绘制状态成功,返回true;否则返回false。 */ DrawingManager.prototype._close = function () { this._isOpen = false; if (this._mask) { this._map.removeOverlay(this._mask); } /** * 如果添加了工具栏,则关闭时候将工具栏样式设置为拖拽地图 */ if (this._drawingTool) { this._drawingTool.setStyleByDrawingMode('hander'); } }; /** * 绑定鼠标画点的事件 */ DrawingManager.prototype._bindMarker = function () { var me = this, map = this._map, mask = this._mask; /** * 鼠标点击的事件 */ var clickAction = function (e) { // 往地图上添加marker var marker = new BMapGL.Marker(e.point, me.markerOptions); map.addOverlay(marker); me._dispatchOverlayComplete(marker); }; mask.addEventListener('click', clickAction); }; /** * 绑定鼠标画圆的事件 */ var tip_label = null; DrawingManager.prototype._bindCircle = function () { var me = this, map = this._map, mask = this._mask, circle = null, overlays = [], centerPoint = null; // 圆的中心点 var radius = 1; var moveMarker = null; var polyline = null; var radiusWindow = null; var operateWindow = null; var lineStyel = { strokeColor: '#4E6DF1', // 边线颜色。 strokeWeight: 2 // 边线的宽度,以像素为单位。 }; var centerIcon = new BMapGL.Icon('//mapopen.bj.bcebos.com/cms/images/DrawingManager/circenter.png', new BMapGL.Size(20, 20)); var moveIcon = new BMapGL.Icon('///mapopen.bj.bcebos.com/cms/images/DrawingManager/nbsearch2.png', new BMapGL.Size(40, 20), { imageOffset: new BMapGL.Size(0, 10) }); /** * 开始绘制圆形 */ var startAction = function (e) { if (me.controlButton == 'right' && (e.button == 1 || e.button == 0)) { return; } centerPoint = e.point; var centerMarker = new BMapGL.Marker(centerPoint); centerIcon.setImageSize(new BMapGL.Size(20, 20)); centerMarker.setIcon(centerIcon); centerMarker.enableDragging(); centerMarker.addEventListener('dragstart', centerDragstart); centerMarker.addEventListener('dragging', centerDragging); centerMarker.addEventListener('dragend', centerDragend); map.addOverlay(centerMarker); overlays.push(centerMarker); circle = new BMapGL.Circle(centerPoint, radius, me.circleOptions); map.addOverlay(circle); mask.enableEdgeMove(); mask.addEventListener('mousemove', moveAction); baidu.on(document, 'mouseup', endAction); }; /** * 绘制圆形过程中,鼠标移动过程的事件 */ var moveAction = function (e) { radius = me._map.getDistance(centerPoint, e.point).toFixed(0); circle.setRadius(radius); map.removeOverlay(tip_label); tip_label = new BMapGL.Label('半径:' + radius + '米
松开完成绘制', { position: e.point, // 指定文本标注所在的地理位置 offset: new BMapGL.Size(10, 10) // 设置文本偏移量 }); tip_label.setStyle(me.labelOptions); map.addOverlay(tip_label); }; /** * 绘制圆形结束 */ var endAction = function (e) { var cz = map.getViewport(circle.getBounds()); cz.zoom -= 1; map.setViewport(cz); map.removeOverlay(tip_label); var endPoint = new BMapGL.Point(circle.getBounds().getNorthEast().lng, centerPoint.lat); mask.hide(); moveMarker = new BMapGL.Marker(endPoint); moveMarker.setIcon(moveIcon); moveMarker.enableDragging(); polyline = new BMapGL.Polyline([centerPoint, endPoint], lineStyel); var midPoint = new BMapGL.Point((circle.getBounds().getNorthEast().lng + centerPoint.lng) / 2, centerPoint.lat); radiusWindow = new Screenshot('circle', midPoint, radius, circle, me); overlays = overlays.concat([moveMarker, polyline, radiusWindow]); var limit = null; if (me.limit) { limit = me.limit.area; } var targetOverlay = { limit: limit, type: 'circle', point: endPoint, overlay: circle, overlays: overlays }; operateWindow = new Operate(targetOverlay, me); map.addOverlay(moveMarker); map.addOverlay(polyline); map.addOverlay(radiusWindow); map.addOverlay(operateWindow); radiusWindow.addEventListener('radiuschange', function (e) { var radius = e.radius; circle.setRadius(radius); var ePoint = getPointByDistance(centerPoint, radius, 'east'); var dragLeftPoint = new BMapGL.Point(ePoint.lng, centerPoint.lat); var halflng = ePoint.lng > centerPoint.lng ? (circle.getBounds().getNorthEast().lng + centerPoint.lng) / 2 : (circle.getBounds().getSouthWest().lng + centerPoint.lng) / 2; var halfLeftPoint = new BMapGL.Point(halflng, centerPoint.lat); moveMarker.setPosition(dragLeftPoint); radiusWindow.setInfo(halfLeftPoint, radius); operateWindow.setPosition(dragLeftPoint, true); operateWindow.updateWindow(); polyline.setPath([centerPoint, dragLeftPoint]); }); moveMarker.addEventListener('dragging', function (e) { var dragLeftPoint = new BMapGL.Point(e.latLng.lng, centerPoint.lat); var halflng = e.latLng.lng > centerPoint.lng ? (circle.getBounds().getNorthEast().lng + centerPoint.lng) / 2 : (circle.getBounds().getSouthWest().lng + centerPoint.lng) / 2; var isright = e.latLng.lng > centerPoint.lng ? true : false; var halfLeftPoint = new BMapGL.Point(halflng, centerPoint.lat); e.target.setPosition(dragLeftPoint); radiusWindow.setInfo(halfLeftPoint, me._map.getDistance(centerPoint, e.latLng).toFixed(0)); operateWindow.setPosition(dragLeftPoint, isright); polyline.setPath([centerPoint, dragLeftPoint]); radius = me._map.getDistance(centerPoint, e.latLng).toFixed(0); circle.setRadius(me._map.getDistance(centerPoint, e.latLng)); }); moveMarker.addEventListener('dragend', function (e) { operateWindow.updateWindow(); }); mask.disableEdgeMove(); mask.removeEventListener('mousemove', moveAction); mask.removeEventListener('mousemove', mousedownAction); baidu.un(document, 'mouseup', endAction); me.close(); }; /** * 鼠标点击起始点 */ var mousedownAction = function (e) { baidu.preventDefault(e); baidu.stopBubble(e); if (me.controlButton == 'right' && e.button == 1) { return; } if (centerPoint == null) { startAction(e); } }; /** * 非绘制圆形过程中,鼠标移动过程的事件 */ var mousemoveAction = function (e) { baidu.preventDefault(e); baidu.stopBubble(e); map.removeOverlay(tip_label); tip_label = new BMapGL.Label('按下确认中心点,拖拽确认半径', { position: e.point, // 指定文本标注所在的地理位置 offset: new BMapGL.Size(10, 10) // 设置文本偏移量 }); tip_label.setStyle(me.labelOptions); map.addOverlay(tip_label); }; var centerDragstart = function (e) { map.removeOverlay(moveMarker); map.removeOverlay(polyline); map.removeOverlay(radiusWindow); map.removeOverlay(operateWindow); }; var centerDragging = function (e) { centerPoint = e.latLng; circle.setCenter(e.latLng); }; var centerDragend = function (e) { centerPoint = e.latLng; endAction(e); }; mask.addEventListener('mousedown', mousedownAction); mask.addEventListener('mousemove', mousemoveAction); }; /** * 画线和画多边形相似性比较大,公用一个方法 */ DrawingManager.prototype._bindPolylineOrPolygon = function () { var me = this, map = this._map, mask = this._mask, points = [], // 用户绘制的点 drawPoint = null, // 实际需要画在地图上的点 overlay = null, match = null, isBinded = false; function getNorthEast() { var bound = arguments[0]; var maxlng = 0; var index = 0; for (var j = 0; j < bound.length; j++) { if (maxlng < bound[j].lng) { maxlng = bound[j].lng; index = j; } } return bound[index]; } /** * 鼠标点击的事件 */ var startAction = function (e) { if (me.controlButton == 'right' && (e.button == 1 || e.button == 0)) { return; } var point = e.point; if (match) { point = match; } points.push(point); drawPoint = points.concat(points[points.length - 1]); if (points.length == 1) { if (me._drawingType == BMAP_DRAWING_POLYLINE) { overlay = new BMapGL.Polyline(drawPoint, me.polylineOptions); } else if (me._drawingType == BMAP_DRAWING_POLYGON) { overlay = new BMapGL.Polygon(drawPoint, me.polygonOptions); } map.addOverlay(overlay); } else { overlay.setPath(drawPoint); } if (!isBinded) { isBinded = true; mask.enableEdgeMove(); mask.removeEventListener('mousemove', mousemoveAction); mask.addEventListener('mousemove', moveAction); mask.addEventListener('dblclick', dblclickAction); } }; /** * 鼠标移动过程的事件 */ var moveAction = function (e) { var point = e.point; if (me._enableSorption) { var matchs = me.getSorptionMatch(point, me.overlays, me._sorptionDistance); if (matchs && matchs.length > 0) { match = matchs[0].point; overlay.setPositionAt(drawPoint.length - 1, matchs[0].point); return; } } match = null; overlay.setPositionAt(drawPoint.length - 1, e.point); map.removeOverlay(tip_label); tip_label = new BMapGL.Label('单击绘制下一个点,双击完成绘制', { position: e.point, // 指定文本标注所在的地理位置 offset: new BMapGL.Size(10, 10) // 设置文本偏移量 }); tip_label.setStyle(me.labelOptions); map.addOverlay(tip_label); }; /** * 鼠标双击的事件 */ var dblclickAction = function (e) { baidu.stopBubble(e); isBinded = false; map.removeOverlay(tip_label); mask.disableEdgeMove(); mask.removeEventListener('mousedown',startAction); mask.removeEventListener('mousemove', moveAction); mask.removeEventListener('mousemove', mousemoveAction); mask.removeEventListener('dblclick', dblclickAction); if (me.controlButton == 'right') { points.push(e.point); } else if (baidu.ie <= 8) { } else { points.pop(); } // 裁剪 try { if (me._enableGpc && window.gpcas && 'polygon' === me._drawingType) { var res = new gpcas.geometry.PolyDefault(); for (var i = 0; i < points.length; i++) { res.addPoint(new gpcas.Point(points[i].lng, points[i].lat)); } for (var j = 0; j < me.overlays.length; j++) { var path = me.overlays[j].getPath(); var target = new gpcas.geometry.PolyDefault(); for (var i = 0; i < path.length; i++) { target.addPoint(new gpcas.Point(path[i].lng, path[i].lat)); } var diff = res.difference(target); var newPoints = diff.getPoints(); var outPoints = []; for (var i = 0; i < newPoints.length; i++) { outPoints.push(new BMapGL.Point(newPoints[i].x, newPoints[i].y)); } res = new gpcas.geometry.PolyDefault(); for (var i = 0; i < newPoints.length; i++) { res.addPoint(new gpcas.Point(newPoints[i].x, newPoints[i].y)); } points = outPoints; } } } catch(e) { } overlay.setPath(points); var cz = map.getViewport(points); cz.zoom -= 1; map.setViewport(cz); overlay.enableEditing(); var limit = null; if (me.limit) { limit = 'polygon' === me._drawingType ? me.limit.area : me.limit.distance; } var targetOverlay = { limit: limit, type: me._drawingType, point: getNorthEast(points), overlay: overlay, overlays: [] }; var operateWindow = new Operate(targetOverlay, me); map.addOverlay(operateWindow); overlay.addEventListener('lineupdate', function (e) { var point = getNorthEast(e.currentTarget.getPath()); operateWindow.setPosition(point, true); operateWindow.updateWindow(); }); points.length = 0; drawPoint.length = 0; me.close(); }; /** * 非绘制多边形过程中,鼠标移动过程的事件 */ var mousemoveAction = function (e) { baidu.preventDefault(e); baidu.stopBubble(e); map.removeOverlay(tip_label); tip_label = new BMapGL.Label('单击确认起点', { position: e.point, // 指定文本标注所在的地理位置 offset: new BMapGL.Size(10, 10) // 设置文本偏移量 }); tip_label.setStyle(me.labelOptions); map.addOverlay(tip_label); }; mask.addEventListener('mousemove', mousemoveAction); // mask.addEventListener('mouseup', startAction); mask.addEventListener('mousedown', startAction); // 双击时候不放大地图级别 mask.addEventListener('dblclick', function (e) { baidu.stopBubble(e); }); }; /** * 绑定鼠标画矩形的事件 */ DrawingManager.prototype._bindRectangle = function () { var me = this, map = this._map, mask = this._mask, polygon = null, startPoint = null; // 获取4个顶点和4条边中点的坐标 function getRectAllPoints(pointA, pointB) { var pointLT = new BMapGL.Point(pointA.lng, pointA.lat); // 左上角 var pointRT = new BMapGL.Point(pointB.lng, pointA.lat); // 右上角 var pointRB = new BMapGL.Point(pointB.lng, pointB.lat); // 右下角 var pointLB = new BMapGL.Point(pointA.lng, pointB.lat); // 左上角 var pointTC = new BMapGL.Point((pointA.lng + pointB.lng) / 2, pointA.lat); var pointRC = new BMapGL.Point(pointB.lng, (pointA.lat + pointB.lat) / 2); var pointBC = new BMapGL.Point((pointA.lng + pointB.lng) / 2, pointB.lat); var pointLC = new BMapGL.Point(pointA.lng, (pointA.lat + pointB.lat) / 2); return [pointLT, pointTC, pointRT, pointRC, pointRB, pointBC, pointLB, pointLC]; } var moveIcon = new BMapGL.Icon('//mapopen.bj.bcebos.com/cms/images/DrawingManager/bullet2.png', new BMapGL.Size(10, 10)); moveIcon.setImageSize(new BMapGL.Size(10, 10)); /** * 开始绘制矩形 */ var startAction = function (e) { baidu.stopBubble(e); baidu.preventDefault(e); if (me.controlButton == 'right' && (e.button == 1 || e.button == 0)) { return; } startPoint = e.point; var endPoint = startPoint; polygon = new BMapGL.Polygon(me._getRectanglePoint(startPoint, endPoint), me.rectangleOptions); map.addOverlay(polygon); mask.enableEdgeMove(); mask.addEventListener('mousemove', moveAction); baidu.on(document, 'mouseup', endAction); }; /** * 绘制矩形过程中,鼠标移动过程的事件 */ var moveAction = function (e) { map.removeOverlay(tip_label); polygon.setPath(me._getRectanglePoint(startPoint, e.point)); var points = getRectAllPoints(startPoint, e.point); var width = me._map.getDistance(startPoint, points[2]).toFixed(0); var height = me._map.getDistance(startPoint, points[6]).toFixed(0); tip_label = new BMapGL.Label('尺寸:' + width + '米 x ' + height + '米
松开结束绘制', { position: e.point, // 指定文本标注所在的地理位置 offset: new BMapGL.Size(10, 10) // 设置文本偏移量 }); tip_label.setStyle(me.labelOptions); map.addOverlay(tip_label); }; /** * 绘制矩形结束 */ var endAction = function (e) { mask.hide(); var endPoint = null; var markers = []; var points = getRectAllPoints(startPoint, e.point); var pointsTmp = []; var cz = map.getViewport(points); cz.zoom -= 1; map.setViewport(cz); map.removeOverlay(tip_label); var width = me._map.getDistance(startPoint, points[2]).toFixed(0); var height = me._map.getDistance(startPoint, points[6]).toFixed(0); var rectInfo = new Screenshot('rectangle', points[0], { width: width, height: height }, polygon, me); for (var i = 0; i < points.length; i++) { var marker = new BMapGL.Marker(points[i]); marker.setIcon(moveIcon); marker.enableDragging(); markers.push(marker); map.addOverlay(marker); pointsTmp[i] = me.mc2ll(marker.point); marker.addEventListener('mousedown', function (e) { endPoint = me.mc2ll(e.target.point); }); marker.addEventListener('dragging', function (e) { var point = e.latLng; for (var j = 0; j < pointsTmp.length; j++) { if (endPoint.lng == pointsTmp[j].lng) { points[j].lng = point.lng; } if (endPoint.lat == pointsTmp[j].lat) { points[j].lat = point.lat; } } points = getRectAllPoints(points[0], points[4]); for (var j = 0; j < markers.length; j++) { markers[j].setPosition(points[j]); } width = me._map.getDistance(points[0], points[2]).toFixed(0); height = me._map.getDistance(points[0], points[6]).toFixed(0); rectInfo.setInfo(points[0], { width: width, height: height }); operateWindow.setPosition(points[3], true); polygon.setPath(points); }); marker.addEventListener('dragend', function (e) { for (var i = 0; i < markers.length; i++) { var marker = markers[i]; pointsTmp[i] = me.mc2ll(marker.point); } operateWindow.updateWindow(); }); } rectInfo.addEventListener('rectwhchange', function (e) { var width = e.width; var height = e.height; var pointx = getPointByDistance(points[0], width, 'east'); var pointy = getPointByDistance(points[0], height, 'south'); points[4].lng = pointx.lng; points[4].lat = pointy.lat; points = getRectAllPoints(points[0], points[4]); for (var j = 0; j < markers.length; j++) { markers[j].setPosition(points[j]); } rectInfo.setInfo(points[0], { width: width, height: height }); operateWindow.setPosition(points[3], true); polygon.setPath(points); for (var i = 0; i < markers.length; i++) { var marker = markers[i]; pointsTmp[i] = me.mc2ll(marker.point); } operateWindow.updateWindow(); }); var overlays = [markers, rectInfo]; var limit = null; if (me.limit) { limit = me.limit.area; } var overlay = { limit: limit, type: 'rectangle', point: points[3], overlay: polygon, overlays: overlays }; var operateWindow = new Operate(overlay, me); map.addOverlay(operateWindow); map.addOverlay(rectInfo); mask.disableEdgeMove(); mask.removeEventListener('mousemove', moveAction); mask.removeEventListener('mousemove', mousemoveAction); baidu.un(document, 'mouseup', endAction); me.close(); }; /** * 非绘制矩形过程中,鼠标移动过程的事件 */ var mousemoveAction = function (e) { baidu.preventDefault(e); baidu.stopBubble(e); map.removeOverlay(tip_label); tip_label = new BMapGL.Label('按住确认起点,拖拽进行绘制', { position: e.point, // 指定文本标注所在的地理位置 offset: new BMapGL.Size(10, 10) // 设置文本偏移量 }); tip_label.setStyle(me.labelOptions); map.addOverlay(tip_label); }; mask.addEventListener('mousedown', startAction); mask.addEventListener('mousemove', mousemoveAction); }; /** * 添加显示所绘制图形的面积或者长度 * @param {overlay} 覆盖物 * @param {point} 显示的位置 */ DrawingManager.prototype._calculate = function (overlay, point) { var result = { data: 0, // 计算出来的长度或面积 label: null // 显示长度或面积的label对象 }; if (this._enableCalculate && BMapGLLib.GeoUtils) { var type = overlay.toString(); // 不同覆盖物调用不同的计算方法 switch (type) { case 'Polyline': //[object Polyline]==>在3D版本中已经转为了Polyline result.data = BMapGLLib.GeoUtils.getPolylineDistance(overlay); break; case 'Polygon': result.data = BMapGLLib.GeoUtils.getPolygonArea(overlay); break; case 'Circle': var radius = overlay.getRadius(); result.data = Math.PI * radius * radius; break; } // 异常情况处理 if (!result.data || result.data < 0) { result.data = 0; console.error('计算函数异常处理'); } else { // 保留2位小数位 result.data = result.data.toFixed(2); } /** * 这里我们只需要开启计算面积功能,但并不需要在地图上添加显示面积的label,所以注释掉 */ // result.label = this._addLabel(point, result.data); } return result; }; /** * 开启测距和测面功能需要依赖于GeoUtils库 * 所以这里判断用户是否已经加载,若未加载则用js动态加载 */ DrawingManager.prototype._addGeoUtilsLibrary = function () { if (!BMapGLLib.GeoUtils) { var script = document.createElement('script'); script.setAttribute('type', 'text/javascript'); script.setAttribute('src', '//mapopen.cdn.bcebos.com/github/BMapGLLib/GeoUtils/src/GeoUtils.min.js'); // script.setAttribute('src', '../../GeoUtils/GeoUtils.js'); document.body.appendChild(script); } }; /** * 开启裁剪功能需要依赖于gpc库 * 所以这里判断用户是否已经加载,若未加载则用js动态加载 */ DrawingManager.prototype._addGPCLibrary = function () { if (!window.gpcas) { var script = document.createElement('script'); script.setAttribute('type', 'text/javascript'); script.setAttribute('src', '//mapopen.cdn.bcebos.com/github/BMapGLLib/DrawingManager/src/gpc.js'); // script.setAttribute('src', '../src/gpc.js'); document.body.appendChild(script); } }; /** * 向地图中添加文本标注 * @param {Point} * @param {String} 所以显示的内容 */ DrawingManager.prototype._addLabel = function (point, content) { var label = new BMapGL.Label(content, { position: point }); this._map.addOverlay(label); return label; }; /** * 根据起终点获取矩形的四个顶点 * @param {Point} 起点 * @param {Point} 终点 */ DrawingManager.prototype._getRectanglePoint = function (startPoint, endPoint) { return [ new BMapGL.Point(startPoint.lng, startPoint.lat), new BMapGL.Point(endPoint.lng, startPoint.lat), new BMapGL.Point(endPoint.lng, endPoint.lat), new BMapGL.Point(startPoint.lng, endPoint.lat) ]; }; /** * 派发成功事件 */ DrawingManager.prototype._dispatchOverlayComplete = function (overlay, calculate) { var options = { overlay: overlay, drawingMode: this._drawingType }; if (calculate) { options.calculate = calculate.data || null; options.label = calculate.label || null; } this.dispatchEvent(this._drawingType + 'complete', overlay); this.dispatchEvent('overlaycomplete', options); }; /** * 派发失败事件 */ DrawingManager.prototype._dispatchOverlayCancel = function (overlay) { var options = { overlay: overlay, drawingMode: this._drawingType }; this.dispatchEvent(this._drawingType + 'cancel', overlay); this.dispatchEvent('overlaycancel', options); }; // 判断吸附算法 DrawingManager.prototype.getSorptionMatch = function (point, polygons, distance) { distance = distance || 20; var map = this._map; var P = map.pointToPixel(point); // point.pixel; var match = []; for (var j = 0; j < polygons.length; j++) { var pixels = polygons[j].getPath(); var first = pixels[0]; var last = pixels[pixels.length - 1]; if (!first.equals(last)) { pixels.push(pixels[0]); } for (var i = 1; i < pixels.length; i++) { var A = map.pointToPixel(pixels[i - 1]); var B = map.pointToPixel(pixels[i]); var vAP = [P.x - A.x, P.y - A.y]; var vAB = [B.x - A.x, B.y - A.y]; var vPB = [B.x - P.x, B.y - P.y]; var cAPAB = vAP[0] * vAB[0] + vAP[1] * vAB[1]; var lAPAB = Math.sqrt(Math.pow(vAP[0], 2) + Math.pow(vAP[1], 2)) * Math.sqrt(Math.pow(vAB[0], 2) + Math.pow(vAB[1], 2)); var rPAB = Math.acos(cAPAB / lAPAB); var cABPB = vAB[0] * vPB[0] + vAB[1] * vPB[1]; var lABPB = Math.sqrt(Math.pow(vAB[0], 2) + Math.pow(vAB[1], 2)) * Math.sqrt(Math.pow(vPB[0], 2) + Math.pow(vPB[1], 2)); var rPBA = Math.acos(cABPB / lABPB); if (rPAB < Math.PI / 2 && rPBA < Math.PI / 2) { var lAP = Math.sqrt(Math.pow(vAP[0], 2) + Math.pow(vAP[1], 2)); var lAB = Math.sqrt(Math.pow(vAB[0], 2) + Math.pow(vAB[1], 2)); var lAO = Math.cos(rPAB) * lAP; var pAOAB = lAO / lAB; var lPO = Math.sin(rPAB) * lAP; var O = [A.x + vAB[0] * pAOAB, A.y + vAB[1] * pAOAB]; if (lPO < distance) { match.push({ point: map.pixelToPoint({ x: O[0], y: O[1] }), length: lPO }); } } } } match.sort(function (a, b) { return a.length - b.length; }); var ret = match.length > 0 ? match : null; return ret; } // 墨卡托坐标转经纬度 DrawingManager.prototype.mc2ll = function (point) { var map = this._map; var ll = map.mercatorToLnglat(point.lng, point.lat); return new BMapGL.Point(ll[0], ll[1]); }; // 经纬度坐标转墨卡托 DrawingManager.prototype.ll2mc = function (point) { var map = this._map; var mc = map.lnglatToMercator(point.lng, point.lat); return new BMapGL.Point(mc[0], mc[1]); }; // 确认,取消操作覆盖物 function Operate(data, DrawingManager) { this.limit = data.limit; this.type = data.type; this.point = data.point; this.overlay = data.overlay; this.overlays = data.overlays; this.DrawingManager = DrawingManager; } Operate.prototype = new BMapGL.Overlay(); Operate.prototype.dispatchEvent = baidu.lang.Class.prototype.dispatchEvent; Operate.prototype.addEventListener = baidu.lang.Class.prototype.addEventListener; Operate.prototype.removeEventListener = baidu.lang.Class.prototype.removeEventListener; Operate.prototype.initialize = function (map) { var me = this; this._map = map; var overlyTypeText = (this.type === 'polyline' ? '长度' : '面积'); var unit = (this.type === 'polyline' ? '万米' : '万平方米'); var div = this.div = document.createElement('div'); div.className = 'operateWindow'; var html = '
' + overlyTypeText + '不超过' + this.limit / 10000 + unit + '!
'; div.innerHTML = html; this._map.getPanes().markerPane.appendChild(div); this.updateWindow(); this._bind(); return div; }; Operate.prototype._bind = function () { var that = this; var map = this._map; var overlay = this.overlay; var overlays = this.overlays; document.getElementById('confirmOperate').addEventListener('click', function (e) { map.removeOverlay(that); if (that.type == 'rectangle') { var calculate = that.DrawingManager._calculate(overlay, overlay.getPath()); } else if (that.type == 'circle') { var calculate = that.DrawingManager._calculate(overlay, that.point); } else if (that.type == 'polygon') { var calculate = that.DrawingManager._calculate(overlay, (overlay.getPath())); that.DrawingManager.overlays.push(overlay); overlay.disableEditing(); } else if (that.type == 'polyline') { var calculate = that.DrawingManager._calculate(overlay, (overlay.getPath())); that.DrawingManager.overlays.push(overlay); overlay.disableEditing(); } that.DrawingManager._dispatchOverlayComplete(overlay, calculate); for (var i = 0; i < overlays.length; i++) { if (Array.isArray(overlays[i])) { for (var k in overlays[i]) { map.removeOverlay(overlays[i][k]); } } else { map.removeOverlay(overlays[i]); } } that.DrawingManager.close(); }); document.getElementById('cancelOperate').addEventListener('click', function (e) { map.removeOverlay(that); for (var i = 0; i < overlays.length; i++) { if (Array.isArray(overlays[i])) { for (var k in overlays[i]) { map.removeOverlay(overlays[i][k]); } } else { map.removeOverlay(overlays[i]); } } map.removeOverlay(overlay); that.DrawingManager._dispatchOverlayCancel(overlay); that.DrawingManager._mask.show(); that.DrawingManager._setDrawingMode(that.type); }); }; Operate.prototype.updateWindow = function () { if (this.domElement === null) { return; } var overlay = this.overlay; var limit = this.limit; var calculate; if (this.type == 'rectangle') { calculate = this.DrawingManager._calculate(overlay, overlay.getPath()); } else if (this.type == 'circle') { calculate = this.DrawingManager._calculate(overlay, this.point); } else if (this.type == 'polygon') { calculate = this.DrawingManager._calculate(overlay, overlay.getPath()); } else if (this.type == 'polyline') { calculate = this.DrawingManager._calculate(overlay, overlay.getPath()); } if (Object.prototype.toString.call(limit) === '[object Number]' && calculate.data > limit) { document.getElementById('confirmOperate').style.display = 'none'; document.getElementById('warnOperate').style.display = 'block'; } else { document.getElementById('confirmOperate').style.display = 'block'; document.getElementById('warnOperate').style.display = 'none'; } }; Operate.prototype.setPosition = function (point, isright) { this.point = point; var map = this._map, pixel = map.pointToOverlayPixel(this.point); if (isright) { this.div.classList.remove('operateLeft'); this.div.style.left = pixel.x + 15 + 'px'; } else { this.div.classList.add('operateLeft'); this.div.style.left = pixel.x - 105 + 'px'; } this.div.style.top = pixel.y - 16 + 'px'; }; Operate.prototype.draw = function () { var map = this._map, pixel = map.pointToOverlayPixel(this.point); this.div.style.left = pixel.x + 15 + 'px'; this.div.style.top = pixel.y - 16 + 'px'; }; // 显示,编辑半径覆盖物 function Screenshot(type, point, number, overlay, DrawingManager) { this.type = type; this.point = point; this.number = number; this.overlay = overlay; this.DrawingManager = DrawingManager; } Screenshot.prototype = new BMapGL.Overlay(); Screenshot.prototype.dispatchEvent = baidu.lang.Class.prototype.dispatchEvent; Screenshot.prototype.addEventListener = baidu.lang.Class.prototype.addEventListener; Screenshot.prototype.removeEventListener = baidu.lang.Class.prototype.removeEventListener; Screenshot.prototype.initialize = function (map) { var me = this; this._map = map; var div = this.div = document.createElement('div'); div.className = 'screenshot'; if (this.type == 'circle') { var html = '
' + this.number + '
'; } else if (this.type == 'rectangle') { var html = '
' + this.number.width + '
x
' + this.number.height + '
'; } div.innerHTML = html; this._map.getPanes().markerPane.appendChild(div); this._bind(); return div; }; Screenshot.prototype._bind = function () { this.setNumber(this.number); if (this.type == 'circle') { this.bindCircleEvent(); } else { this.bindRectEvent(); } }; Screenshot.prototype.bindCircleEvent = function () { var that = this; var circleSpn = document.getElementById('screenshotNum'); var circleInput = document.getElementById('circleInput'); circleSpn.addEventListener('click', function (e) { var val = circleSpn.innerText; circleSpn.style.display = 'none'; circleInput.value = val; circleInput.style.display = 'inline-block'; circleInput.focus(); }); circleInput.addEventListener('click', function (e) { circleInput.focus(); }); circleInput.addEventListener('keydown', function (e) { if (e.keyCode === 13) { var val = circleInput.value; circleInput.style.display = 'none'; circleSpn.style.display = 'inline-block'; circleSpn.innerText = val; var opt = { radius: val, overlay: that.overlay }; that._dispatchRadiusChange(opt); } }); circleInput.addEventListener('blur', function (e) { var val = circleInput.value; circleInput.style.display = 'none'; circleSpn.style.display = 'inline-block'; circleSpn.innerText = val; var opt = { radius: val, overlay: that.overlay }; that._dispatchRadiusChange(opt); }); }; Screenshot.prototype.bindRectEvent = function () { var that = this; var rectWidthSpn = document.getElementById('rectWidth'); var rectWidthInput = document.getElementById('rectWidthInput'); var rectHeightSpn = document.getElementById('rectHeight'); var rectHeightInput = document.getElementById('rectHeightInput'); rectWidthInput.value = rectWidthSpn.innerText; rectHeightInput.value = rectHeightSpn.innerText; rectWidthSpn.addEventListener('click', function (e) { var val = rectWidthSpn.innerText; rectWidthSpn.style.display = 'none'; rectWidthInput.value = val; rectWidthInput.style.display = 'inline-block'; rectWidthInput.focus(); }); rectHeightSpn.addEventListener('click', function (e) { var val = rectHeightSpn.innerText; rectHeightSpn.style.display = 'none'; rectHeightInput.value = val; rectHeightInput.style.display = 'inline-block'; rectHeightInput.focus(); }); rectWidthInput.addEventListener('click', function (e) { rectWidthInput.focus(); }); rectHeightInput.addEventListener('click', function (e) { rectHeightInput.focus(); }); rectWidthInput.addEventListener('keydown', function (e) { if (e.keyCode === 13) { var widthVal = rectWidthInput.value; var heightVal = rectHeightInput.value; rectWidthInput.style.display = 'none'; rectHeightInput.style.display = 'none'; rectWidthSpn.style.display = 'inline-block'; rectHeightSpn.style.display = 'inline-block'; rectWidthSpn.innerText = widthVal; rectHeightSpn.innerText = heightVal; var opt = { width: widthVal, height: heightVal, overlay: that.overlay }; that._dispatchRectWHChange(opt); } }); rectHeightInput.addEventListener('keydown', function (e) { if (e.keyCode === 13) { var widthVal = rectWidthInput.value; var heightVal = rectHeightInput.value; rectWidthInput.style.display = 'none'; rectHeightInput.style.display = 'none'; rectWidthSpn.style.display = 'inline-block'; rectHeightSpn.style.display = 'inline-block'; rectWidthSpn.innerText = widthVal; rectHeightSpn.innerText = heightVal; var opt = { width: widthVal, height: heightVal, overlay: that.overlay }; that._dispatchRectWHChange(opt); } }); }; Screenshot.prototype.setInfo = function (point, number) { this.setNumber(number); this.setPosition(point); }; Screenshot.prototype.setNumber = function (number) { if (this.type == 'circle') { document.getElementById('screenshotNum').textContent = number; } else { document.getElementById('rectWidth').textContent = number.width; document.getElementById('rectHeight').textContent = number.height; } }; Screenshot.prototype.setPosition = function (point) { this.point = point; var map = this._map, type = this.type, pixel = map.pointToOverlayPixel(this.point); if (type == 'circle') { this.div.style.left = pixel.x - 30 + 'px'; this.div.style.top = pixel.y - 40 + 'px'; } else if (type == 'rectangle') { this.div.style.left = pixel.x + 'px'; this.div.style.top = pixel.y - 45 + 'px'; } }; Screenshot.prototype.draw = function () { var map = this._map, type = this.type, pixel = map.pointToOverlayPixel(this.point); if (type == 'circle') { this.div.style.left = pixel.x - 30 + 'px'; this.div.style.top = pixel.y - 40 + 'px'; } else if (type == 'rectangle') { this.div.style.left = pixel.x + 'px'; this.div.style.top = pixel.y - 45 + 'px'; } }; /** * 派发事件 */ Screenshot.prototype._dispatchRadiusChange = function (opt) { this.dispatchEvent('radiuschange', opt); }; /** * 派发事件 */ Screenshot.prototype._dispatchRectWHChange = function (opt) { this.dispatchEvent('rectwhchange', opt); }; /** * 创建遮罩对象 */ function Mask() { /** * 鼠标到地图边缘的时候是否自动平移地图 */ this._enableEdgeMove = false; } Mask.prototype = new BMapGL.Overlay(); /** * 这里不使用api中的自定义事件,是为了更灵活使用 */ Mask.prototype.dispatchEvent = baidu.lang.Class.prototype.dispatchEvent; Mask.prototype.addEventListener = baidu.lang.Class.prototype.addEventListener; Mask.prototype.removeEventListener = baidu.lang.Class.prototype.removeEventListener; Mask.prototype.initialize = function (map) { var me = this; this._map = map; var div = this.container = document.createElement('div'); var size = this._map.getSize(); div.style.cssText = 'position:absolute;background:transparent;cursor:crosshair;width:' + size.width + 'px;height:' + size.height + 'px'; this._map.addEventListener('resize', function (e) { me._adjustSize(e.size); }); this._map.getPanes().floatPane.appendChild(div); this._bind(); return div; }; Mask.prototype.draw = function () { var map = this._map, point = map.pixelToPoint(new BMapGL.Pixel(0, 0)), pixel = map.pointToOverlayPixel(point); this.container.style.left = pixel.x + 'px'; this.container.style.top = pixel.y + 'px'; }; /** * 开启鼠标到地图边缘,自动平移地图 */ Mask.prototype.enableEdgeMove = function () { this._enableEdgeMove = true; }; /** * 关闭鼠标到地图边缘,自动平移地图 */ Mask.prototype.disableEdgeMove = function () { clearInterval(this._edgeMoveTimer); this._enableEdgeMove = false; }; /** * 绑定事件,派发自定义事件 */ Mask.prototype._bind = function () { var me = this, map = this._map, container = this.container, lastMousedownXY = null, lastClickXY = null; /** * 根据event对象获取鼠标的xy坐标对象 * @param {Event} * @return {Object} {x:e.x, y:e.y} */ var getXYbyEvent = function (e) { return { x: e.clientX, y: e.clientY }; }; var domEvent = function (e) { var type = e.type; e = baidu.getEvent(e); point = me.getDrawPoint(e); // 当前鼠标所在点的地理坐标 var dispatchEvent = function (type) { e.point = point; me.dispatchEvent(e); }; if (type == 'mousedown') { lastMousedownXY = getXYbyEvent(e); } var nowXY = getXYbyEvent(e); // click经过一些特殊处理派发,其他同事件按正常的dom事件派发 if (type == 'click') { // 鼠标点击过程不进行移动才派发click和dblclick if (Math.abs(nowXY.x - lastMousedownXY.x) < 5 && Math.abs(nowXY.y - lastMousedownXY.y) < 5) { if (!lastClickXY || !(Math.abs(nowXY.x - lastClickXY.x) < 5 && Math.abs(nowXY.y - lastClickXY.y) < 5)) { dispatchEvent('click'); lastClickXY = getXYbyEvent(e); } else { lastClickXY = null; } } } else { dispatchEvent(type); } }; /** * 将事件都遮罩层的事件都绑定到domEvent来处理 */ var events = ['click', 'mousedown', 'mousemove', 'mouseup', 'dblclick'], index = events.length; while (index--) { baidu.on(container, events[index], domEvent); } // 鼠标移动过程中,到地图边缘后自动平移地图 baidu.on(container, 'mousemove', function (e) { if (me._enableEdgeMove) { me.mousemoveAction(e); } }); }; // 鼠标移动过程中,到地图边缘后自动平移地图 Mask.prototype.mousemoveAction = function (e) { function getClientPosition(e) { var clientX = e.clientX, clientY = e.clientY; if (e.changedTouches) { clientX = e.changedTouches[0].clientX; clientY = e.changedTouches[0].clientY; } return new BMapGL.Pixel(clientX, clientY); } var map = this._map, me = this, pixel = map.pointToPixel(this.getDrawPoint(e)), clientPos = getClientPosition(e), offsetX = clientPos.x - pixel.x, offsetY = clientPos.y - pixel.y; pixel = new BMapGL.Pixel((clientPos.x - offsetX), (clientPos.y - offsetY)); this._draggingMovePixel = pixel; var point = map.pixelToPoint(pixel), eventObj = { pixel: pixel, point: point }; // 拖拽到地图边缘移动地图 this._panByX = this._panByY = 0; if (pixel.x <= 20 || pixel.x >= map.width - 20 || pixel.y <= 50 || pixel.y >= map.height - 10) { if (pixel.x <= 20) { this._panByX = 8; } else if (pixel.x >= map.width - 20) { this._panByX = -8; } if (pixel.y <= 50) { this._panByY = 8; } else if (pixel.y >= map.height - 10) { this._panByY = -8; } if (!this._edgeMoveTimer) { this._edgeMoveTimer = setInterval(function () { map.panBy(me._panByX, me._panByY, { noAnimation: true }); }, 30); } } else { if (this._edgeMoveTimer) { clearInterval(this._edgeMoveTimer); this._edgeMoveTimer = null; } } }; /* * 调整大小 * @param {Size} */ Mask.prototype._adjustSize = function (size) { this.container.style.width = size.width + 'px'; this.container.style.height = size.height + 'px'; }; /** * 获取当前绘制点的地理坐标 * * @param {Event} e e对象 * @return Point对象的位置信息 */ Mask.prototype.getDrawPoint = function (e) { var map = this._map, trigger = baidu.getTarget(e), x = e.offsetX || e.layerX || 0, y = e.offsetY || e.layerY || 0; if (trigger.nodeType != 1) { trigger = trigger.parentNode; } while (trigger && trigger != map.getContainer()) { if (!(trigger.clientWidth == 0 && trigger.clientHeight == 0 && trigger.offsetParent && trigger.offsetParent.nodeName == 'TD')) { x += trigger.offsetLeft || 0; y += trigger.offsetTop || 0; } trigger = trigger.offsetParent; } var pixel = new BMapGL.Pixel(x, y); var point = map.pixelToPoint(pixel); return point; }; /** * 绘制工具面板,自定义控件 */ function DrawingTool(drawingManager, drawingToolOptions) { this.drawingManager = drawingManager; drawingToolOptions = this.drawingToolOptions = drawingToolOptions || {}; this._opts = {}; // 默认停靠位置和偏移量 this.defaultAnchor = BMAP_ANCHOR_TOP_LEFT; this.defaultOffset = new BMapGL.Size(10, 10); // 默认所有工具栏都显示 this.defaultDrawingModes = [ BMAP_DRAWING_MARKER, BMAP_DRAWING_CIRCLE, BMAP_DRAWING_POLYLINE, BMAP_DRAWING_POLYGON, BMAP_DRAWING_RECTANGLE ]; // 工具栏可显示的绘制模式 if (drawingToolOptions.drawingModes) { this.drawingModes = drawingToolOptions.drawingModes; } else { this.drawingModes = this.defaultDrawingModes; } // 用户设置停靠位置和偏移量 if (drawingToolOptions.hasCustomStyle) { if (drawingToolOptions.anchor) { this.setAnchor(drawingToolOptions.anchor); } if (drawingToolOptions.offset) { this.setOffset(drawingToolOptions.offset); } } } // 通过JavaScript的prototype属性继承于BMap.Control DrawingTool.prototype = new BMapGL.Control(); // 自定义控件必须实现自己的initialize方法,并且将控件的DOM元素返回 // 在本方法中创建个div元素作为控件的容器,并将其添加到地图容器中 DrawingTool.prototype.initialize = function (map) { // 创建一个DOM元素 var container = this.container = document.createElement('div'); container.className = 'BMapGLLib_Drawing'; // 用来设置外层边框阴影 var panel = this.panel = document.createElement('div'); panel.className = 'BMapGLLib_Drawing_panel'; if (this.drawingToolOptions && this.drawingToolOptions.hasCustomStyle && this.drawingToolOptions.scale) { this._setScale(this.drawingToolOptions.scale); } container.appendChild(panel); // 添加内容 var content = this._generalHtml(); panel.appendChild(content); // 添加tip var tip = this.tip = document.createElement('div'); tip.className = 'BMapGLLib_tip'; tip.innerHTML = '

'; if (this.drawingToolOptions.enableTips === true) { panel.appendChild(tip); } // 绑定事件 this._bind(panel); // 添加DOM元素到地图中 if (this.drawingToolOptions.customContainer) { baidu.g(this.drawingToolOptions.customContainer).appendChild(container); } else { map.getContainer().appendChild(container); } // 将DOM元素返回 return container; }; // 生成工具栏的html元素 DrawingTool.prototype._generalHtml = function (map) { var that = this; // 鼠标经过工具栏上的提示信息 var tips = {}; tips.hander = '拖动地图'; tips[BMAP_DRAWING_MARKER] = '画点'; tips[BMAP_DRAWING_CIRCLE] = '圆形工具'; tips[BMAP_DRAWING_POLYLINE] = '画折线'; tips[BMAP_DRAWING_POLYGON] = '多边形工具'; tips[BMAP_DRAWING_RECTANGLE] = '矩形工具'; var getItem = function (className, drawingType) { var ele = document.createElement('a'); ele.className = className; ele.href = 'javascript:void(0)'; ele.setAttribute('drawingType', drawingType); ele.setAttribute('onfocus', 'this.blur()'); ele.addEventListener('mouseenter', function (e) { var drawingType = e.target.getAttribute('drawingType'); var title = tips[drawingType]; if (drawingType === 'hander') { that.tip.children[0].innerText = title; that.tip.children[1].innerText = '使用鼠标拖动地图'; } else { that.tip.className += ' ' + drawingType; that.tip.children[0].innerText = title; that.tip.children[1].innerText = '使用' + title + '选出目标区域'; } that.tip.style.display = 'block'; }); ele.addEventListener('mouseleave', function (e) { // remove class drawingType var drawingType = e.target.getAttribute('drawingType'); var newClass = ' ' + that.tip.className.replace(/[\t\r\n]/g, '') + ' '; while (newClass.indexOf(' ' + drawingType + ' ') >= 0) { newClass = newClass.replace(' ' + drawingType + ' ', ' '); } that.tip.className = newClass.replace(/^\s+|\s+$/g, ''); that.tip.style.display = 'none'; }); return ele; }; // 生成工具 var fragment = document.createDocumentFragment(); // 取消hander工具的展示,交互改为再次点击tool取消active功能 // fragment.appendChild(getItem('BMapGLLib_box BMapGLLib_hander', 'hander')); for (var i = 0, len = this.drawingModes.length; i < len; i++) { var classStr = 'BMapGLLib_box BMapGLLib_' + this.drawingModes[i]; if (i == len - 1) { classStr += ' BMapGLLib_last'; } fragment.appendChild(getItem(classStr, this.drawingModes[i])); } return fragment; }; /** * 设置工具栏的缩放比例 */ DrawingTool.prototype._setScale = function (scale) { var width = 390, height = 50, ml = -parseInt((width - width * scale) / 2, 10), mt = -parseInt((height - height * scale) / 2, 10); this.container.style.cssText = [ '-moz-transform: scale(' + scale + ');', '-o-transform: scale(' + scale + ');', '-webkit-transform: scale(' + scale + ');', 'transform: scale(' + scale + ');', 'margin-left:' + ml + 'px;', 'margin-top:' + mt + 'px;', '*margin-left:0px;', // ie6、7 '*margin-top:0px;', // ie6、7 'margin-left:0px\\0;', // ie8 'margin-top:0px\\0;', // ie8 // ie下使用滤镜 'filter: progid:DXImageTransform.Microsoft.Matrix(', 'M11=' + scale + ',', 'M12=0,', 'M21=0,', 'M22=' + scale + ',', 'SizingMethod=\'auto expand\');' ].join(''); }; // 绑定工具栏的事件 DrawingTool.prototype._bind = function (panel) { var me = this; baidu.on(this.panel, 'click', function (e) { var target = baidu.getTarget(e); var drawingType = target.getAttribute('drawingType'); me.setStyleByDrawingMode(drawingType); me._bindEventByDraingMode(drawingType); }); }; // 设置工具栏当前选中的项样式 DrawingTool.prototype.setStyleByDrawingMode = function (drawingType) { if (!drawingType) { return; } var boxs = this.panel.getElementsByTagName('a'); for (var i = 0, len = boxs.length; i < len; i++) { var box = boxs[i]; if (box.getAttribute('drawingType') == drawingType) { var classStr = 'BMapGLLib_box BMapGLLib_' + drawingType + '_hover'; if (i == len - 1) { classStr += ' BMapGLLib_last'; } box.className = classStr; } else { box.className = box.className.replace(/_hover/, ''); } } }; // 设置工具栏当前选中的项样式 DrawingTool.prototype._bindEventByDraingMode = function (drawingType) { var me = this; var drawingManager = this.drawingManager; // 点在拖拽地图的按钮上 // hander工具的逻辑 // if (drawingType == 'hander') { // drawingManager.close(); // drawingManager._map.enableDoubleClickZoom(); // } // else { // drawingManager.setDrawingMode(drawingType); // drawingManager.open(); // drawingManager._map.disableDoubleClickZoom(); // } // 关闭hander工具的逻辑 if (drawingManager._isOpen && drawingManager.getDrawingMode() === drawingType) { drawingManager.close(); drawingManager._map.enableDoubleClickZoom(); } else { drawingManager.setDrawingMode(drawingType); drawingManager.open(); drawingManager._map.disableDoubleClickZoom(); } }; // 用来存储用户实例化出来的drawingmanager对象 var instances = []; /* * 关闭其他实例的绘制模式 * @param {DrawingManager} 当前的实例 */ function closeInstanceExcept(instance) { var index = instances.length; while (index--) { if (instances[index] != instance) { instances[index].close(); } } } function drawcircle(center, radius) { var points = []; var cx = center["lng"], cy = center["lat"]; var d = radius / 6378800, // circle radius / meters of Earth radius = radians lat1 = (Math.PI / 180) * cy, lng1 = (Math.PI / 180) * cx; for (var i = 0; i < 271; i += 9) { var tc = (Math.PI / 180) * i, y = Math.asin(Math.sin(lat1) * Math.cos(d) + Math.cos(lat1) * Math.sin(d) * Math.cos(tc)), dlng = Math.atan2(Math.sin(tc) * Math.sin(d) * Math.cos(lat1), Math.cos(d) - Math.sin(lat1) * Math.sin(y)), x = ((lng1 - dlng + Math.PI) % (2 * Math.PI)) - Math.PI, point = new BMapGL.Point(x * (180 / Math.PI), y * (180 / Math.PI)); points.push(point); } var fstPoint = points[0]; points.push(new BMapGL.Point(fstPoint["lng"], fstPoint["lat"])); return points; } function getPointByDistance(srcPoint, distance, direction) { var cx = srcPoint["lng"], cy = srcPoint["lat"]; var d = distance / 6378800, // circle radius / meters of Earth radius = radians lat1 = (Math.PI / 180) * cy, lng1 = (Math.PI / 180) * cx; var i,tmplng,tmplat; switch (direction) { case 'North': case 'north': case 'N': case 'n': i = 0; tmplng = srcPoint.lng; break; case 'West': case 'west': case 'W': case 'w': i = 90; tmplat = srcPoint.lat; break; case 'South': case 'south': case 'S': case 's': i = 180; tmplng = srcPoint.lng; break; case 'East': case 'east': case 'E': case 'e': i = 270; tmplat = srcPoint.lat; break; default: i = ~~direction; break; } var tc = (Math.PI / 180) * i, y = Math.asin(Math.sin(lat1) * Math.cos(d) + Math.cos(lat1) * Math.sin(d) * Math.cos(tc)), dlng = Math.atan2(Math.sin(tc) * Math.sin(d) * Math.cos(lat1), Math.cos(d) - Math.sin(lat1) * Math.sin(y)), x = ((lng1 - dlng + Math.PI) % (2 * Math.PI)) - Math.PI, point = new BMapGL.Point(tmplng || x * (180 / Math.PI), tmplat || y * (180 / Math.PI)); point.lng = parseFloat(point.lng.toFixed(6)); point.lat = parseFloat(point.lat.toFixed(6)); return point; } })();