百度地圖提供了多邊形繪製的功能,可是對於不符合多邊形規則的圖形卻沒有作限制:javascript
因此咱們在繪製的時候須要判斷當前繪製的圖形是不是多邊形:php
1:下載百度地圖開源庫裏面的鼠標繪製工具條庫:DrawingManager.jscss
2:找到DrawingManager.prototype._bindPolylineOrPolygon方法裏面的startAction方法,在咱們繪製的時候會觸發該方法,在startAction裏咱們會拿到當前準備繪製的點位e.point,而points是繪製以前的多邊形的點位數組html
3:引用下面的js文件java
4:在DrawingManager.js文件裏面對應多邊形的startAction最開始的地方,寫下:node
var currentPoints = points.concat(e.point); if(window.isPolygon(currentPoints) == false){ if(window.currentFanceVueInstance){ window.currentFanceVueInstance.promptBox.mes = "該操做不被容許" window.currentFanceVueInstance.promptBox.show = true; } window.drawPolygonEnable = false; return; }
完整代碼(polygon.js):web
(function(w){ /* 方法名稱:isPolygon 功能描述:判斷是不是多邊形 判斷依據:多邊形的每條線段最多和兩條線段相交 參數描述: pointData:多邊形各個點的順序數組([{lat:31,lng:121},{lat:32,lng:122}]) 返回值: true:是多邊形 false:不是多邊形 */ var isPolygon = function(pointData){ console.log("pointData:",pointData) var pointsList = unique(pointData); console.log("pointsList:",pointsList) if(pointsList.length < 3){ return true; } var len = pointsList.length, isPolygon = true, line = null, otherLineList = [], currentLine = null, item = null, OverlapLineCount = 0, prevItem = null, nextItem = null; if(len < 3){ return false; } for(var i = 0;i < len; i++){ item = pointsList[i]; prevItem = pointsList[i-1]; if( i == len-1){ nextItem = pointsList[0]; }else{ nextItem = pointsList[i+1]; } currentLine = { S:{ x:item.lat, y:item.lng, }, E:{ x:nextItem.lat, y:nextItem.lng, } } otherLineList = getPolygonLine(pointsList,currentLine); OverlapLineCount = getOverlapCount(currentLine,otherLineList); if(OverlapLineCount.length > 2){ isPolygon = false; break; } } return isPolygon; } var unique = function(list){ var res = [], json = {}, key = "", item = null, len = list.length; for(var i = 0; i < len; i++){ item = list[i]; key = "" + item.lat + item.lng; if(!!json[key] == false){ res.push(item); json[key] = 1; } } return res; } /* 方法名稱:getPolygonLine 功能描述:獲取多邊形除指定線段的其餘線段 參數描述: pointsList:多邊形各個點的順序數組 line:指定排除的線段 返回值:多邊形線段數組 */ var getPolygonLine = function(pointsList,expectLine){ var len = pointsList.length, line = null, item = null, lineList = [], prevItem = null, nextItem = null; for(var i = 0;i < len; i++){ item = pointsList[i]; prevItem = pointsList[i-1]; if( i == len-1){ nextItem = pointsList[0]; }else{ nextItem = pointsList[i+1]; } if(parseFloat(item.lat) == parseFloat(expectLine.S.x) && parseFloat(item.lng) == parseFloat(expectLine.S.y)){ continue; } line = { S:{ x:item.lat, y:item.lng, }, E:{ x:nextItem.lat, y:nextItem.lng, } } lineList.push(line); } return lineList; } /* 方法名稱:getOverlapCount 功能描述:獲取指定線段與線段數組裏面相交的線段(不包括斜率一致的) 參數描述: line:指定線段 lineList:線段數組 返回值:返回相交的線段 */ var getOverlapCount = function(line,lineList){ var len = lineList.length, item = null, OverlapLine = []; for(var i = 0; i < len; i++){ item = lineList[i]; if(isOverlapping(line,item) && isEqualK(line,item) == false){ OverlapLine.push(item); } } return OverlapLine; } /* 方法名稱:isEqualK 功能描述:判斷斜率是否一致 參數描述: lineA:線段A lineB:線段B 返回值: true:一致 false:不一致 */ var isEqualK = function(lineA,lineB){ var lineAK = getLineK(lineA.S.x,lineA.S.y,lineA.E.x,lineA.E.y); var lineBK = getLineK(lineB.S.x,lineB.S.y,lineB.E.x,lineB.E.y); return lineAK == lineBK; } /* 方法名稱:isOverlapping 功能描述:判斷兩個線段是否相交 參數描述: lineA:線段A lineB:線段B 返回值: true:交叉 false:不交叉 判斷依據:1:判斷兩條線段的端點是否存在在彼此之上的狀況,2:判斷兩個線段的兩個端點是否都在彼此的兩邊 */ var isOverlapping = function(lineA,lineB){ var lineAStartPointInLineB = isPointInLine(lineA.S,lineB.S,lineB.E); var lineAEndPointInLineB = isPointInLine(lineA.E,lineB.S,lineB.E); var lineBStartPointInLineA = isPointInLine(lineB.S,lineA.S,lineA.E); var lineBEndPointInLineA = isPointInLine(lineB.E,lineA.S,lineA.E); //只要有一點在另一條線上咱們就認爲相交,也就是兩條直線相交 if(lineAStartPointInLineB == 0 || lineAEndPointInLineB == 0 || lineBStartPointInLineA == 0 || lineBEndPointInLineA == 0 ){ return true; } //若是上面條件不知足,點都不在對應的線段上,可是有一個點在另一條線的延長線上,說明必定不會相交 if(lineAStartPointInLineB == -2 || lineAEndPointInLineB == -2 || lineBStartPointInLineA == -2 || lineBEndPointInLineA == -2 ){ return false; } //由於在上面是1,在下面是-1,兩個相乘若是小於0則必定在兩邊,若是兩條線段的兩個端點分別在對應線段的兩端,說明相交 if(lineAStartPointInLineB*lineAEndPointInLineB < 1 && lineBStartPointInLineA*lineBEndPointInLineA < 1){ return true; } return false;//默認不相交 } /* 方法名稱:isPointInLine 功能描述:判斷點point是否在以linePS爲起點,linePE爲終點的線段上 參數描述: point:點 linePS:線段起點 linePE:線段終點 返回值: 0:在線段上 1:不在線段上,而是在線段的上方 -1:不在線段上,而是在線段的下方 -2:不在線段上,而是在線段所在的直線上 */ var isPointInLine = function(point,linePS,linePE){ var maxLineX = 0, minLineX = 0, maxLineY = 0, minLineY = 0, K = getLineK(linePS.x,linePS.y,linePE.x,linePE.y); var B = getLineB(linePS.x,linePS.y,K); var linePointY = (K*point.x+B); if(linePS.x < linePE.x){ maxLineX = linePE.x;minLineX = linePS.x; }else{ maxLineX = linePS.x;minLineX = linePE.x; } if(linePS.y < linePE.y){ maxLineY = linePE.y;minLineY = linePS.y; }else{ maxLineY = linePS.y;minLineY = linePE.y; } if(point.x >= minLineX && point.x <= maxLineX && point.y >= minLineY && point.y <= maxLineY){//在線段所在的矩形範圍以內 if(linePointY == point.y){ return 0; }else if(linePointY > point.y){ if(point.y >= 0){ return -1 }else { return 1 } }else{ if(point.y >= 0){ return 1 }else { return -1 } } }else{ if(linePointY == point.y){ return -2; }else if(linePointY > point.y){ if(point.y >= 0){ return -1 }else{ return 1 } }else{ if(point.y >= 0){ return 1 }else{ return -1 } } } } /* 方法名稱:getLineK 功能描述:獲取線段的斜率 參數描述: x1:X座標1 y1:Y座標1 x2:X座標2 y2:Y座標2 返回值:斜率 */ var getLineK = function(x1,y1,x2,y2){ return (y1-y2)/(x1-x2); } /* 方法名稱:getLineB 功能描述:獲取線段的y軸截距 參數描述: x1:X座標1 y1:Y座標1 k:斜率 返回值:線段的y軸截距 */ var getLineB = function(x1,y1,k){ return y1-k*x1; } w.isPolygon = isPolygon; })(window);
完整代碼(DrawingManager.js):chrome
/** * @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_CLOSE = "close", // 鼠標畫線模式 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; } baidu.browser = baidu.browser || {}; if (/msie (\d+\.\d)/i.test(navigator.userAgent)) { //IE 8下,以documentMode爲準 //在百度模板中,可能會有$,防止衝突,將$1 寫成 \x241 /** * 判斷是否爲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.ie = baidu.ie = document.documentMode || + RegExp['\x241']; } })(); /** * @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; } var me = this; this._close(); setTimeout(function(){ me._map.enableDoubleClickZoom(); },2000); } /** * 設置當前的繪製模式,參數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.controlButton = opts.controlButton == "right" ? "right" : "left"; }, /** * 開啓地圖的繪製狀態 * @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 = {}; console.log("mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm") 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) { if(me.controlButton == "right" && (e.button == 1 || e.button==0)){ return ; } centerPoint = e.point; circle = new BMap.Circle(centerPoint, 0, me.circleOptions); window.currentcircle = circle; 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(me.controlButton == "right" && e.button == 1){ return ; } 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) { window.DrawPlogining = true; var currentPoints = points.concat(e.point); if(window.isPolygon(currentPoints) == false){ if(window.currentFanceVueInstance){ window.currentFanceVueInstance.promptBox.mes = "該操做不被容許" window.currentFanceVueInstance.promptBox.show = true; } window.drawPolygonEnable = false; return; }else{ window.drawPolygonEnable = true; } if(me.controlButton == "right" && (e.button == 1 || e.button==0)){ 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) { overlay.setPositionAt(drawPoint.length - 1, e.point); } /** * 鼠標雙擊的事件 */ var dblclickAction = function (e) { if(window.drawPolygonEnable == false){ if(window.currentFanceVueInstance){ window.currentFanceVueInstance.promptBox.mes = "該操做不被容許" window.currentFanceVueInstance.promptBox.show = true; } return; } window.DrawPlogining = false; baidu.stopBubble(e); isBinded = false; mask.disableEdgeMove(); mask.removeEventListener('mousedown',startAction); mask.removeEventListener('mousemove', mousemoveAction); mask.removeEventListener('dblclick', dblclickAction); if(me.controlButton == "right"){ points.push(e.point); } else if(baidu.ie <= 8){ }else{ points.pop(); } overlay.setPath(points); var calculate = me._calculate(overlay, points.pop()); me._dispatchOverlayComplete(overlay, calculate); points.length = 0; drawPoint.length = 0; me.close(); } 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; /** * 開始繪製矩形 */ 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 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); } 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 }; if (calculate) { options.calculate = calculate.data || null; options.label = calculate.label || null; } this.dispatchEvent(this._drawingType + 'complete', overlay); this.dispatchEvent('overlaycomplete', options); } /** * 建立遮罩對象 */ function Mask(){ /** * 鼠標到地圖邊緣的時候是否自動平移地圖 */ this._enableEdgeMove = false; } Mask.prototype = new BMap.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: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) { if(className == "BMapLib_box BMapLib_hander"){ return '<a style="display:none;" class="' + className + '" drawingType="' + drawingType + '" href="javascript:void(0)" title="' + tips[drawingType] + '" onfocus="this.blur()"></a>'; } 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;", //ie六、7 "*margin-top:0px;", //ie六、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'); if(drawingType == "circle"){ if(!!window.currentcircle && window.currentFanceVueInstance){ window.currentFanceVueInstance.remind.remindModalControl = true; window.currentFanceVueInstance.remind.msg = "請先結束正在編輯的圍欄!"; window.currentFanceVueInstance.map.panTo(window.currentFanceVueInstance.currentDrawRound.getCenter()) return; } } if(drawingType == "polygon" && !!window.currentFanceVueInstance){ if(!!window.currentFanceVueInstance.currentDrawRound){ window.currentFanceVueInstance.showMsg("請先結束正在編輯的圍欄!") return; } window.currentFanceVueInstance.isdrawing = true; } if(drawingType == "close" && !!window.currentFanceVueInstance){ if(window.DrawPlogining){ if(window.currentFanceVueInstance){ window.currentFanceVueInstance.promptBox.mes = "該操做不被容許" window.currentFanceVueInstance.promptBox.show = true; } return; }else{ window.currentFanceVueInstance.toggleMap(); } } 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 me = this; var drawingManager = this.drawingManager; //點在拖拽地圖的按鈕上 if (drawingType == "hander" || drawingType == "close") { 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(); } } } })();