百度地圖多邊形繪製之多邊形判斷

百度地圖提供了多邊形繪製的功能,可是對於不符合多邊形規則的圖形卻沒有作限制: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&lt;span&gt;afterBegin   this is span! beforeEnd&lt;/span&gt; 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 />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"<b>anchor</b>" : {ControlAnchor} 停靠位置、默認左上角
         * <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"<b>offset</b>" : {Size} 偏移值。
         * <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"<b>scale</b>" : {Number} 工具欄的縮放比例,默認爲1
         * <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"<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();
            }
        }
    }

})();
相關文章
相關標籤/搜索