textIconOverlay.js 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054
  1. /**
  2. * @fileoverview 此类表示地图上的一个覆盖物,该覆盖物由文字和图标组成,从Overlay继承。
  3. * 主入口类是<a href="symbols/BMapLib.TextIconOverlay.html">TextIconOverlay</a>,
  4. * 基于Baidu Map API 1.2。
  5. *
  6. * @author Baidu Map Api Group
  7. * @version 1.2
  8. */
  9. /**
  10. * @namespace BMap的所有library类均放在BMapLib命名空间下
  11. */
  12. var BMapLib = window.BMapLib = BMapLib || {};
  13. (function () {
  14. /**
  15. * 声明baidu包
  16. */
  17. var T,
  18. baidu = T = baidu || {version: "1.3.8"};
  19. (function (){
  20. //提出guid,防止在与老版本Tangram混用时
  21. //在下一行错误的修改window[undefined]
  22. baidu.guid = "$BAIDU$";
  23. //Tangram可能被放在闭包中
  24. //一些页面级别唯一的属性,需要挂载在window[baidu.guid]上
  25. window[baidu.guid] = window[baidu.guid] || {};
  26. /**
  27. * @ignore
  28. * @namespace baidu.dom 操作dom的方法。
  29. */
  30. baidu.dom = baidu.dom || {};
  31. /**
  32. * 从文档中获取指定的DOM元素
  33. * @name baidu.dom.g
  34. * @function
  35. * @grammar baidu.dom.g(id)
  36. * @param {string|HTMLElement} id 元素的id或DOM元素
  37. * @shortcut g,T.G
  38. * @meta standard
  39. * @see baidu.dom.q
  40. *
  41. * @returns {HTMLElement|null} 获取的元素,查找不到时返回null,如果参数不合法,直接返回参数
  42. */
  43. baidu.dom.g = function (id) {
  44. if ('string' == typeof id || id instanceof String) {
  45. return document.getElementById(id);
  46. } else if (id && id.nodeName && (id.nodeType == 1 || id.nodeType == 9)) {
  47. return id;
  48. }
  49. return null;
  50. };
  51. // 声明快捷方法
  52. baidu.g = baidu.G = baidu.dom.g;
  53. /**
  54. * 获取目标元素所属的document对象
  55. * @name baidu.dom.getDocument
  56. * @function
  57. * @grammar baidu.dom.getDocument(element)
  58. * @param {HTMLElement|string} element 目标元素或目标元素的id
  59. * @meta standard
  60. * @see baidu.dom.getWindow
  61. *
  62. * @returns {HTMLDocument} 目标元素所属的document对象
  63. */
  64. baidu.dom.getDocument = function (element) {
  65. element = baidu.dom.g(element);
  66. return element.nodeType == 9 ? element : element.ownerDocument || element.document;
  67. };
  68. /**
  69. * @ignore
  70. * @namespace baidu.lang 对语言层面的封装,包括类型判断、模块扩展、继承基类以及对象自定义事件的支持。
  71. */
  72. baidu.lang = baidu.lang || {};
  73. /**
  74. * 判断目标参数是否string类型或String对象
  75. * @name baidu.lang.isString
  76. * @function
  77. * @grammar baidu.lang.isString(source)
  78. * @param {Any} source 目标参数
  79. * @shortcut isString
  80. * @meta standard
  81. * @see baidu.lang.isObject,baidu.lang.isNumber,baidu.lang.isArray,baidu.lang.isElement,baidu.lang.isBoolean,baidu.lang.isDate
  82. *
  83. * @returns {boolean} 类型判断结果
  84. */
  85. baidu.lang.isString = function (source) {
  86. return '[object String]' == Object.prototype.toString.call(source);
  87. };
  88. // 声明快捷方法
  89. baidu.isString = baidu.lang.isString;
  90. /**
  91. * 从文档中获取指定的DOM元素
  92. * **内部方法**
  93. *
  94. * @param {string|HTMLElement} id 元素的id或DOM元素
  95. * @meta standard
  96. * @return {HTMLElement} DOM元素,如果不存在,返回null,如果参数不合法,直接返回参数
  97. */
  98. baidu.dom._g = function (id) {
  99. if (baidu.lang.isString(id)) {
  100. return document.getElementById(id);
  101. }
  102. return id;
  103. };
  104. // 声明快捷方法
  105. baidu._g = baidu.dom._g;
  106. /**
  107. * @ignore
  108. * @namespace baidu.browser 判断浏览器类型和特性的属性。
  109. */
  110. baidu.browser = baidu.browser || {};
  111. if (/msie (\d+\.\d)/i.test(navigator.userAgent)) {
  112. //IE 8下,以documentMode为准
  113. //在百度模板中,可能会有$,防止冲突,将$1 写成 \x241
  114. /**
  115. * 判断是否为ie浏览器
  116. * @property ie ie版本号
  117. * @grammar baidu.browser.ie
  118. * @meta standard
  119. * @shortcut ie
  120. * @see baidu.browser.firefox,baidu.browser.safari,baidu.browser.opera,baidu.browser.chrome,baidu.browser.maxthon
  121. */
  122. baidu.browser.ie = baidu.ie = document.documentMode || + RegExp['\x241'];
  123. }
  124. /**
  125. * 获取目标元素的computed style值。如果元素的样式值不能被浏览器计算,则会返回空字符串(IE)
  126. *
  127. * @author berg
  128. * @name baidu.dom.getComputedStyle
  129. * @function
  130. * @grammar baidu.dom.getComputedStyle(element, key)
  131. * @param {HTMLElement|string} element 目标元素或目标元素的id
  132. * @param {string} key 要获取的样式名
  133. *
  134. * @see baidu.dom.getStyle
  135. *
  136. * @returns {string} 目标元素的computed style值
  137. */
  138. baidu.dom.getComputedStyle = function(element, key){
  139. element = baidu.dom._g(element);
  140. var doc = baidu.dom.getDocument(element),
  141. styles;
  142. if (doc.defaultView && doc.defaultView.getComputedStyle) {
  143. styles = doc.defaultView.getComputedStyle(element, null);
  144. if (styles) {
  145. return styles[key] || styles.getPropertyValue(key);
  146. }
  147. }
  148. return '';
  149. };
  150. /**
  151. * 提供给setStyle与getStyle使用
  152. */
  153. baidu.dom._styleFixer = baidu.dom._styleFixer || {};
  154. /**
  155. * 提供给setStyle与getStyle使用
  156. */
  157. baidu.dom._styleFilter = baidu.dom._styleFilter || [];
  158. /**
  159. * 为获取和设置样式的过滤器
  160. * @private
  161. * @meta standard
  162. */
  163. baidu.dom._styleFilter.filter = function (key, value, method) {
  164. for (var i = 0, filters = baidu.dom._styleFilter, filter; filter = filters[i]; i++) {
  165. if (filter = filter[method]) {
  166. value = filter(key, value);
  167. }
  168. }
  169. return value;
  170. };
  171. /**
  172. * @ignore
  173. * @namespace baidu.string 操作字符串的方法。
  174. */
  175. baidu.string = baidu.string || {};
  176. /**
  177. * 将目标字符串进行驼峰化处理
  178. * @name baidu.string.toCamelCase
  179. * @function
  180. * @grammar baidu.string.toCamelCase(source)
  181. * @param {string} source 目标字符串
  182. * @remark
  183. * 支持单词以“-_”分隔
  184. * @meta standard
  185. *
  186. * @returns {string} 驼峰化处理后的字符串
  187. */
  188. baidu.string.toCamelCase = function (source) {
  189. //提前判断,提高getStyle等的效率 thanks xianwei
  190. if (source.indexOf('-') < 0 && source.indexOf('_') < 0) {
  191. return source;
  192. }
  193. return source.replace(/[-_][^-_]/g, function (match) {
  194. return match.charAt(1).toUpperCase();
  195. });
  196. };
  197. /**
  198. * 获取目标元素的样式值
  199. * @name baidu.dom.getStyle
  200. * @function
  201. * @grammar baidu.dom.getStyle(element, key)
  202. * @param {HTMLElement|string} element 目标元素或目标元素的id
  203. * @param {string} key 要获取的样式名
  204. * @remark
  205. *
  206. * 为了精简代码,本模块默认不对任何浏览器返回值进行归一化处理(如使用getStyle时,不同浏览器下可能返回rgb颜色或hex颜色),也不会修复浏览器的bug和差异性(如设置IE的float属性叫styleFloat,firefox则是cssFloat)。<br />
  207. * baidu.dom._styleFixer和baidu.dom._styleFilter可以为本模块提供支持。<br />
  208. * 其中_styleFilter能对颜色和px进行归一化处理,_styleFixer能对display,float,opacity,textOverflow的浏览器兼容性bug进行处理。
  209. * @shortcut getStyle
  210. * @meta standard
  211. * @see baidu.dom.setStyle,baidu.dom.setStyles, baidu.dom.getComputedStyle
  212. *
  213. * @returns {string} 目标元素的样式值
  214. */
  215. baidu.dom.getStyle = function (element, key) {
  216. var dom = baidu.dom;
  217. element = dom.g(element);
  218. key = baidu.string.toCamelCase(key);
  219. //computed style, then cascaded style, then explicitly set style.
  220. var value = element.style[key] ||
  221. (element.currentStyle ? element.currentStyle[key] : "") ||
  222. dom.getComputedStyle(element, key);
  223. // 在取不到值的时候,用fixer进行修正
  224. if (!value) {
  225. var fixer = dom._styleFixer[key];
  226. if(fixer){
  227. value = fixer.get ? fixer.get(element) : baidu.dom.getStyle(element, fixer);
  228. }
  229. }
  230. /* 检查结果过滤器 */
  231. if (fixer = dom._styleFilter) {
  232. value = fixer.filter(key, value, 'get');
  233. }
  234. return value;
  235. };
  236. // 声明快捷方法
  237. baidu.getStyle = baidu.dom.getStyle;
  238. if (/opera\/(\d+\.\d)/i.test(navigator.userAgent)) {
  239. /**
  240. * 判断是否为opera浏览器
  241. * @property opera opera版本号
  242. * @grammar baidu.browser.opera
  243. * @meta standard
  244. * @see baidu.browser.ie,baidu.browser.firefox,baidu.browser.safari,baidu.browser.chrome
  245. */
  246. baidu.browser.opera = + RegExp['\x241'];
  247. }
  248. /**
  249. * 判断是否为webkit内核
  250. * @property isWebkit
  251. * @grammar baidu.browser.isWebkit
  252. * @meta standard
  253. * @see baidu.browser.isGecko
  254. */
  255. baidu.browser.isWebkit = /webkit/i.test(navigator.userAgent);
  256. /**
  257. * 判断是否为gecko内核
  258. * @property isGecko
  259. * @grammar baidu.browser.isGecko
  260. * @meta standard
  261. * @see baidu.browser.isWebkit
  262. */
  263. baidu.browser.isGecko = /gecko/i.test(navigator.userAgent) && !/like gecko/i.test(navigator.userAgent);
  264. /**
  265. * 判断是否严格标准的渲染模式
  266. * @property isStrict
  267. * @grammar baidu.browser.isStrict
  268. * @meta standard
  269. */
  270. baidu.browser.isStrict = document.compatMode == "CSS1Compat";
  271. /**
  272. * 获取目标元素相对于整个文档左上角的位置
  273. * @name baidu.dom.getPosition
  274. * @function
  275. * @grammar baidu.dom.getPosition(element)
  276. * @param {HTMLElement|string} element 目标元素或目标元素的id
  277. * @meta standard
  278. *
  279. * @returns {Object} 目标元素的位置,键值为top和left的Object。
  280. */
  281. baidu.dom.getPosition = function (element) {
  282. element = baidu.dom.g(element);
  283. var doc = baidu.dom.getDocument(element),
  284. browser = baidu.browser,
  285. getStyle = baidu.dom.getStyle,
  286. // Gecko 1.9版本以下用getBoxObjectFor计算位置
  287. // 但是某些情况下是有bug的
  288. // 对于这些有bug的情况
  289. // 使用递归查找的方式
  290. BUGGY_GECKO_BOX_OBJECT = browser.isGecko > 0 &&
  291. doc.getBoxObjectFor &&
  292. getStyle(element, 'position') == 'absolute' &&
  293. (element.style.top === '' || element.style.left === ''),
  294. pos = {"left":0,"top":0},
  295. viewport = (browser.ie && !browser.isStrict) ? doc.body : doc.documentElement,
  296. parent,
  297. box;
  298. if(element == viewport){
  299. return pos;
  300. }
  301. if(element.getBoundingClientRect){ // IE and Gecko 1.9+
  302. //当HTML或者BODY有border width时, 原生的getBoundingClientRect返回值是不符合预期的
  303. //考虑到通常情况下 HTML和BODY的border只会设成0px,所以忽略该问题.
  304. box = element.getBoundingClientRect();
  305. pos.left = Math.floor(box.left) + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft);
  306. pos.top = Math.floor(box.top) + Math.max(doc.documentElement.scrollTop, doc.body.scrollTop);
  307. // IE会给HTML元素添加一个border,默认是medium(2px)
  308. // 但是在IE 6 7 的怪异模式下,可以被html { border: 0; } 这条css规则覆盖
  309. // 在IE7的标准模式下,border永远是2px,这个值通过clientLeft 和 clientTop取得
  310. // 但是。。。在IE 6 7的怪异模式,如果用户使用css覆盖了默认的medium
  311. // clientTop和clientLeft不会更新
  312. pos.left -= doc.documentElement.clientLeft;
  313. pos.top -= doc.documentElement.clientTop;
  314. var htmlDom = doc.body,
  315. // 在这里,不使用element.style.borderLeftWidth,只有computedStyle是可信的
  316. htmlBorderLeftWidth = parseInt(getStyle(htmlDom, 'borderLeftWidth')),
  317. htmlBorderTopWidth = parseInt(getStyle(htmlDom, 'borderTopWidth'));
  318. if(browser.ie && !browser.isStrict){
  319. pos.left -= isNaN(htmlBorderLeftWidth) ? 2 : htmlBorderLeftWidth;
  320. pos.top -= isNaN(htmlBorderTopWidth) ? 2 : htmlBorderTopWidth;
  321. }
  322. } else {
  323. // safari/opera/firefox
  324. parent = element;
  325. do {
  326. pos.left += parent.offsetLeft;
  327. pos.top += parent.offsetTop;
  328. // safari里面,如果遍历到了一个fixed的元素,后面的offset都不准了
  329. if (browser.isWebkit > 0 && getStyle(parent, 'position') == 'fixed') {
  330. pos.left += doc.body.scrollLeft;
  331. pos.top += doc.body.scrollTop;
  332. break;
  333. }
  334. parent = parent.offsetParent;
  335. } while (parent && parent != element);
  336. // 对body offsetTop的修正
  337. if(browser.opera > 0 || (browser.isWebkit > 0 && getStyle(element, 'position') == 'absolute')){
  338. pos.top -= doc.body.offsetTop;
  339. }
  340. // 计算除了body的scroll
  341. parent = element.offsetParent;
  342. while (parent && parent != doc.body) {
  343. pos.left -= parent.scrollLeft;
  344. // see https://bugs.opera.com/show_bug.cgi?id=249965
  345. if (!browser.opera || parent.tagName != 'TR') {
  346. pos.top -= parent.scrollTop;
  347. }
  348. parent = parent.offsetParent;
  349. }
  350. }
  351. return pos;
  352. };
  353. /**
  354. * @ignore
  355. * @namespace baidu.event 屏蔽浏览器差异性的事件封装。
  356. * @property target 事件的触发元素
  357. * @property pageX 鼠标事件的鼠标x坐标
  358. * @property pageY 鼠标事件的鼠标y坐标
  359. * @property keyCode 键盘事件的键值
  360. */
  361. baidu.event = baidu.event || {};
  362. /**
  363. * 事件监听器的存储表
  364. * @private
  365. * @meta standard
  366. */
  367. baidu.event._listeners = baidu.event._listeners || [];
  368. /**
  369. * 为目标元素添加事件监听器
  370. * @name baidu.event.on
  371. * @function
  372. * @grammar baidu.event.on(element, type, listener)
  373. * @param {HTMLElement|string|window} element 目标元素或目标元素id
  374. * @param {string} type 事件类型
  375. * @param {Function} listener 需要添加的监听器
  376. * @remark
  377. *
  378. 1. 不支持跨浏览器的鼠标滚轮事件监听器添加<br>
  379. 2. 改方法不为监听器灌入事件对象,以防止跨iframe事件挂载的事件对象获取失败
  380. * @shortcut on
  381. * @meta standard
  382. * @see baidu.event.un
  383. *
  384. * @returns {HTMLElement|window} 目标元素
  385. */
  386. baidu.event.on = function (element, type, listener) {
  387. type = type.replace(/^on/i, '');
  388. element = baidu.dom._g(element);
  389. var realListener = function (ev) {
  390. // 1. 这里不支持EventArgument, 原因是跨frame的事件挂载
  391. // 2. element是为了修正this
  392. listener.call(element, ev);
  393. },
  394. lis = baidu.event._listeners,
  395. filter = baidu.event._eventFilter,
  396. afterFilter,
  397. realType = type;
  398. type = type.toLowerCase();
  399. // filter过滤
  400. if(filter && filter[type]){
  401. afterFilter = filter[type](element, type, realListener);
  402. realType = afterFilter.type;
  403. realListener = afterFilter.listener;
  404. }
  405. //2018.2.7 注释 --------------------------------------------------------------------------------------------------
  406. //事件监听器挂载
  407. if (element.addEventListener) {
  408. element.addEventListener(realType, realListener, false);
  409. } else if (element.attachEvent) {
  410. element.attachEvent('on' + realType, realListener);
  411. }
  412. // 将监听器存储到数组中
  413. lis[lis.length] = [element, type, listener, realListener, realType];
  414. //------------------------------------------------------------------------------------------------------------------
  415. return element;
  416. };
  417. // 声明快捷方法
  418. baidu.on = baidu.event.on;
  419. /**
  420. * 返回一个当前页面的唯一标识字符串。
  421. * @name baidu.lang.guid
  422. * @function
  423. * @grammar baidu.lang.guid()
  424. * @version 1.1.1
  425. * @meta standard
  426. *
  427. * @returns {String} 当前页面的唯一标识字符串
  428. */
  429. (function(){
  430. //不直接使用window,可以提高3倍左右性能
  431. var guid = window[baidu.guid];
  432. baidu.lang.guid = function() {
  433. return "TANGRAM__" + (guid._counter ++).toString(36);
  434. };
  435. guid._counter = guid._counter || 1;
  436. })();
  437. /**
  438. * 所有类的实例的容器
  439. * key为每个实例的guid
  440. * @meta standard
  441. */
  442. window[baidu.guid]._instances = window[baidu.guid]._instances || {};
  443. /**
  444. * 判断目标参数是否为function或Function实例
  445. * @name baidu.lang.isFunction
  446. * @function
  447. * @grammar baidu.lang.isFunction(source)
  448. * @param {Any} source 目标参数
  449. * @version 1.2
  450. * @see baidu.lang.isString,baidu.lang.isObject,baidu.lang.isNumber,baidu.lang.isArray,baidu.lang.isElement,baidu.lang.isBoolean,baidu.lang.isDate
  451. * @meta standard
  452. * @returns {boolean} 类型判断结果
  453. */
  454. baidu.lang.isFunction = function (source) {
  455. // chrome下,'function' == typeof /a/ 为true.
  456. return '[object Function]' == Object.prototype.toString.call(source);
  457. };
  458. /**
  459. *
  460. * @ignore
  461. * @class Tangram继承机制提供的一个基类,用户可以通过继承baidu.lang.Class来获取它的属性及方法。
  462. * @name baidu.lang.Class
  463. * @grammar baidu.lang.Class(guid)
  464. * @param {string} guid 对象的唯一标识
  465. * @meta standard
  466. * @remark baidu.lang.Class和它的子类的实例均包含一个全局唯一的标识guid。guid是在构造函数中生成的,因此,继承自baidu.lang.Class的类应该直接或者间接调用它的构造函数。<br>baidu.lang.Class的构造函数中产生guid的方式可以保证guid的唯一性,及每个实例都有一个全局唯一的guid。
  467. * @meta standard
  468. * @see baidu.lang.inherits,baidu.lang.Event
  469. */
  470. baidu.lang.Class = function(guid) {
  471. this.guid = guid || baidu.lang.guid();
  472. window[baidu.guid]._instances[this.guid] = this;
  473. };
  474. window[baidu.guid]._instances = window[baidu.guid]._instances || {};
  475. /**
  476. * 释放对象所持有的资源,主要是自定义事件。
  477. * @name dispose
  478. * @grammar obj.dispose()
  479. */
  480. baidu.lang.Class.prototype.dispose = function(){
  481. delete window[baidu.guid]._instances[this.guid];
  482. for(var property in this){
  483. if (!baidu.lang.isFunction(this[property])) {
  484. delete this[property];
  485. }
  486. }
  487. this.disposed = true;
  488. };
  489. /**
  490. * 重载了默认的toString方法,使得返回信息更加准确一些。
  491. * @return {string} 对象的String表示形式
  492. */
  493. baidu.lang.Class.prototype.toString = function(){
  494. return "[object " + (this._className || "Object" ) + "]";
  495. };
  496. /**
  497. * @ignore
  498. * @class 自定义的事件对象。
  499. * @name baidu.lang.Event
  500. * @grammar baidu.lang.Event(type[, target])
  501. * @param {string} type 事件类型名称。为了方便区分事件和一个普通的方法,事件类型名称必须以"on"(小写)开头。
  502. * @param {Object} [target]触发事件的对象
  503. * @meta standard
  504. * @remark 引入该模块,会自动为Class引入3个事件扩展方法:addEventListener、removeEventListener和dispatchEvent。
  505. * @meta standard
  506. * @see baidu.lang.Class
  507. */
  508. baidu.lang.Event = function (type, target) {
  509. this.type = type;
  510. this.returnValue = true;
  511. this.target = target || null;
  512. this.currentTarget = null;
  513. };
  514. /**
  515. * 注册对象的事件监听器。引入baidu.lang.Event后,Class的子类实例才会获得该方法。
  516. * @grammar obj.addEventListener(type, handler[, key])
  517. * @param {string} type 自定义事件的名称
  518. * @param {Function} handler 自定义事件被触发时应该调用的回调函数
  519. * @param {string} [key] 为事件监听函数指定的名称,可在移除时使用。如果不提供,方法会默认为它生成一个全局唯一的key。
  520. * @remark 事件类型区分大小写。如果自定义事件名称不是以小写"on"开头,该方法会给它加上"on"再进行判断,即"click"和"onclick"会被认为是同一种事件。
  521. */
  522. baidu.lang.Class.prototype.addEventListener = function (type, handler, key) {
  523. if (!baidu.lang.isFunction(handler)) {
  524. return;
  525. }
  526. !this.__listeners && (this.__listeners = {});
  527. var t = this.__listeners, id;
  528. if (typeof key == "string" && key) {
  529. if (/[^\w\-]/.test(key)) {
  530. throw("nonstandard key:" + key);
  531. } else {
  532. handler.hashCode = key;
  533. id = key;
  534. }
  535. }
  536. type.indexOf("on") != 0 && (type = "on" + type);
  537. typeof t[type] != "object" && (t[type] = {});
  538. id = id || baidu.lang.guid();
  539. handler.hashCode = id;
  540. t[type][id] = handler;
  541. };
  542. /**
  543. * 移除对象的事件监听器。引入baidu.lang.Event后,Class的子类实例才会获得该方法。
  544. * @grammar obj.removeEventListener(type, handler)
  545. * @param {string} type 事件类型
  546. * @param {Function|string} handler 要移除的事件监听函数或者监听函数的key
  547. * @remark 如果第二个参数handler没有被绑定到对应的自定义事件中,什么也不做。
  548. */
  549. baidu.lang.Class.prototype.removeEventListener = function (type, handler) {
  550. if (typeof handler != "undefined") {
  551. if ( (baidu.lang.isFunction(handler) && ! (handler = handler.hashCode))
  552. || (! baidu.lang.isString(handler))
  553. ){
  554. return;
  555. }
  556. }
  557. !this.__listeners && (this.__listeners = {});
  558. type.indexOf("on") != 0 && (type = "on" + type);
  559. var t = this.__listeners;
  560. if (!t[type]) {
  561. return;
  562. }
  563. if (typeof handler != "undefined") {
  564. t[type][handler] && delete t[type][handler];
  565. } else {
  566. for(var guid in t[type]){
  567. delete t[type][guid];
  568. }
  569. }
  570. };
  571. /**
  572. * 派发自定义事件,使得绑定到自定义事件上面的函数都会被执行。引入baidu.lang.Event后,Class的子类实例才会获得该方法。
  573. * @grammar obj.dispatchEvent(event, options)
  574. * @param {baidu.lang.Event|String} event Event对象,或事件名称(1.1.1起支持)
  575. * @param {Object} options 扩展参数,所含属性键值会扩展到Event对象上(1.2起支持)
  576. * @remark 处理会调用通过addEventListenr绑定的自定义事件回调函数之外,还会调用直接绑定到对象上面的自定义事件。例如:<br>
  577. myobj.onMyEvent = function(){}<br>
  578. myobj.addEventListener("onMyEvent", function(){});
  579. */
  580. baidu.lang.Class.prototype.dispatchEvent = function (event, options) {
  581. if (baidu.lang.isString(event)) {
  582. event = new baidu.lang.Event(event);
  583. }
  584. !this.__listeners && (this.__listeners = {});
  585. // 20100603 添加本方法的第二个参数,将 options extend到event中去传递
  586. options = options || {};
  587. for (var i in options) {
  588. event[i] = options[i];
  589. }
  590. var i, t = this.__listeners, p = event.type;
  591. event.target = event.target || this;
  592. event.currentTarget = this;
  593. p.indexOf("on") != 0 && (p = "on" + p);
  594. baidu.lang.isFunction(this[p]) && this[p].apply(this, arguments);
  595. if (typeof t[p] == "object") {
  596. for (i in t[p]) {
  597. t[p][i].apply(this, arguments);
  598. }
  599. }
  600. return event.returnValue;
  601. };
  602. baidu.lang.inherits = function (subClass, superClass, className) {
  603. var key, proto,
  604. selfProps = subClass.prototype,
  605. clazz = new Function();
  606. clazz.prototype = superClass.prototype;
  607. proto = subClass.prototype = new clazz();
  608. for (key in selfProps) {
  609. proto[key] = selfProps[key];
  610. }
  611. subClass.prototype.constructor = subClass;
  612. subClass.superClass = superClass.prototype;
  613. // 类名标识,兼容Class的toString,基本没用
  614. if ("string" == typeof className) {
  615. proto._className = className;
  616. }
  617. };
  618. // 声明快捷方法
  619. baidu.inherits = baidu.lang.inherits;
  620. })();
  621. /**
  622. * 图片的路径
  623. * @private
  624. * @type {String}
  625. */
  626. var _IMAGE_PATH = './img/blue';
  627. /**
  628. * 图片的后缀名
  629. * @private
  630. * @type {String}
  631. */
  632. var _IMAGE_EXTENSION = 'png';
  633. /**
  634. *@exports TextIconOverlay as BMapLib.TextIconOverlay
  635. */
  636. var TextIconOverlay =
  637. /**
  638. * TextIconOverlay
  639. * @class 此类表示地图上的一个覆盖物,该覆盖物由文字和图标组成,从Overlay继承。文字通常是数字(0-9)或字母(A-Z ),而文字与图标之间有一定的映射关系。
  640. *该覆盖物适用于以下类似的场景:需要在地图上添加一系列覆盖物,这些覆盖物之间用不同的图标和文字来区分,文字可能表示了该覆盖物的某一属性值,根据该文字和一定的映射关系,自动匹配相应颜色和大小的图标。
  641. *
  642. *@constructor
  643. *@param {Point} position 表示一个经纬度坐标位置。
  644. *@param {String} text 表示该覆盖物显示的文字信息。//秦改成obj形式吧
  645. *@param {Json Object} options 可选参数,可选项包括:<br />
  646. *"<b>styles</b>":{Array<IconStyle>} 一组图标风格。单个图表风格包括以下几个属性:<br />
  647. * url {String} 图片的url地址。(必选)<br />
  648. * size {Size} 图片的大小。(必选)<br />
  649. * anchor {Size} 图标定位在地图上的位置相对于图标左上角的偏移值,默认偏移值为图标的中心位置。(可选)<br />
  650. * offset {Size} 图片相对于可视区域的偏移值,此功能的作用等同于CSS中的background-position属性。(可选)<br />
  651. * textSize {Number} 文字的大小。(可选,默认10)<br />
  652. * textColor {String} 文字的颜色。(可选,默认black)<br />
  653. */
  654. BMapLib.TextIconOverlay = function(position, text, options){
  655. this._position = position;
  656. this._text = text;
  657. this._options = options || {};
  658. this._styles = this._options['styles'] || [];
  659. (!this._styles.length) && this._setupDefaultStyles();
  660. };
  661. T.lang.inherits(TextIconOverlay, BMap.Overlay, "TextIconOverlay");
  662. TextIconOverlay.prototype._setupDefaultStyles = function(){
  663. //var sizes = [53, 56, 66, 78, 92];
  664. // for(var i = 0, size; size = sizes[i]; i++){
  665. // }//for循环的简洁写法
  666. // 聚合的数据
  667. this._styles.push({
  668. url:_IMAGE_PATH + '.' + _IMAGE_EXTENSION,
  669. size: new BMap.Size(92, 92)
  670. });
  671. //单条数据
  672. };
  673. /**
  674. *继承Overlay的intialize方法,自定义覆盖物时必须。
  675. *@param {Map} map BMap.Map的实例化对象。
  676. *@return {HTMLElement} 返回覆盖物对应的HTML元素。
  677. */
  678. TextIconOverlay.prototype.initialize = function(map){
  679. this._map = map;
  680. this._domElement = document.createElement('div');
  681. this._updateCss();
  682. this._updateText();
  683. this._updatePosition();
  684. this._bind();
  685. this._map.getPanes().markerMouseTarget.appendChild(this._domElement);
  686. return this._domElement;
  687. };
  688. /**
  689. *继承Overlay的draw方法,自定义覆盖物时必须。
  690. *@return 无返回值。
  691. */
  692. TextIconOverlay.prototype.draw = function(){
  693. this._map && this._updatePosition();
  694. };
  695. /**
  696. *获取该覆盖物上的文字。
  697. *@return {String} 该覆盖物上的文字。
  698. */
  699. TextIconOverlay.prototype.getText = function(){
  700. return this._text;
  701. };
  702. /**
  703. *设置该覆盖物上的文字。
  704. *@param {String} text 要设置的文字,通常是字母A-Z或数字0-9。
  705. *@return 无返回值。
  706. */
  707. TextIconOverlay.prototype.setText = function(text){
  708. if(text && (!this._text || (this._text.value != text.value) || (this._text.name != text.name))){
  709. this._text = text;
  710. this._updateText();
  711. this._updateCss();
  712. this._updatePosition();
  713. }
  714. };
  715. /**
  716. *获取该覆盖物的位置。
  717. *@return {Point} 该覆盖物的经纬度坐标。
  718. */
  719. TextIconOverlay.prototype.getPosition = function () {
  720. return this._position;
  721. };
  722. /**
  723. *设置该覆盖物的位置。
  724. *@param {Point} position 要设置的经纬度坐标。
  725. *@return 无返回值。
  726. */
  727. TextIconOverlay.prototype.setPosition = function (position) {
  728. if(position && (!this._position || !this._position.equals(position))){
  729. this._position = position;
  730. this._updatePosition();
  731. }
  732. };
  733. /**
  734. *由文字信息获取风格数组的对应索引值。
  735. *内部默认的对应函数为文字转换为数字除以10的结果,比如文字8返回索引0,文字25返回索引2.
  736. *如果需要自定义映射关系,请覆盖该函数。
  737. *@param {String} text 文字。
  738. *@param {Array<IconStyle>} styles 一组图标风格。
  739. *@return {Number} 对应的索引值。
  740. *2017-2-17 09:03:58废除
  741. */
  742. // TextIconOverlay.prototype.getStyleByText = function(text, styles){
  743. // var count = parseInt(text.value);
  744. // var index = parseInt(count / 10);
  745. // index = Math.max(0, index);
  746. // index = Math.min(index, styles.length - 1);
  747. // return styles[index];
  748. // }
  749. /**
  750. *更新相应的CSS。
  751. *@return 无返回值。
  752. */
  753. TextIconOverlay.prototype._updateCss = function(){
  754. //var style = this.getStyleByText(this._text, this._styles);
  755. var style = this._styles[0];
  756. this._domElement.style.cssText = this._buildCssText(style);
  757. };
  758. /**
  759. *更新覆盖物的显示文字。
  760. *@return 无返回值。
  761. */
  762. TextIconOverlay.prototype._updateText = function(){
  763. if (this._domElement) {
  764. this._domElement.innerHTML = '<p style="margin-top:25px;width:75px;margin-left:9px;line-height:15px;">'+this._text.name+'</p>'+'<p>'+this._text.value+'</p>';
  765. }
  766. };
  767. /**
  768. *调整覆盖物在地图上的位置更新覆盖物的显示文字。
  769. *@return 无返回值。
  770. */
  771. TextIconOverlay.prototype._updatePosition = function(){
  772. if (this._domElement && this._position) {
  773. var style = this._domElement.style;
  774. var pixelPosition= this._map.pointToOverlayPixel(this._position);
  775. pixelPosition.x -= Math.ceil(parseInt(style.width) / 2);
  776. pixelPosition.y -= Math.ceil(parseInt(style.height) / 2);
  777. style.left = pixelPosition.x + "px";
  778. style.top = pixelPosition.y + "px";
  779. }
  780. };
  781. /**
  782. * 为该覆盖物的HTML元素构建CSS
  783. * @param {IconStyle} 一个图标的风格。
  784. * @return {String} 构建完成的CSSTEXT。
  785. */
  786. TextIconOverlay.prototype._buildCssText = function(style) {
  787. //根据style来确定一些默认值
  788. var url = style['url'];
  789. var size = style['size'];
  790. var anchor = style['anchor'];
  791. var offset = style['offset'];
  792. var textColor = style['textColor'] || '#fff';
  793. var textSize = style['textSize'] || 10;
  794. var csstext = [];
  795. if (T.browser["ie"] < 7) {
  796. csstext.push('filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(' +
  797. 'sizingMethod=scale,src="' + url + '");')
  798. } else {
  799. csstext.push('background-image:url(' + url + ');');
  800. var backgroundPosition = '0 0';
  801. (offset instanceof BMap.Size) && (backgroundPosition = offset.width + 'px' + ' ' + offset.height + 'px');
  802. csstext.push('background-position:' + backgroundPosition + ';');
  803. }
  804. if (size instanceof BMap.Size){
  805. if (anchor instanceof BMap.Size) {
  806. if (anchor.height > 0 && anchor.height < size.height) {
  807. csstext.push('height:' + (size.height - anchor.height) + 'px; padding-top:' + anchor.height + 'px;');
  808. }
  809. if(anchor.width > 0 && anchor.width < size.width){
  810. csstext.push('width:' + (size.width - anchor.width) + 'px; padding-left:' + anchor.width + 'px;');
  811. }
  812. } else {
  813. csstext.push('height:' + size.height + 'px; line-height:' + 20 + 'px;');
  814. csstext.push('width:' + size.width + 'px; text-align:center;');
  815. }
  816. }
  817. csstext.push('cursor:pointer; color:' + textColor + '; position:absolute; font-size:' +
  818. textSize + 'px; font-family:Arial,sans-serif; font-weight:bold');
  819. return csstext.join('');
  820. };
  821. /**
  822. * 当鼠标点击该覆盖物时会触发该事件
  823. * @name TextIconOverlay#click
  824. * @event
  825. * @param {Event Object} e 回调函数会返回event参数,包括以下返回值:
  826. * <br />"<b>type</b> : {String} 事件类型
  827. * <br />"<b>target</b>:{BMapLib.TextIconOverlay} 事件目标
  828. *
  829. */
  830. /**
  831. * 当鼠标进入该覆盖物区域时会触发该事件
  832. * @name TextIconOverlay#mouseover
  833. * @event
  834. * @param {Event Object} e 回调函数会返回event参数,包括以下返回值:
  835. * <br />"<b>type</b> : {String} 事件类型
  836. * <br />"<b>target</b>:{BMapLib.TextIconOverlay} 事件目标
  837. * <br />"<b>point</b> : {BMap.Point} 最新添加上的节点BMap.Point对象
  838. * <br />"<b>pixel</b>:{BMap.pixel} 最新添加上的节点BMap.Pixel对象
  839. *
  840. * @example <b>参考示例:</b><br />
  841. * myTextIconOverlay.addEventListener("mouseover", function(e) { alert(e.point); });
  842. */
  843. /**
  844. * 当鼠标离开该覆盖物区域时会触发该事件
  845. * @name TextIconOverlay#mouseout
  846. * @event
  847. * @param {Event Object} e 回调函数会返回event参数,包括以下返回值:
  848. * <br />"<b>type</b> : {String} 事件类型
  849. * <br />"<b>target</b>:{BMapLib.TextIconOverlay} 事件目标
  850. * <br />"<b>point</b> : {BMap.Point} 最新添加上的节点BMap.Point对象
  851. * <br />"<b>pixel</b>:{BMap.pixel} 最新添加上的节点BMap.Pixel对象
  852. *
  853. * @example <b>参考示例:</b><br />
  854. * myTextIconOverlay.addEventListener("mouseout", function(e) { alert(e.point); });
  855. */
  856. /**
  857. * 为该覆盖物绑定一系列事件
  858. * 当前支持click mouseover mouseout
  859. * @return 无返回值。
  860. */
  861. TextIconOverlay.prototype._bind = function(){
  862. if (!this._domElement){
  863. return;
  864. }
  865. var me = this;
  866. var map = this._map;
  867. var BaseEvent = T.lang.Event;
  868. function eventExtend(e, be){
  869. var elem = e.srcElement || e.target;
  870. var x = e.clientX || e.pageX;
  871. var y = e.clientY || e.pageY;
  872. if (e && be && x && y && elem){
  873. var offset = T.dom.getPosition(map.getContainer());
  874. be.pixel = new BMap.Pixel(x - offset.left, y - offset.top);
  875. be.point = map.pixelToPoint(be.pixel);
  876. }
  877. return be;
  878. }//给事件参数增加pixel和point两个值
  879. T.event.on(this._domElement,"mouseover", function(e){
  880. me.dispatchEvent(eventExtend(e, new BaseEvent("onmouseover")));
  881. });
  882. T.event.on(this._domElement,"mouseout", function(e){
  883. me.dispatchEvent(eventExtend(e, new BaseEvent("onmouseout")));
  884. });
  885. T.event.on(this._domElement,"click", function(e){
  886. me.dispatchEvent(eventExtend(e, new BaseEvent("onclick")));
  887. });
  888. };
  889. })();