滑鼠繪製工具加是否超出範圍判斷
阿新 • • 發佈:2019-01-12
初始化滑鼠繪製工具的程式碼:
//例項化滑鼠繪製工具 _this.drawingManager = new BMapLib.DrawingManager(_this.addMap, { isOpen: true, //是否開啟繪製模式 enableDrawingTool: false, //是否顯示工具欄 drawingToolOptions: { anchor: BMAP_ANCHOR_TOP_RIGHT, //位置 offset: new BMap.Size(5, 5), //偏離值 drawingModes: [ BMAP_DRAWING_POLYGON ] }, polygonOptions: _this.styleOptions, //多邊形的樣式 //----------------主要是這裡哦---------------- outRange:false,//是否超出範圍 hasLabel:false//是否顯示label });
然後先新增一個多邊形,滑鼠繪製不可以離開多邊形:
var ply = new BMap.Polygon(points, { strokeWeight: 2, strokeColor: red, fillOpacity: 0.4}); //建立多邊形覆蓋物
.addEventListener("mouseover", this.mouseover);
ply.addEventListener("mouseout", this.mouseout);
this.addMap.addOverlay(ply);
下面是滑鼠移入移出事件:
//子網格滑鼠移入事件,如果正在繪製,並且繪製模式為選中狀態 mouseover(evt) { if(this.drawingManager._isOpen&&this.drawingManager.getDrawingMode()!='marker'){ if(!this.drawingManager._outRange){ this.drawingManager.outRangeAction(); } } }, mouseout(evt) { if(this.drawingManager._isOpen && this.drawingManager.getDrawingMode()!='marker'){ if(this.drawingManager._outRange){ this.drawingManager.inRangeAction(); } } }
DrawingManager.js原始碼:搜尋outRange可直接檢視我加的一些程式碼
/** * @fileoverview 百度地圖的滑鼠繪製工具,對外開放。 * 允許使用者在地圖上點選完成滑鼠繪製的功能。 * 使用者可以自定義所繪製結果的相關樣式,例如線寬、顏色、測線段距離、面積等等。 * 主入口類是<a href="symbols/BMapLib.DrawingManager.html">DrawingManager</a>, * 基於Baidu Map API 1.4。 * * @author Baidu Map Api Group * @version 1.4 */ /** * @namespace BMap的所有library類均放在BMapLib名稱空間下 */ var BMapLib = window.BMapLib = BMapLib || {}; /** * 定義常量, 繪製的模式 * @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的類應該直接或者間接呼叫它的建構函式。<br> * 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繫結的自定義事件回撥函式之外,還會呼叫直接繫結到物件上面的自定義事件。 * 例如:<br> * myobj.onMyEvent = function(){}<br> * 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中定義的所有屬性和方法。<br> * 這個函式實際上是建立了subClass和superClass的原型鏈整合,並對subClass進行了constructor修正。<br> * <strong>注意:如果要繼承建構函式,需要在subClass裡面call一下,具體見下面的demo例子</strong> * @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引數,大小寫不敏感<br> * 引數的意思:beforeBegin<span>afterBegin this is span! beforeEnd</span> afterEnd <br /> * 此外,如果使用本函式插入帶有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. 不支援跨瀏覽器的滑鼠滾輪事件監聽器新增<br> * 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; } })(); /** * @exports DrawingManager as BMapLib.DrawingManager */ var DrawingManager = /** * DrawingManager類的建構函式 * @class 滑鼠繪製管理類,實現滑鼠繪製管理的<b>入口</b>。 * 例項化該類後,即可呼叫該類提供的open * 方法開啟繪製模式狀態。 * 也可加入工具欄進行選擇操作。 * * @constructor * @param {Map} map Baidu map的例項物件 * @param {Json Object} opts 可選的輸入引數,非必填項。可輸入選項包括:<br /> * {"<b>isOpen</b>" : {Boolean} 是否開啟繪製模式 * <br />"<b>enableDrawingTool</b>" : {Boolean} 是否新增繪製工具欄控制元件,預設不新增 * <br />"<b>drawingToolOptions</b>" : {Json Object} 可選的輸入引數,非必填項。可輸入選項包括 * <br /> "<b>anchor</b>" : {ControlAnchor} 停靠位置、預設左上角 * <br /> "<b>offset</b>" : {Size} 偏移值。 * <br /> "<b>scale</b>" : {Number} 工具欄的縮放比例,預設為1 * <br /> "<b>drawingModes</b>" : {DrawingType<Array>} 工具欄上可以選擇出現的繪製模式,將需要顯示的DrawingType以陣列型形式傳入,如[BMAP_DRAWING_MARKER, BMAP_DRAWING_CIRCLE] 將只顯示畫點和畫圓的選項 * <br />"<b>enableCalculate</b>" : {Boolean} 繪製是否進行測距(畫線時候)、測面(畫圓、多邊形、矩形) * <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> * <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> * <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> * <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> * <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> * * @example <b>參考示例:</b><br /> * var map = new BMap.Map("container");<br />map.centerAndZoom(new BMap.Point(116.404, 39.915), 15);<br /> * var myDrawingManagerObject = new BMapLib.DrawingManager(map, {isOpen: true, * drawingType: BMAP_DRAWING_MARKER, enableDrawingTool: true, * enableCalculate: false, * drawingToolOptions: { * anchor: BMAP_ANCHOR_TOP_LEFT, * offset: new BMap.Size(5, 5), * drawingTypes : [ * BMAP_DRAWING_MARKER, * BMAP_DRAWING_CIRCLE, * BMAP_DRAWING_POLYLINE, * BMAP_DRAWING_POLYGON, * BMAP_DRAWING_RECTANGLE * ] * }, * polylineOptions: { * strokeColor: "#333" * }); */ BMapLib.DrawingManager = function(map, opts){ if (!map) { return; } instances.push(this); opts = opts || {}; this._initialize(map, opts); } // 通過baidu.lang下的inherits方法,讓DrawingManager繼承baidu.lang.Class baidu.lang.inherits(DrawingManager, baidu.lang.Class, "DrawingManager"); /** * 開啟地圖的繪製模式 * * @example <b>參考示例:</b><br /> * myDrawingManagerObject.open(); */ DrawingManager.prototype.open = function() { // 判斷繪製狀態是否已經開啟 if (this._isOpen == true){ return true; } closeInstanceExcept(this); this._open(); } /** * 關閉地圖的繪製狀態 * * @example <b>參考示例:</b><br /> * myDrawingManagerObject.close(); */ DrawingManager.prototype.close = function() { // 判斷繪製狀態是否已經開啟 if (this._isOpen == false){ return true; } this._close(); } DrawingManager.prototype.outRangeAction=function(){ this._outRangeAction(); } DrawingManager.prototype.inRangeAction=function(){ this._inRangeAction(); } /** * 設定當前的繪製模式,引數DrawingType,為5個可選常量: * <br/>BMAP_DRAWING_MARKER 畫點 * <br/>BMAP_DRAWING_CIRCLE 畫圓 * <br/>BMAP_DRAWING_POLYLINE 畫線 * <br/>BMAP_DRAWING_POLYGON 畫多邊形 * <br/>BMAP_DRAWING_RECTANGLE 畫矩形 * @param {DrawingType} DrawingType * @return {Boolean} * * @example <b>參考示例:</b><br /> * myDrawingManagerObject.setDrawingMode(BMAP_DRAWING_POLYLINE); */ DrawingManager.prototype.setDrawingMode = function(drawingType) { //與當前模式不一樣時候才進行重新繫結事件 if (this._drawingType != drawingType) { closeInstanceExcept(this); this._setDrawingMode(drawingType); } } /** * 獲取當前的繪製模式 * @return {DrawingType} 繪製的模式 * * @example <b>參考示例:</b><br /> * alert(myDrawingManagerObject.getDrawingMode()); */ DrawingManager.prototype.getDrawingMode = function() { return this._drawingType; } /** * 開啟距離或面積計算 * * @example <b>參考示例:</b><br /> * myDrawingManagerObject.enableCalculate(); */ DrawingManager.prototype.enableCalculate = function() { this._enableCalculate = true; this._addGeoUtilsLibrary(); } /** * 關閉距離或面積計算 * * @example <b>參考示例:</b><br /> * myDrawingManagerObject.disableCalculate(); */ DrawingManager.prototype.disableCalculate = function() { this._enableCalculate = false; } /** * 滑鼠繪製完成後,派發總事件的介面 * @name DrawingManager#overlaycomplete * @event * @param {Event Object} e 回撥函式會返回event引數,包括以下返回值: * <br />{"<b>drawingMode</b> : {DrawingType} 當前的繪製模式 * <br />"<b>overlay</b>:{Marker||Polyline||Polygon||Circle} 對應的繪製模式返回對應的覆蓋物 * <br />"<b>calculate</b>:{Number} 需要開啟計算模式才會返回這個值,當繪製線的時候返回距離、繪製多邊形、圓、矩形時候返回面積,單位為米, * <br />"<b>label</b>:{Label} 計算面積時候出現在Map上的Label物件 * * @example <b>參考示例:</b> * myDrawingManagerObject.addEventListener("overlaycomplete", function(e) { * alert(e.drawingMode); * alert(e.overlay); * alert(e.calculate); * alert(e.label); * }); */ /** * 繪製點完成後,派發的事件介面 * @name DrawingManager#markercomplete * @event * @param {Marker} overlay 回撥函式會返回相應的覆蓋物, * <br />{"<b>overlay</b> : {Marker} * * @example <b>參考示例:</b> * myDrawingManagerObject.addEventListener("circlecomplete", function(e, overlay) { * alert(overlay); * }); */ /** * 繪製圓完成後,派發的事件介面 * @name DrawingManager#circlecomplete * @event * @param {Circle} overlay 回撥函式會返回相應的覆蓋物, * <br />{"<b>overlay</b> : {Circle} */ /** * 繪製線完成後,派發的事件介面 * @name DrawingManager#polylinecomplete * @event * @param {Polyline} overlay 回撥函式會返回相應的覆蓋物, * <br />{"<b>overlay</b> : {Polyline} */ /** * 繪製多邊形完成後,派發的事件介面 * @name DrawingManager#polygoncomplete * @event * @param {Polygon} overlay 回撥函式會返回相應的覆蓋物, * <br />{"<b>overlay</b> : {Polygon} */ /** * 繪製矩形完成後,派發的事件介面 * @name DrawingManager#rectanglecomplete * @event * @param {Polygon} overlay 回撥函式會返回相應的覆蓋物, * <br />{"<b>overlay</b> : {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) { var drawingTool = new DrawingTool(this, opts.drawingToolOptions); this._drawingTool = drawingTool; map.addControl(drawingTool); } //是否計算繪製出的面積 if (opts.enableCalculate === true) { this.enableCalculate(); } else { this.disableCalculate(); } /** * 是否已經開啟了繪製狀態 * @private * @type {Boolean} */ this._isOpen = !!(opts.isOpen === true); if (this._isOpen) { this._open(); } this.markerOptions = opts.markerOptions || {}; this.circleOptions = opts.circleOptions || {}; this.polylineOptions = opts.polylineOptions || {}; this.polygonOptions = opts.polygonOptions || {}; this.rectangleOptions = opts.rectangleOptions || {}; /**是否越界 */ this._outRange=!!(opts.outRange === true); this._hasLabel=!!(opts.hasLabel === true); }, DrawingManager.prototype._outRangeAction= function(){ this._outRange=true; } DrawingManager.prototype._inRangeAction= function(){ this._outRange=false; } /** * 開啟地圖的繪製狀態 * @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 BMap.Marker(e.point, me.markerOptions); map.addOverlay(marker); me._dispatchOverlayComplete(marker); } mask.addEventListener('click', clickAction); } /** * 繫結滑鼠畫圓的事件 */ DrawingManager.prototype._bindCircle = function() { var me = this, map = this._map, mask = this._mask, circle = null, centerPoint = null; //圓的中心點 /** * 開始繪製圓形 */ var startAction = function (e) { centerPoint = e.point; circle = new BMap.Circle(centerPoint, 0, me.circleOptions); map.addOverlay(circle); mask.enableEdgeMove(); mask.addEventListener('mousemove', moveAction); baidu.on(document, 'mouseup', endAction); } /** * 繪製圓形過程中,滑鼠移動過程的事件 */ var moveAction = function(e) { circle.setRadius(me._map.getDistance(centerPoint, e.point)); } /** * 繪製圓形結束 */ var endAction = function (e) { var calculate = me._calculate(circle, e.point); me._dispatchOverlayComplete(circle, calculate); centerPoint = null; mask.disableEdgeMove(); mask.removeEventListener('mousemove', moveAction); baidu.un(document, 'mouseup', endAction); } /** * 滑鼠點選起始點 */ var mousedownAction = function (e) { baidu.preventDefault(e); baidu.stopBubble(e); if (centerPoint == null) { startAction(e); } } mask.addEventListener('mousedown', mousedownAction); } /** * 畫線和畫多邊形相似性比較大,公用一個方法 */ DrawingManager.prototype._bindPolylineOrPolygon = function() { var me = this, map = this._map, mask = this._mask, points = [], //使用者繪製的點 drawPoint = null; //實際需要畫在地圖上的點 overlay = null, isBinded = false; /** * 滑鼠點選的事件 */ var startAction = function (e) { if(me._outRange){ return; } points.push(e.point); drawPoint = points.concat(points[points.length - 1]); if (points.length == 1) { if (me._drawingType == BMAP_DRAWING_POLYLINE) { overlay = new BMap.Polyline(drawPoint, me.polylineOptions); } else if (me._drawingType == BMAP_DRAWING_POLYGON) { overlay = new BMap.Polygon(drawPoint, me.polygonOptions); } map.addOverlay(overlay); } else { overlay.setPath(drawPoint); } if (!isBinded) { isBinded = true; mask.enableEdgeMove(); mask.addEventListener('mousemove', mousemoveAction); mask.addEventListener('dblclick', dblclickAction); } } /** * 滑鼠移動過程的事件 */ var mousemoveAction = function(e) { //自定義---如果超出範圍,禁止地圖自動平移 if(me._outRange){ mask.disableEdgeMove(); return; } overlay.setPositionAt(drawPoint.length - 1, e.point); } /** * 滑鼠雙擊的事件 */ var dblclickAction = function (e) { baidu.stopBubble(e); isBinded = false; mask.disableEdgeMove(); mask.removeEventListener('mousemove', mousemoveAction); mask.removeEventListener('dblclick', dblclickAction); overlay.setPath(points); var calculate = me._calculate(overlay, points.pop()); me._dispatchOverlayComplete(overlay, calculate); points.length = 0; drawPoint.length = 0; } mask.addEventListener('click', 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; /** * 開始繪製矩形 */ var startAction = function (e) { baidu.stopBubble(e); baidu.preventDefault(e); startPoint = e.point; var endPoint = startPoint; polygon = new BMap.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) { polygon.setPath(me._getRectanglePoint(startPoint, e.point)); } /** * 繪製矩形結束 */ var endAction = function (e) { var calculate = me._calculate(polygon, polygon.getPath()[2]); me._dispatchOverlayComplete(polygon, calculate); startPoint = null; mask.disableEdgeMove(); mask.removeEventListener('mousemove', moveAction); baidu.un(document, 'mouseup', endAction); } mask.addEventListener('mousedown', startAction); } /** * 新增顯示所繪製圖形的面積或者長度 * @param {overlay} 覆蓋物 * @param {point} 顯示的位置 */ DrawingManager.prototype._calculate = function (overlay, point) { var result = { data : 0, //計算出來的長度或面積 label : null //顯示長度或面積的label物件 }; if (this._enableCalculate && BMapLib.GeoUtils) { var type = overlay.toString(); //不同覆蓋物呼叫不同的計算方法 switch (type) { case "[object Polyline]": result.data = BMapLib.GeoUtils.getPolylineDistance(overlay); break; case "[object Polygon]": result.data = BMapLib.GeoUtils.getPolygonArea(overlay); break; case "[object Circle]": var radius = overlay.getRadius(); result.data = Math.PI * radius * radius; break; } //一場情況處理 if (!result.data || result.data < 0) { result.data = 0; } else { //保留2位小數位 result.data = result.data.toFixed(2); } //如果需要顯示LABEL並且面積大於0 if(this._hasLabel && result.data >0){ //把標籤的位置放到了最後一個點的位置 result.label = this._addLabel(point, result.data); } } return result; } /** * 開啟測距和測面功能需要依賴於GeoUtils庫 * 所以這裡判斷使用者是否已經載入,若未載入則用js動態載入 */ DrawingManager.prototype._addGeoUtilsLibrary = function () { if (!BMapLib.GeoUtils) { var script = document.createElement('script'); script.setAttribute("type", "text/javascript"); script.setAttribute("src", 'http://api.map.baidu.com/library/GeoUtils/1.2/src/GeoUtils_min.js'); document.body.appendChild(script); } } /** * 向地圖中新增文字標註 * @param {Point} * @param {String} 所以顯示的內容 */ DrawingManager.prototype._addLabel = function (point, content) { var label = new BMap.Label(content, { position: point }); this._map.addOverlay(label); return label; } /** * 根據起終點獲取矩形的四個頂點 * @param {Point} 起點 * @param {Point} 終點 */ DrawingManager.prototype._getRectanglePoint = function (startPoint, endPoint) { return [ new BMap.Point(startPoint.lng,startPoint.lat), new BMap.Point(endPoint.lng,startPoint.lat), new BMap.Point(endPoint.lng,endPoint.lat), new BMap.Point(startPoint.lng,endPoint.lat) ]; } /** * 派發事件 */ DrawingManager.prototype._dispatchOverlayComplete = function (overlay, calculate) { var options = { 'overlay' : overlay, 'drawingMode' : this._drawingType, 'calculate' : calculate.data || null, 'label' : calculate.label || null }; this.dispatchEvent(this._drawingType + 'complete', overlay); this.dispatchEvent('overlaycomplete', options); } /** * 建立遮罩物件 */ function Mask(){ /** * 滑鼠到地圖邊緣的時候是否自動平移地圖 */ this._enableEdgeMove = false; } Mask.prototype = new BMap.Overlay(); // Mask.disableMassClear(); /** * 這裡不使用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.se = false; this._map = map; var div = this.container = document.createElement("div"); div.id="mask"; var size = this._map.getSize(); div.style.cssText = "position:absolute;background:url(about:blank);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 BMap.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 BMap.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 BMap.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 BMap.Pixel(x, y); var point = map.pixelToPoint(pixel); return point; } /** * 繪製工具面板,自定義控制元件 */ function DrawingTool(drawingManager, drawingToolOptions) { this.drawingManager = drawingManager; drawingToolOptions = this.drawingToolOptions = drawingToolOptions || {}; // 預設停靠位置和偏移量 this.defaultAnchor = BMAP_ANCHOR_TOP_LEFT; this.defaultOffset = new BMap.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.anchor) { this.setAnchor(drawingToolOptions.anchor); } if (drawingToolOptions.offset) { this.setOffset(drawingToolOptions.offset); } } // 通過JavaScript的prototype屬性繼承於BMap.Control DrawingTool.prototype = new BMap.Control(); // 自定義控制元件必須實現自己的initialize方法,並且將控制元件的DOM元素返回 // 在本方法中建立個div元素作為控制元件的容器,並將其新增到地圖容器中 DrawingTool.prototype.initialize = function(map){ // 建立一個DOM元素 var container = this.container = document.createElement("div"); container.className = "BMapLib_Drawing"; //用來設定外層邊框陰影 var panel = this.panel = document.createElement("div"); panel.className = "BMapLib_Drawing_panel"; if (this.drawingToolOptions && this.drawingToolOptions.scale) { this._setScale(this.drawingToolOptions.scale); } container.appendChild(panel); // 新增內容 panel.innerHTML = this._generalHtml(); //繫結事件 this._bind(panel); // 新增DOM元素到地圖中 map.getContainer().appendChild(container); // 將DOM元素返回 return container; } //生成工具欄的html元素 DrawingTool.prototype._generalHtml = function(map){ //滑鼠經過工具欄上的提示資訊 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) { return '<a class="' + className + '" drawingType="' + drawingType + '" href="javascript:void(0)" title="' + tips[drawingType] + '" onfocus="this.blur()"></a>'; } var html = []; html.push(getItem("BMapLib_box BMapLib_hander", "hander")); for (var i = 0, len = this.drawingModes.length; i < len; i++) { var classStr = 'BMapLib_box BMapLib_' + this.drawingModes[i]; if (i == len-1) { classStr += ' BMapLib_last'; } html.push(getItem(classStr, this.drawingModes[i])); } return html.join(''); } /** * 設定工具欄的縮放比例 */ 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 = "BMapLib_box BMapLib_" + drawingType + "_hover"; if (i == len - 1) { classStr += " BMapLib_last"; } box.className = classStr; } else { box.className = box.className.replace(/_hover/, ""); } } } //設定工具欄當前選中的項樣式 DrawingTool.prototype._bindEventByDraingMode = function(drawingType){ var drawingManager = this.drawingManager; //點在拖拽地圖的按鈕上 if (drawingType == "hander") { drawingManager.close(); } else { drawingManager.setDrawingMode(drawingType); drawingManager.open(); } } //用來儲存使用者例項化出來的drawingmanager物件 var instances = []; /* * 關閉其他例項的繪製模式 * @param {DrawingManager} 當前的例項 */ function closeInstanceExcept(instance) { var index = instances.length; while (index--) { if (instances[index] != instance) { instances[index].close(); } } } })();