123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782 |
- /**
- * @fileoverview 百度地图的测距工具类,对外开放。
- * 允许用户在地图上点击完成距离的测量。
- * 使用者可以自定义测距线段的相关样式,例如线宽、颜色、测距结果所用的单位制等等。
- * 主入口类是<a href="symbols/BMapLib.DistanceTool.html">DistanceTool</a>,
- * 基于Baidu Map API 1.2。
- *
- * @author Baidu Map Api Group
- * @version 1.2
- */
- /**
- * @namespace BMap的所有library类均放在BMapLib命名空间下
- */
- (function (root, factory) {
- if (typeof exports === 'object') {
- module.exports = factory();
- } else if (typeof define === 'function' && define.amd) {
- define(factory);
- } else {
- root.BMapLib = root.BMapLib || {};
- root.BMapLib.Heatmap = root.BMapLib.DistanceTool || factory();
- }
- })(this, function() {
- var baidu = baidu || {guid : "$BAIDU$"};
- var context = {};
- (function() {
- // 一些页面级别唯一的属性,需要挂载在window[baidu.guid]上
- context[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__" + (context[baidu.guid]._counter ++).toString(36);
- };
- context[baidu.guid]._counter = context[baidu.guid]._counter || 1;
- /**
- * 所有类的实例的容器
- * key为每个实例的guid
- */
- context[baidu.guid]._instances = context[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();
- context[baidu.guid]._instances[this.guid] = this;
- };
- context[baidu.guid]._instances = context[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 context[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;
- };
- /**
- * 阻止事件的默认行为
- * @name baidu.event.preventDefault
- * @function
- * @grammar baidu.event.preventDefault(event)
- * @param {Event} event 事件对象
- * @meta standard
- */
- baidu.preventDefault = baidu.event.preventDefault = function (event) {
- if (event.preventDefault) {
- event.preventDefault();
- } else {
- event.returnValue = false;
- }
- };
- })();
- /**
- * @exports DistanceTool as BMapLib.DistanceTool
- */
- var DistanceTool = function(map, opts){
- if (!map) {
- return;
- }
-
- /**
- * OperationMask,透明覆盖层,在地图上进行鼠标绘制操作时使用
- */
- var OperationMask = this.OperationMask = {
- /**
- * map对象
- * @type {Map}
- */
- _map : null,
- /**
- * HTML字符串
- * @type {String}
- */
- _html : "<div style='background:transparent url(http://api.map.baidu.com/images/blank.gif);position:absolute;left:0;top:0;width:100%;height:100%;z-index:1000' unselectable='on'></div>",
- /**
- * html元素
- * @type {HTMLElement}
- */
- _maskElement : null,
- /**
- * 鼠标指针
- * @type {String}
- */
- _cursor: 'default',
- /**
- * 操作层是否在使用中
- * @type {Boolean}
- */
- _inUse: false,
- /**
- * 透明覆盖层的显示
- *
- * @param {Map} map map对象
- * @return 无返回值
- */
- show : function(map) {
- if (!this._map) {
- this._map = map;
- }
- this._inUse = true;
- if (!this._maskElement) {
- this._createMask(map);
- }
- this._maskElement.style.display = 'block';
- },
- /**
- * 创建覆盖层
- *
- * @param {Map} map map对象
- * @return 无返回值
- */
- _createMask : function(map) {
- this._map = map;
- if (!this._map) {
- return;
- }
- baidu.insertHTML(this._map.getContainer(), "beforeEnd", this._html);
- var elem = this._maskElement = this._map.getContainer().lastChild;
- var stopAndPrevent = function(e) {
- stopBubble(e);
- return baidu.preventDefault(e);
- }
- baidu.on(elem, 'mouseup', function(e) {
- if (e.button == 2) {
- stopAndPrevent(e);
- }
- });
- baidu.on(elem, 'contextmenu', stopAndPrevent);
- elem.style.display = 'none';
- },
- /**
- * 获取当前绘制点的地理坐标
- *
- * @param {Event} e e对象
- * @param {Boolean} n 是否向上查到相对于地图container元素的坐标位置
- * @return Point对象的位置信息
- */
- getDrawPoint : function(e, n) {
- e = global.event || e;
- var x = e.layerX || e.offsetX || 0;
- var y = e.layerY || e.offsetY || 0;
- var t = e.target || e.srcElement;
- if (t != OperationMask.getDom(this._map) && n == true) {
- while (t && t != this._map.getContainer()) {
- if (!(t.clientWidth == 0 &&
- t.clientHeight == 0 &&
- t.offsetParent &&
- t.offsetParent.nodeName.toLowerCase() == 'td')) {
- x += t.offsetLeft;
- y += t.offsetTop;
- }
- t = t.offsetParent;
- }
- }
- if (t != OperationMask.getDom(this._map) &&
- t != this._map.getContainer()) {
- return;
- }
- if (typeof x === 'undefined' ||
- typeof y === 'undefined') {
- return;
- }
- if (isNaN(x) || isNaN(y)) {
- return;
- }
- return this._map.pixelToPoint(new BMap.Pixel(x, y));
- },
- /**
- * 透明覆盖层的隐藏
- *
- * @return 无返回值
- */
- hide : function() {
- if (!this._map) {
- return;
- }
- this._inUse = false;
- if (this._maskElement) {
- this._maskElement.style.display = 'none';
- }
- },
- /**
- * 获取HTML容器
- *
- * @param {Map} map map对象
- * @return HTML容器元素
- */
- getDom : function(map) {
- if (!this._maskElement) {
- this._createMask(map);
- }
- return this._maskElement;
- },
- /**
- * 设置鼠标样式
- *
- * @type {String} cursor 鼠标样式
- * @return 无返回值
- */
- _setCursor : function(cursor) {
- this._cursor = cursor || 'default';
- if (this._maskElement) {
- this._maskElement.style.cursor = this._cursor;
- }
- }
- };
- /**
- * map对象
- * @private
- * @type {Map}
- */
- this._map = map;
- opts = opts || {};
- /**
- * _opts是默认参数赋值。
- * 下面通过用户输入的opts,对默认参数赋值
- * @private
- * @type {Json}
- */
- this._opts = baidu.extend(
- baidu.extend(this._opts || {}, {
- /**
- * 测距提示
- * @private
- * @type {String}
- */
- tips : "测距",
- /**
- * 测距过程中,提示框文字
- * @private
- * @type {String}
- */
- followText : "单击确定地点,双击结束",
- /**
- * 测距结果所用的单位制,可接受的属性为"metric"表示米制和"us"表示美国传统单位
- * @private
- * @type {String}
- */
- unit : "metric",
- /**
- * 折线颜色
- * @private
- * @type {String}
- */
- lineColor : "#ff6319",
- /**
- * 折线线宽
- * @private
- * @type {Number}
- */
- lineStroke : 2,
- /**
- * 折线透明度
- * @private
- * @type {Number}
- */
- opacity : 0.8,
- /**
- * 折线样式
- * @private
- * @type {String}
- */
- lineStyle : "solid",
- /**
- * 跟随鼠标样式
- * @private
- * @type {String}
- */
- cursor : "http://api.map.baidu.com/images/ruler.cur",
- /**
- * 转折点的ICON样式
- * @private
- * @type {BMap.Icon}
- */
- secIcon : null,
-
- /**
- * 转折点的ICON样式
- * @private
- * @type {BMap.Icon}
- */
- closeIcon : null
- })
- , opts);
- /**
- * 跟随的title覆盖物
- * @private
- * @type {BMap.Label}
- */
- this._followTitle = null;
- /**
- * 折线包含所有点的数组
- * @private
- * @type {Array}
- */
- this._points = [];
- /**
- * 折线所包含的所有path数组
- * @private
- * @type {Array}
- */
- this._paths = [];
- /**
- * 折线结点图片数组
- * @private
- * @type {Array}
- */
- this._dots = [];
- /**
- * 折线测距包含所有线段的距离
- * @private
- * @type {Array}
- */
- this._segDistance = [];
- /**
- * 覆盖物的数组
- * @private
- * @type {Array}
- */
- this._overlays = [];
- /**
- * 是否在调用map.clearOverlays清除画线需要建立的相关overlay元素
- * @private
- * @type {Boolean}
- */
- this._enableMassClear = true,
-
- /**
- * 单位制,存储语言包中定义的单位名称
- * @private
- * @type {Json}
- */
- this._units = {
- // metric 表示米制
- metric : {
- /**
- * 米制的名称
- * @type {String}
- */
- name : "metric",
- /**
- * 和米制的换算关系
- * @type {Number}
- */
- conv : 1,
- /**
- * 米制单位下两个单位制之间的换算关系
- * @type {Number}
- */
- incon : 1000,
- /**
- * 米制单位下较小单位
- * @type {String}
- */
- u1 : "米",
- /**
- * 米制单位下较大单位
- * @type {String}
- */
- u2 : "公里"
- },
- // us 表示美国传统单位,各参数意义同上metric
- us : {
- name : "us",
- conv : 3.2808,
- incon : 5279.856,
- u1 : "英尺",
- u2 : "英里"
- }
- };
- /**
- * 是否已经开启了测距状态
- * @private
- * @type {Boolean}
- */
- this._isOpen = false;
- /**
- * 未点击任何一点时,鼠标移动时的跟随提示文字
- * @private
- * @type {String}
- */
- this._startFollowText = "单击确定起点";
- /**
- * 地图移动的计时器
- * @private
- * @type {Object}
- */
- this._movingTimerId = null;
- /**
- * 测距需要添加的CSS样式
- * @private
- * @type {Json}
- */
- this._styles = {
- "BMapLib_diso" : "height:17px;width:5px;position:absolute;background:url(http://api.map.baidu.com/images/dis_box_01.gif) no-repeat left top"
- ,"BMapLib_disi" : "color:#7a7a7a;position:absolute;left:5px;padding:0 4px 1px 0;line-height:17px;background:url(http://api.map.baidu.com/images/dis_box_01.gif) no-repeat right top"
- ,"BMapLib_disBoxDis" : "color:#ff6319;font-weight:bold"
- };
- if (this._opts.lineStroke <= 0) {
- this._opts.lineStroke = 2;
- }
- if (this._opts.opacity > 1) {
- this._opts.opacity = 1;
- } else if (this._opts.opacity < 0) {
- this._opts.opacity = 0;
- }
- if (this._opts.lineStyle != "solid" &&
- this._opts.lineStyle != "dashed") {
- this._opts.lineStyle = "solid";
- }
- if (!this._units[this._opts.unit]) {
- this._opts.unit = "metric";
- }
-
- this.text = "测距";
- }
-
- // 通过baidu.lang下的inherits方法,让DistanceTool继承baidu.lang.Class
- baidu.lang.inherits(DistanceTool, baidu.lang.Class, "DistanceTool");
- /**
- * 地图区域的移动事件绑定
- * @return 无返回值
- */
- DistanceTool.prototype._bind = function(){
- // 设置鼠标样式
- this._setCursor(this._opts.cursor);
- var me = this;
- var OperationMask = this.OperationMask;
- // 在装载地图的页面元素上,绑定鼠标移动事件
- baidu.on(this._map.getContainer(), "mousemove", function(e){
- if (!me._isOpen) {
- return;
- }
- if (!me._followTitle) {
- return;
- }
- e = global.event || e;
- var t = e.target || e.srcElement;
- // 如果触发该事件的页面元素不是遮盖效果层,则返回,无操作
- if (t != OperationMask.getDom(me._map)) {
- me._followTitle.hide();
- return;
- }
- if (!me._mapMoving) {
- me._followTitle.show();
- }
- // 设置鼠标移动过程中,跟随的文字提示框的位置
- var pt = OperationMask.getDrawPoint(e, true);
- me._followTitle.setPosition(pt);
- });
- // 创建鼠标跟随的文字提示框
- if (this._startFollowText) {
- var t = this._followTitle = new BMap.Label(this._startFollowText, {offset : new BMap.Size(14, 16)});
- this._followTitle.setStyles({color : "#333", borderColor : "#ff0103"});
- }
- };
- /**
- * 开启地图的测距状态
- * @return {Boolean},开启测距状态成功,返回true;否则返回false。
- *
- * @example <b>参考示例:</b><br />
- * myDistanceToolObject.open();
- */
- DistanceTool.prototype.open = function(){
- var OperationMask = this.OperationMask;
- // 判断测距状态是否已经开启
- if (this._isOpen == true){
- return true;
- }
- // 已有其他地图上的鼠标操作工具开启
- if (DistanceTool._toolInUse) {
- return;
- } else {
- this._isOpen = true;
- DistanceTool._toolInUse = true;
- }
- // 判断是否是否在移动过程中
- if (this._mapMoving){
- delete this._mapMoving;
- }
- var me = this;
- // 增加鼠标在地图区域移动的事件
- // 通过binded参数,避免多次绑定
- if (!this._binded) {
- this._binded = true;
- // 绑定控件项事件
- this._bind();
- // 地图的移动过程中,需要隐藏相关的提示框
- this._map.addEventListener("moving", function(){
- me._hideCurrent();
- });
- }
- // 将文字提示框作为BMap.Label元素,提交给Map Api进行管理
- if (this._followTitle) {
- this._map.addOverlay(this._followTitle);
- this._followTitle.hide();
- }
- /**
- * 测距过程中,点击地图时,触发的操作
- * @ignore
- * @param {Object} e event对象
- */
- var distClick = function(e) {
- var map = me._map;
- if (!me._isOpen) {
- return;
- }
- // 通过event对象,计算得出点击位置的物理坐标,poi为一个BMap.Point对象
- e = global.event || e;
- var poi = OperationMask.getDrawPoint(e, true);
- // 验证计算得出的该点的位置合理性
- if (!me._isPointValid(poi)) {
- return;
- }
- // 记录当前点的屏幕位置
- me._bind.initX = e.pageX || e.clientX || 0;
- me._bind.initY = e.pageY || e.clientY || 0;
- // 这个if循环内的计算是,判断当前这个点,与存储内的最后一个点的距离,
- // 如果距离过小,比如小于5,可以认为是用户的误点,可以忽略掉
- if (me._points.length > 0){
- var lstPx = map.pointToPixel(me._points[me._points.length - 1]);
- var thisPx = map.pointToPixel(poi);
- var dis = Math.sqrt(Math.pow(lstPx.x - thisPx.x, 2) + Math.pow(lstPx.y - thisPx.y, 2));
- if (dis < 5) {
- return;
- }
- }
- me._bind.x = e.layerX || e.offsetX || 0;
- me._bind.y = e.layerY || e.offsetY || 0;
- me._points.push(poi);
- // 添加测距结点
- me._addSecPoint(poi);
- // 调整跟踪鼠标的标签
- if (me._paths.length == 0) {
- me._formatTitle(1, me._opts.followText, me._getTotalDistance());
- }
- // 修改确定线的颜色
- if (me._paths.length > 0) {
- me._paths[me._paths.length - 1].show();
- me._paths[me._paths.length - 1].setStrokeOpacity(me._opts.opacity);
- }
- var path = new BMap.Polyline([poi, poi], {enableMassClear : me._enableMassClear});
- me._map.addOverlay(path);
- me._paths.push(path);
- me._overlays.push(path);
- // 测距模式下线样式固定
- path.setStrokeWeight(me._opts.lineStroke);
- path.setStrokeColor(me._opts.lineColor);
- path.setStrokeOpacity(me._opts.opacity / 2);
- path.setStrokeStyle(me._opts.lineStyle);
- // 如果地图正在移动则隐藏掉
- if (me._mapMoving){
- path.hide();
- }
- if (me._points.length > 1) {
- var siblingPath = me._paths[me._points.length - 2];
- siblingPath.setPositionAt(1, poi);
- }
- // 生成节点旁边的距离显示框
- var disText = "";
- if (me._points.length > 1) {
- // 非起点的节点,显示当前的距离
- var segDis = me._setSegDistance(me._points[me._points.length - 2], me._points[me._points.length - 1]);
- var meters = me._getTotalDistance();
- disText = me._formatDisStr(meters);
- } else {
- disText = "起点";
- }
- var disLabel = new BMap.Label(disText, {offset : new BMap.Size(10, -5), enableMassClear : me._enableMassClear});
- disLabel.setStyles({color : "#333", borderColor : "#ff0103"});
- me._map.addOverlay(disLabel);
- me._formatSegLabel(disLabel, disText);
- me._overlays.push(disLabel);
- poi.disLabel = disLabel;
- disLabel.setPosition(poi);
- /**
- * 测距过程中,每次点击底图添加节点时,派发事件的接口
- * @name DistanceTool#onaddpoint
- * @event
- * @param {Event Object} e 回调函数会返回event参数,包括以下返回值:
- * <br />{"<b>point</b> : {BMap.Point} 最新添加上的节点BMap.Point对象,
- * <br />"<b>pixel</b>:{BMap.pixel} 最新添加上的节点BMap.Pixel对象,
- * <br />"<b>index</b>:{Number} 最新添加的节点的索引,
- * <br />"<b>distance</b>:{Number} 截止最新添加的节点的总距离}
- *
- * @example <b>参考示例:</b><br />
- * myDistanceToolObject.addEventListener("addpoint", function(e) { alert(e.distance); });
- */
- // 生成名为onaddpoint的baidu.lang.Event对象
- // 并给该event对象添加上point、pixel、index和distance等属性字段
- // 然后在此刻,将绑定在onaddpoint上事件,全部赋予event参数,然后派发出去
- var event = new baidu.lang.Event("onaddpoint");
- event.point = poi;
- event.pixel = me._map.pointToPixel(poi);
- event.index = me._points.length - 1;
- event.distance = me._getTotalDistance().toFixed(0);
- me.dispatchEvent(event);
- };
- /**
- * 测距过程中,鼠标在地图上移动时,触发的操作
- * @ignore
- * @param {Object} e event对象
- */
- var distMove = function(e) {
- if (!me._isOpen){
- return;
- }
- // 通过判断数组me._paths的长度,判断当前是否已经有测量节点
- // 也就是,如果没有节点,则还没有开始测量
- if (me._paths.length > 0) {
- // 通过event参数,计算当前点的位置
- e = global.event || e;
- var curX = e.pageX || e.clientX || 0;
- var curY = e.pageY || e.clientY || 0;
- if (typeof me._bind.initX == "undefined") {
- me._bind.x = e.layerX || e.offsetX || 0;
- me._bind.y = e.layerY || e.offsetY || 0;
- me._bind.initX = curX;
- me._bind.initY = curY;
- }
- var x = me._bind.x + curX - me._bind.initX;
- var y = me._bind.y + curY - me._bind.initY;
- // 修改最后一条折线的终点位置,使之随着鼠标移动画线
- var path = me._paths[me._paths.length - 1];
- var poi = me._map.pixelToPoint(new BMap.Pixel(x, y));
- path.setPositionAt(1, poi);
- if (!me._mapMoving) {
- path.show();
- }
- var dx = 0;
- var dy = 0;
- // 计算当前鼠标位置,是否靠近边界、或者已经出了边界
- // 如果在边界位置,则需要向对应的方向移动地图,来进行测量
- // 每次移动的距离,设定为8
- if (x < 10) {
- dx = 8;
- } else if (x > me._map.getSize().width - 10){
- dx = -8;
- }
- if (y < 10) {
- dy = 8;
- } else if (y > me._map.getSize().height - 10){
- dy = -8;
- }
- // 如果dx和dy都等于0,表明不需要移动地图
- if (dx != 0 || dy != 0){
- // 此时需要向一个方向,平移地图
- if (!distMove._movingTimerId){
- me._mapMoving = true;
- me._map.panBy(dx, dy, {noAnimation : true});
- me._movingTimerId = distMove._movingTimerId = setInterval(function(){
- me._map.panBy(dx, dy, {noAnimation : true});
- }, 30);
- // 地图移动过程中,隐藏线段和标签
- path.hide();
- me._followTitle && me._followTitle.hide();
- }
- } else {
- if (distMove._movingTimerId) {
- // 此时用户不在需要移动地图来测量,可以清除计时器
- clearInterval(distMove._movingTimerId);
- delete distMove._movingTimerId;
- delete me._movingTimerId;
- // 显示跟随提示框,并修改线路位置
- var lstP = me._paths[me._paths.length - 1];
- var poiN = me._map.pixelToPoint(new BMap.Pixel(x, y));
- if (!lstP) {
- return;
- }
- lstP.setPositionAt(1, poiN);
- lstP.show();
- if (me._followTitle) {
- me._followTitle.setPosition(poiN);
- me._followTitle.show();
- }
- me._bind.i = 0;
- me._bind.j = 0;
- delete me._mapMoving;
- }
- }
- // 实时更新文字提示框中的距离
- if (me._followTitle) {
- var td = me._getTotalDistance();
- var dis = me._map.getDistance(me._points[me._points.length - 1], poi);
- me._updateInstDis(me._followTitle, td + dis);
- }
- } else {
- // 此时用户还没有开始测量,只是鼠标随便在地图上移动
- if (me._followTitle) {
- me._followTitle.show();
- e = global.event || e;
- var t = e.target || e.srcElement;
- if (t != OperationMask.getDom()) {
- me._followTitle.hide();
- }
- }
- }
- };
- /**
- * 测距要结束时,双击地图,触发的操作
- * @ignore
- * @param {Object} e event对象
- */
- var distDblclick = function(e) {
- if (!me._isOpen) {
- return;
- }
- // 结束时,删除绑定的事件
- baidu.un(OperationMask.getDom(me._map), "click", distClick);
- baidu.un(document, "mousemove", distMove);
- baidu.un(OperationMask.getDom(me._map), "dblclick", distDblclick);
- baidu.un(document, "keydown", distKeyDown);
- baidu.un(OperationMask.getDom(me._map), "mouseup", distMouseUp);
- // 调用close()关闭测距状态
- setTimeout(function(){
- me.close();
- }, 50);
- };
-
- /**
- * 测距时的键盘操作
- * @ignore
- * @param {Object} e event对象
- */
- var distKeyDown = function(e){
- e = global.event || e;
- if (e.keyCode == 27){
- // [ESC]退出本次测距
- me._clearCurData();
- setTimeout(function(){
- me.close();
- }, 50);
- }
- };
- /**
- * 测距过程中,鼠标弹起时,触发的操作
- * @ignore
- * @param {Object} e event对象
- */
- var distMouseUp = function(e) {
- e = global.event || e;
- var ieVersion = 0;
- if (/msie (\d+\.\d)/i.test(navigator.userAgent)) {
- ieVersion = document.documentMode || + RegExp['\x241'];
- }
- if (ieVersion &&
- e.button != 1 ||
- e.button == 2){
- me.close();
- }
- };
- // 初始化存储数据
- me._initData();
- // 调整title的内容
- this._formatTitle();
- // 创建透明覆盖层,并设置鼠标样式
- OperationMask.show(this._map);
- this._setCursor(this._opts.cursor);
- // 绑定全部事件
- baidu.on(OperationMask.getDom(this._map), "click", distClick);
- baidu.on(document, "mousemove", distMove);
- baidu.on(OperationMask.getDom(this._map), "dblclick", distDblclick);
- baidu.on(document, "keydown", distKeyDown);
- baidu.on(OperationMask.getDom(this._map), "mouseup", distMouseUp);
-
- // 将绑定的事件、和对应的绑定对象,记录在数组中
- this.bindFunc = [
- {elem : OperationMask.getDom(this._map), type : "click", func : distClick},
- {elem : OperationMask.getDom(this._map), type : "dblclick", func : distDblclick},
- {elem : document, type : "mousemove", func : distMove},
- {elem : document, type : "keydown", func : distKeyDown},
- {elem : OperationMask.getDom(this._map), type : "mouseup", func : distMouseUp}];
- return true;
- };
- /**
- * 画线结束时,派发drawend事件
- * @return 无返回值
- */
- DistanceTool.prototype._dispatchLastEvent = function() {
- /**
- * 测距时,每次双击底图结束当前测距折线时,派发事件的接口
- * @name DistanceTool#ondrawend
- * @event
- * @param {Event Object} e 回调函数会返回event参数,包括以下返回值:
- * <br />{"<b>points</b> : {BMap.Point} 所有测量时,打下的节点BMap.Point对象,
- * <br />"<b>overlays</b>:{Array} 所有测量时,生成的线段BMap.Overlay对象,
- * <br />"<b>distance</b>:{Number} 测量解释时的最终距离}
- *
- * @example <b>参考示例:</b><br />
- * myDistanceToolObject.addEventListener("drawend", function(e) { alert(e.distance); });
- */
- // 生成名为ondrawend的baidu.lang.Event对象
- // 并给该event对象添加上points、overlays和distance等属性字段
- // 然后在此刻,将绑定在ondrawend上事件,全部赋予event参数,然后派发出去
- var event = new baidu.lang.Event("ondrawend");
- event.points =
- this._points ?
- this._points.slice(0) :
- [];
- event.overlays =
- this._paths ?
- this._paths.slice(0, this._paths.length - 1) :
- [];
- event.distance = this._getTotalDistance().toFixed(0);
- this.dispatchEvent(event);
- };
- /**
- * 关闭测距状态
- * @return 无返回值
- *
- * @example <b>参考示例:</b><br />
- * myDistanceToolObject.close();
- */
- DistanceTool.prototype.close = function(){
- var OperationMask = this.OperationMask;
- if (this._isOpen == false){
- return;
- }
- this._isOpen = false;
- DistanceTool._toolInUse = false;
- if (this._mapMoving){
- delete this._mapMoving;
- }
- var me = this;
- me._dispatchLastEvent();
- if (me._points.length < 2){
- // 不是有效绘制,清除所有内容
- me._clearCurData();
- } else {
- me._paths[me._paths.length - 1].remove();
- me._paths[me._paths.length - 1] = null;
- me._paths.length = me._paths.length - 1;
- // 移除最近一次标记
- var pt = me._points[me._points.length - 1];
- if (pt.disLabel){
- pt.disLabel.remove();
- }
- me._processLastOp();
- }
- OperationMask.hide();
- // 删除绑定的事件
- for (var i = 0, l = this.bindFunc.length; i < l; i ++){
- baidu.un(this.bindFunc[i].elem, this.bindFunc[i].type, this.bindFunc[i].func);
- }
- // 停止地图移动
- if (me._movingTimerId){
- clearInterval(me._movingTimerId);
- me._movingTimerId = null;
- }
- if (this._followTitle){
- this._followTitle.hide();
- }
- };
- /**
- * 清除本次测距的暂存数据
- * @return 无返回值
- */
- DistanceTool.prototype._clearCurData = function(){
- var OperationMask = this.OperationMask;
- for (var i = 0, l = this._points.length; i < l; i ++){
- if (this._points[i].disLabel){
- this._points[i].disLabel.remove();
- }
- }
- for (var i = 0, l = this._paths.length; i < l; i ++){
- this._paths[i].remove();
- }
- for (var i = 0, l = this._dots.length; i < l; i ++){
- this._dots[i].remove();
- }
- this._initData();
- };
- /**
- * 初始化存储数组
- * @return 无返回值
- */
- DistanceTool.prototype._initData = function(){
- // 初始化point数组
- this._points.length = 0;
- // 初始化path数组
- this._paths.length = 0;
- // 初始化分段距离数组
- this._segDistance.length = 0;
- // 初始化结点图像数组
- this._dots.length = 0;
- };
- /**
- * 计算两点之间距离并存放在分段距离数组中
- * @param {Point}
- * @param {Point}
- * @return {Number} 两个地理点之间的距离
- */
- DistanceTool.prototype._setSegDistance = function(pt0, pt1){
- if (!pt0 || !pt1){
- return;
- }
- var dis = this._map.getDistance(pt0, pt1);
- this._segDistance.push(dis);
- return dis;
- };
- /**
- * 获得总距离
- * @return {Number} 总距离
- */
- DistanceTool.prototype._getTotalDistance = function(){
- var totalDis = 0;
- for (var i = 0, l = this._segDistance.length; i < l; i ++){
- totalDis += this._segDistance[i];
- }
- return totalDis;
- };
- /**
- * 将米制单位的数值换算成为目标单位下的数值
- * @type {Number} 需要转换的数值
- * @type {String} 字符串描述的目标单位,
- * "metric" 表示米制单位,
- * "us" 表示美国传统单位制
- * @return {Number} 转换后的数值
- */
- DistanceTool.prototype._convertUnit = function(num, unit){
- unit = unit || "metric";
- if (this._units[unit]){
- return num * this._units[unit].conv;
- }
- return num;
- };
- /**
- * 添加测距结点
- * @param {BMap.Point} 节点
- * @return 无返回值
- */
- DistanceTool.prototype._addSecPoint = function(pt){
- var ico =
- this._opts.secIcon ?
- this._opts.secIcon :
- new BMap.Icon("http://api.map.baidu.com/images/mapctrls.png", new BMap.Size(11, 11), {imageOffset: new BMap.Size(-26, -313)});
- var secPt = new BMap.Marker(pt, {
- icon : ico,
- clickable : false,
- baseZIndex : 3500000,
- zIndexFixed : true,
- enableMassClear : this._enableMassClear
- });
- this._map.addOverlay(secPt);
- this._dots.push(secPt);
- };
- /**
- * 格式化距离字符串
- * @param {Number} 距离
- * @return {String} 格式化的字符串
- */
- DistanceTool.prototype._formatDisStr = function(distance){
- var u = this._opts.unit;
- var unit = this._units[u].u1;
- var dis = this._convertUnit(distance, u);
- if (dis > this._units[u].incon){
- dis = dis / this._units[u].incon;
- unit = this._units[u].u2;
- dis = dis.toFixed(1);
- } else {
- dis = dis.toFixed(0);
- }
- return dis + unit;
- };
- /**
- * 设置鼠标样式
- * @param {String} cursor 鼠标样式
- * @return 没有返回值
- */
- DistanceTool.prototype._setCursor = function(cursor){
- var OperationMask = this.OperationMask;
- // 由于webkit内核浏览器下,cursor设置后默认不会居中,所以需要对偏移值进行设置
- var csr =
- /webkit/.test(navigator.userAgent.toLowerCase()) ?
- "url(" + this._opts.cursor + ") 3 6, crosshair" :
- "url(" + this._opts.cursor + "), crosshair"
- OperationMask._setCursor(csr);
- };
- /**
- * 获取鼠标样式
- * @return {String} 跟随的鼠标样式
- */
- DistanceTool.prototype._getCursor = function(){
- return this._opts.cursor;
- };
- /**
- * 调整分段距离样式
- * @param {BMap.Label} label 提示框的Label
- * @param {String} 需要填入的文字
- * @return 没有返回值
- */
- DistanceTool.prototype._formatSegLabel = function(label, text){
- label.setStyle({"border" : "none", "padding" : "0"});
- label.setContent("<span style='" + this._styles.BMapLib_diso + "'><span style='" + this._styles.BMapLib_disi + "'>" + text + "</span></span>");
- };
- /**
- * 处理最后一次操作,当用户双击或测距被强行退出时调用
- * @return 没有返回值
- */
- DistanceTool.prototype._processLastOp = function() {
- var me = this;
- // 删除上次移动临时数据
- delete me._bind.x;
- delete me._bind.y;
- delete me._bind.initX;
- delete me._bind.initY;
- // 验证路径
- if (me._paths.length > me._points.length - 1){
- var l = me._paths.length - 1;
- me._paths[l].remove();
- me._paths[l] = null;
- me._paths.length = l;
- }
- // 保存本次测距对象
- var disObj = {};
- disObj.points = me._points.slice(0);
- disObj.paths = me._paths.slice(0);
- disObj.dots = me._dots.slice(0);
- disObj.segDis = me._segDistance.slice(0);
- // 判断总距离和按钮位置
- var lstPx = me._map.pointToPixel(disObj.points[disObj.points.length - 1]);
- var prePx = me._map.pointToPixel(disObj.points[disObj.points.length - 2]);
- var btnOffset = [0, 0];
- var disOffset = [0, 0];
- if (lstPx.y - prePx.y >= 0){
- // 距离位于下端
- disOffset = [-5, 11];
- } else {
- // 距离位于上端
- disOffset = [-5, -35];
- }
- if (lstPx.x - prePx.x >= 0){
- // 按钮位于右侧
- btnOffset = [14, 0];
- } else {
- // 按钮位于左侧
- btnOffset = [-14, 0];
- }
- // 显示总距离
- var pt = disObj.points[disObj.points.length - 1];
- pt.disLabel = new BMap.Label("", {offset: new BMap.Size(-15, -40), enableMassClear: me._enableMassClear});
- pt.disLabel.setStyles({color: "#333", borderColor: "#ff0103"});
- me._map.addOverlay(pt.disLabel);
- pt.disLabel.setOffset(new BMap.Size(disOffset[0], disOffset[1]));
- pt.disLabel.setPosition(pt);
- me._formatTitle(2, "", "", pt.disLabel);
- // 添加关闭按钮
- var bico =
- this._opts.closeIcon ?
- this._opts.closeIcon :
- new BMap.Icon("http://api.map.baidu.com/images/mapctrls.gif", new BMap.Size(12, 12), {imageOffset: new BMap.Size(0, -14)});
- disObj.closeBtn = new BMap.Marker(disObj.points[disObj.points.length - 1],
- {icon : bico,
- offset : new BMap.Size(btnOffset[0], btnOffset[1]),
- baseZIndex : 3600000,
- enableMassClear : me._enableMassClear}
- );
- me._map.addOverlay(disObj.closeBtn);
- disObj.closeBtn.setTitle("清除本次测距");
- // 点击关闭按钮,绑定关闭按钮事件
- disObj.closeBtn.addEventListener("click", function(e){
- // 关闭本次测距,清除相关存储和变量
- for (var i = 0, l = disObj.points.length; i < l; i ++){
- disObj.points[i].disLabel.remove();
- disObj.points[i].disLabel = null;
- }
- for (var i = 0, l = disObj.paths.length; i < l; i ++){
- disObj.paths[i].remove();
- disObj.paths[i] = null;
- }
- for (var i = 0, l = disObj.dots.length; i < l; i ++){
- disObj.dots[i].remove();
- disObj.dots[i] = null;
- }
- disObj.closeBtn.remove();
- disObj.closeBtn = null;
- stopBubble(e);
-
- /**
- * @ignore
- * 测距结束后,点击线段上最后一个节点旁的关闭按钮时,派发事件的接口
- * @name DistanceTool#onremovepolyline
- * @event
- * @param {Event Object} e 回调函数会返回event参数
- *
- * @example <b>参考示例:</b><br />
- * myDistanceToolObject.addEventListener("removepolyline", function(e) { alert(e.type); });
- */
- // 生成名为onremovepolyline的baidu.lang.Event对象
- // 然后在此刻,将绑定在onremovepolyline上事件,全部赋予event参数,然后派发出去
- var event = new baidu.lang.Event("onremovepolyline");
- me.dispatchEvent(event);
- });
- me._initData();
- };
- /**
- * 生成测距过程中的文字提示框
- * @param {String} type
- * @param {String} text
- * @param {String} distance
- * @param {Label} label
- * @return 无返回值
- */
- DistanceTool.prototype._formatTitle = function(type, text, distance, label){
- var title = label || this._followTitle;
- if (!title){
- return;
- }
- title.setStyle({"lineHeight" : "16px", "zIndex" : "85", "padding" : "3px 5px"});
- var t = this._startFollowText || "";
- var htmls = [];
- if (type == 1){
- // 测距过程中的提示
- title.setOffset(0, 25);
- var u = this._opts.unit;
- var unit = this._units[u].u1;
- var dis = this._convertUnit(distance, u);
- if (dis > this._units[u].incon){
- dis = dis / this._units[u].incon;
- unit = this._units[u].u2;
- dis = dis.toFixed(1);
- } else {
- dis = dis.toFixed(0);
- }
- htmls.push("<span>总长:<span style='" + this._styles.BMapLib_disBoxDis+"'>" + dis + "</span>" + unit + "</span><br />");
- htmls.push("<span style='color:#7a7a7a'>" + text + "</span>");
- } else if (type == 2) {
- // 结束时的总距离展示
- var u = this._opts.unit;
- var unit = this._units[u].u1;
- var dis = this._convertUnit(this._getTotalDistance(), u);
- if (dis > this._units[u].incon){
- dis = dis / this._units[u].incon;
- unit = this._units[u].u2;
- dis = dis.toFixed(1);
- } else{
- dis = dis.toFixed(0);
- }
- htmls.push("总长:<span style='" + this._styles.BMapLib_disBoxDis + "'>" + dis + "</span>" + unit);
- } else {
- title.setOffset(0, 25);
- htmls.push(t);
- }
- title.setContent(htmls.join(""));
- };
- /**
- * 更新label的距离
- * @param HTMLElement label的DOM元素
- * @param Number 距离
- */
- DistanceTool.prototype._updateInstDis = function(label, dis){
- // 换算距离
- var u = this._opts.unit;
- var unit = this._units[u].u1;
- if (dis > this._units[u].incon){
- dis = dis / this._units[u].incon;
- unit = this._units[u].u2;
- dis = dis.toFixed(1);
- } else {
- dis = dis.toFixed(0);
- }
- // 修改Label的内容
- if (label) {
- var htmls = [];
- htmls.push("<span>总长:<span style='" + this._styles.BMapLib_disBoxDis + "'>" + dis + "</span>" + unit + "</span><br />");
- htmls.push("<span style='color:#7a7a7a'>" + this._opts.followText + "</span>");
- label.setContent(htmls.join(""));
- }
- };
- /**
- * 隐藏相关的线段和提示框文字
- * @return 无返回值
- */
- DistanceTool.prototype._hideCurrent = function(){
- if (!this._isOpen){
- return;
- }
- if (this._paths.length > 0){
- var p = this._paths[this._paths.length - 1];
- p.hide();
- }
- this._followTitle && this._followTitle.hide();
- };
- /**
- * 验证传入点的位置合理性
- * @param {BMap.Point} pt 需要被验证的point点
- * @return 无返回值
- */
- DistanceTool.prototype._isPointValid = function(pt){
- if (!pt){
- return false;
- }
- var mapBounds = this._map.getBounds();
- var sw = mapBounds.getSouthWest(),
- ne = mapBounds.getNorthEast();
- if (pt.lng < sw.lng ||
- pt.lng > ne.lng ||
- pt.lat < sw.lat ||
- pt.lat > ne.lat) {
- return false;
- }
- return true;
- };
- /**
- * 停止事件冒泡传播,
- * 闭包,对外不暴露
- *
- * @type {Event} e e对象
- */
- function stopBubble(e){
- var e = global.event || e;
- e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true;
- };
- return DistanceTool;
- });
|