|
|
/**
|
|
|
* @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;
|
|
|
});
|