InfoBox.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  1. /**
  2. * @fileoverview 百度地图的自定义信息窗口,对外开放。
  3. * 用户自定义信息窗口的各种样式。例如:border,margin,padding,color,background等
  4. * 主入口类是<a href="symbols/BMapLib.InfoBox.html">InfoBox</a>,
  5. * 基于Baidu Map API 1.2。
  6. *
  7. * @author Baidu Map Api Group
  8. * @version 1.2
  9. */
  10. /**
  11. * @namespace BMap的所有library类均放在BMapLib命名空间下
  12. */
  13. var BMapLib = window.BMapLib = BMapLib || {};
  14. //常量,infoBox可以出现的位置,此版本只可实现上下两个方向。
  15. var INFOBOX_AT_TOP = 1, INFOBOX_AT_RIGHT = 2, INFOBOX_AT_BOTTOM = 3, INFOBOX_AT_LEFT = 4;
  16. (function() {
  17. //声明baidu包
  18. var T, baidu = T = baidu || {version: '1.5.0'};
  19. baidu.guid = '$BAIDU$';
  20. //以下方法为百度Tangram框架中的方法,请到http://tangram.baidu.com 查看文档
  21. (function() {
  22. window[baidu.guid] = window[baidu.guid] || {};
  23. baidu.lang = baidu.lang || {};
  24. baidu.lang.isString = function (source) {
  25. return '[object String]' == Object.prototype.toString.call(source);
  26. };
  27. baidu.lang.isFunction = function (source) {
  28. return '[object Function]' == Object.prototype.toString.call(source);
  29. };
  30. baidu.lang.Event = function (type, target) {
  31. this.type = type;
  32. this.returnValue = true;
  33. this.target = target || null;
  34. this.currentTarget = null;
  35. };
  36. baidu.object = baidu.object || {};
  37. baidu.extend =
  38. baidu.object.extend = function (target, source) {
  39. for (var p in source) {
  40. if (source.hasOwnProperty(p)) {
  41. target[p] = source[p];
  42. }
  43. }
  44. return target;
  45. };
  46. baidu.event = baidu.event || {};
  47. baidu.event._listeners = baidu.event._listeners || [];
  48. baidu.dom = baidu.dom || {};
  49. baidu.dom._g = function (id) {
  50. if (baidu.lang.isString(id)) {
  51. return document.getElementById(id);
  52. }
  53. return id;
  54. };
  55. baidu._g = baidu.dom._g;
  56. baidu.event.on = function (element, type, listener) {
  57. type = type.replace(/^on/i, '');
  58. element = baidu.dom._g(element);
  59. var realListener = function (ev) {
  60. // 1. 这里不支持EventArgument, 原因是跨frame的事件挂载
  61. // 2. element是为了修正this
  62. listener.call(element, ev);
  63. },
  64. lis = baidu.event._listeners,
  65. filter = baidu.event._eventFilter,
  66. afterFilter,
  67. realType = type;
  68. type = type.toLowerCase();
  69. // filter过滤
  70. if(filter && filter[type]){
  71. afterFilter = filter[type](element, type, realListener);
  72. realType = afterFilter.type;
  73. realListener = afterFilter.listener;
  74. }
  75. // 事件监听器挂载
  76. if (element.addEventListener) {
  77. element.addEventListener(realType, realListener, false);
  78. } else if (element.attachEvent) {
  79. element.attachEvent('on' + realType, realListener);
  80. }
  81. // 将监听器存储到数组中
  82. lis[lis.length] = [element, type, listener, realListener, realType];
  83. return element;
  84. };
  85. baidu.on = baidu.event.on;
  86. baidu.event.un = function (element, type, listener) {
  87. element = baidu.dom._g(element);
  88. type = type.replace(/^on/i, '').toLowerCase();
  89. var lis = baidu.event._listeners,
  90. len = lis.length,
  91. isRemoveAll = !listener,
  92. item,
  93. realType, realListener;
  94. while (len--) {
  95. item = lis[len];
  96. if (item[1] === type
  97. && item[0] === element
  98. && (isRemoveAll || item[2] === listener)) {
  99. realType = item[4];
  100. realListener = item[3];
  101. if (element.removeEventListener) {
  102. element.removeEventListener(realType, realListener, false);
  103. } else if (element.detachEvent) {
  104. element.detachEvent('on' + realType, realListener);
  105. }
  106. lis.splice(len, 1);
  107. }
  108. }
  109. return element;
  110. };
  111. baidu.un = baidu.event.un;
  112. baidu.dom.g = function (id) {
  113. if ('string' == typeof id || id instanceof String) {
  114. return document.getElementById(id);
  115. } else if (id && id.nodeName && (id.nodeType == 1 || id.nodeType == 9)) {
  116. return id;
  117. }
  118. return null;
  119. };
  120. baidu.g = baidu.G = baidu.dom.g;
  121. baidu.dom._styleFixer = baidu.dom._styleFixer || {};
  122. baidu.dom._styleFilter = baidu.dom._styleFilter || [];
  123. baidu.dom._styleFilter.filter = function (key, value, method) {
  124. for (var i = 0, filters = baidu.dom._styleFilter, filter; filter = filters[i]; i++) {
  125. if (filter = filter[method]) {
  126. value = filter(key, value);
  127. }
  128. }
  129. return value;
  130. };
  131. baidu.string = baidu.string || {};
  132. baidu.string.toCamelCase = function (source) {
  133. //提前判断,提高getStyle等的效率 thanks xianwei
  134. if (source.indexOf('-') < 0 && source.indexOf('_') < 0) {
  135. return source;
  136. }
  137. return source.replace(/[-_][^-_]/g, function (match) {
  138. return match.charAt(1).toUpperCase();
  139. });
  140. };
  141. baidu.dom.setStyle = function (element, key, value) {
  142. var dom = baidu.dom, fixer;
  143. // 放弃了对firefox 0.9的opacity的支持
  144. element = dom.g(element);
  145. key = baidu.string.toCamelCase(key);
  146. if (fixer = dom._styleFilter) {
  147. value = fixer.filter(key, value, 'set');
  148. }
  149. fixer = dom._styleFixer[key];
  150. (fixer && fixer.set) ? fixer.set(element, value) : (element.style[fixer || key] = value);
  151. return element;
  152. };
  153. baidu.setStyle = baidu.dom.setStyle;
  154. baidu.dom.setStyles = function (element, styles) {
  155. element = baidu.dom.g(element);
  156. for (var key in styles) {
  157. baidu.dom.setStyle(element, key, styles[key]);
  158. }
  159. return element;
  160. };
  161. baidu.setStyles = baidu.dom.setStyles;
  162. baidu.browser = baidu.browser || {};
  163. baidu.browser.ie = baidu.ie = /msie (\d+\.\d+)/i.test(navigator.userAgent) ? (document.documentMode || + RegExp['\x241']) : undefined;
  164. baidu.dom._NAME_ATTRS = (function () {
  165. var result = {
  166. 'cellpadding': 'cellPadding',
  167. 'cellspacing': 'cellSpacing',
  168. 'colspan': 'colSpan',
  169. 'rowspan': 'rowSpan',
  170. 'valign': 'vAlign',
  171. 'usemap': 'useMap',
  172. 'frameborder': 'frameBorder'
  173. };
  174. if (baidu.browser.ie < 8) {
  175. result['for'] = 'htmlFor';
  176. result['class'] = 'className';
  177. } else {
  178. result['htmlFor'] = 'for';
  179. result['className'] = 'class';
  180. }
  181. return result;
  182. })();
  183. baidu.dom.setAttr = function (element, key, value) {
  184. element = baidu.dom.g(element);
  185. if ('style' == key){
  186. element.style.cssText = value;
  187. } else {
  188. key = baidu.dom._NAME_ATTRS[key] || key;
  189. element.setAttribute(key, value);
  190. }
  191. return element;
  192. };
  193. baidu.setAttr = baidu.dom.setAttr;
  194. baidu.dom.setAttrs = function (element, attributes) {
  195. element = baidu.dom.g(element);
  196. for (var key in attributes) {
  197. baidu.dom.setAttr(element, key, attributes[key]);
  198. }
  199. return element;
  200. };
  201. baidu.setAttrs = baidu.dom.setAttrs;
  202. baidu.dom.create = function(tagName, opt_attributes) {
  203. var el = document.createElement(tagName),
  204. attributes = opt_attributes || {};
  205. return baidu.dom.setAttrs(el, attributes);
  206. };
  207. T.undope=true;
  208. })();
  209. /**
  210. * @exports InfoBox as BMapLib.InfoBox
  211. */
  212. var InfoBox =
  213. /**
  214. * InfoBox类的构造函数
  215. * @class InfoBox <b>入口</b>。
  216. * 可以自定义border,margin,padding,关闭按钮等等。
  217. * @constructor
  218. * @param {Map} map Baidu map的实例对象.
  219. * @param {String} content infoBox中的内容.
  220. * @param {Json Object} opts 可选的输入参数,非必填项。可输入选项包括:<br />
  221. * {<br />"<b>offset</b>" : {Size} infoBox的偏移量
  222. * <br />"<b>boxClass</b>" : {String} 定义infoBox的class,
  223. * <br />"<b>boxStyle</b>" : {Json} 定义infoBox的style,此项会覆盖boxClass<br />
  224. * <br />"<b>closeIconMargin</b>" : {String} 关闭按钮的margin <br />
  225. * <br />"<b>closeIconUrl</b>" : {String} 关闭按钮的url地址 <br />
  226. * <br />"<b>enableAutoPan</b>" : {Boolean} 是否启动自动平移功能 <br />
  227. * <br />"<b>align</b>" : {Number} 基于哪个位置进行定位,取值为[INFOBOX_AT_TOP,INFOBOX_AT_BOTTOM]<br />
  228. * }<br />.
  229. * @example <b>参考示例:</b><br />
  230. * var infoBox = new BMapLib.InfoBox(map,"百度地图api",{boxStyle:{background:"url('tipbox.gif') no-repeat
  231. center top",width: "200px"},closeIconMargin: "10px 2px 0 0",enableAutoPan: true
  232. ,alignBottom: false});
  233. */
  234. BMapLib.InfoBox = function(map, content, opts) {
  235. this._content = content || "";
  236. this._isOpen = false;
  237. this._map = map;
  238. this._opts = opts = opts || {};
  239. this._opts.offset = opts.offset || new BMap.Size(0,0);
  240. this._opts.boxClass = opts.boxClass || "infoBox";
  241. this._opts.boxStyle = opts.boxStyle || {};
  242. this._opts.closeIconMargin = opts.closeIconMargin || "2px";
  243. this._opts.closeIconUrl = opts.closeIconUrl || MAPCONFIG.MAPPATH+"images/iw_close1d3.gif";
  244. this._opts.enableAutoPan = opts.enableAutoPan ? true : false;
  245. this._opts.align = opts.align || INFOBOX_AT_TOP;
  246. }
  247. InfoBox.prototype = new BMap.Overlay();
  248. InfoBox.prototype.initialize = function(map) {
  249. var me = this;
  250. var div = this._div = baidu.dom.create('div', {"class": this._opts.boxClass});
  251. baidu.dom.setStyles(div, this._opts.boxStyle);
  252. //设置position为absolute,用于定位
  253. div.style.position = "absolute";
  254. this._setContent(this._content);
  255. var floatPane = map.getPanes().floatPane;
  256. floatPane.style.width = "auto";
  257. floatPane.appendChild(div);
  258. //设置完内容后,获取div的宽度,高度
  259. this._getInfoBoxSize();
  260. //this._boxWidth = parseInt(this._div.offsetWidth,10);
  261. //this._boxHeight = parseInt(this._div.offsetHeight,10);
  262. //阻止各种冒泡事件
  263. baidu.event.on(div,"onmousedown",function(e){
  264. me._stopBubble(e);
  265. });
  266. baidu.event.on(div,"onmouseover",function(e){
  267. me._stopBubble(e);
  268. });
  269. baidu.event.on(div,"click",function(e){
  270. me._stopBubble(e);
  271. });
  272. baidu.event.on(div,"dblclick",function(e){
  273. me._stopBubble(e);
  274. });
  275. return div;
  276. }
  277. InfoBox.prototype.draw = function() {
  278. this._isOpen && this._adjustPosition(this._point);
  279. }
  280. /**
  281. * 打开infoBox
  282. * @param {Marker|Point} anchor 要在哪个marker或者point上打开infobox
  283. * @return none
  284. *
  285. * @example <b>参考示例:</b><br />
  286. * infoBox.open();
  287. */
  288. InfoBox.prototype.open = function(anchor){
  289. var me = this,poi;
  290. if(!this._isOpen) {
  291. this._map.addOverlay(this);
  292. this._isOpen = true;
  293. //延迟10ms派发open事件,使后绑定的事件可以触发。
  294. setTimeout(function(){
  295. me._dispatchEvent(me,"open",{"point" : me._point});
  296. },10);
  297. }
  298. if(anchor instanceof BMap.Point){
  299. poi = anchor;
  300. //清除之前存在的marker事件绑定,如果存在的话
  301. this._removeMarkerEvt();
  302. }else if(anchor instanceof BMap.Marker){
  303. //如果当前marker不为空,说明是第二个marker,或者第二次点open按钮,先移除掉之前绑定的事件
  304. if(this._marker){
  305. this._removeMarkerEvt();
  306. }
  307. poi = anchor.getPosition();
  308. this._marker = anchor;
  309. !this._markerDragend && this._marker.addEventListener("dragend",this._markerDragend = function(e){
  310. me._point = e.point;
  311. me._adjustPosition(me._point);
  312. me._panBox();
  313. me.show();
  314. });
  315. //给marker绑定dragging事件,拖动marker的时候,infoBox也跟随移动
  316. !this._markerDragging && this._marker.addEventListener("dragging",this._markerDragging = function(){
  317. me.hide();
  318. me._point = me._marker.getPosition();
  319. me._adjustPosition(me._point);
  320. });
  321. }
  322. //打开的时候,将infowindow显示
  323. this.show();
  324. this._point = poi;
  325. this._panBox();
  326. this._adjustPosition(this._point);
  327. }
  328. /**
  329. * 关闭infoBox
  330. * @return none
  331. *
  332. * @example <b>参考示例:</b><br />
  333. * infoBox.close();
  334. */
  335. InfoBox.prototype.close = function(){
  336. if(this._isOpen){
  337. this._map.removeOverlay(this);
  338. this._div.style.display="none";
  339. this._isOpen = false;
  340. this._dispatchEvent(this,"close",{"point" : this._point});
  341. }
  342. }
  343. /**
  344. * 打开infoBox时,派发事件的接口
  345. * @name InfoBox#Open
  346. * @event
  347. * @param {Event Object} e 回调函数会返回event参数,包括以下返回值:
  348. * <br />{"<b>target</b> : {BMap.Overlay} 触发事件的元素,
  349. * <br />"<b>type</b>:{String} 事件类型,
  350. * <br />"<b>point</b>:{Point} infoBox的打开位置}
  351. *
  352. * @example <b>参考示例:</b>
  353. * infoBox.addEventListener("open", function(e) {
  354. * alert(e.type);
  355. * });
  356. */
  357. /**
  358. * 关闭infoBox时,派发事件的接口
  359. * @name InfoBox#Close
  360. * @event
  361. * @param {Event Object} e 回调函数会返回event参数,包括以下返回值:
  362. * <br />{"<b>target</b> : {BMap.Overlay} 触发事件的元素,
  363. * <br />"<b>type</b>:{String} 事件类型,
  364. * <br />"<b>point</b>:{Point} infoBox的关闭位置}
  365. *
  366. * @example <b>参考示例:</b>
  367. * infoBox.addEventListener("close", function(e) {
  368. * alert(e.type);
  369. * });
  370. */
  371. /**
  372. * 启用自动平移
  373. * @return none
  374. *
  375. * @example <b>参考示例:</b><br />
  376. * infoBox.enableAutoPan();
  377. */
  378. InfoBox.prototype.enableAutoPan = function(){
  379. this._opts.enableAutoPan = true;
  380. }
  381. /**
  382. * 禁用自动平移
  383. * @return none
  384. *
  385. * @example <b>参考示例:</b><br />
  386. * infoBox.disableAutoPan();
  387. */
  388. InfoBox.prototype.disableAutoPan = function(){
  389. this._opts.enableAutoPan = false;
  390. }
  391. /**
  392. * 设置infoBox的内容
  393. * @param {String|HTMLElement} content 弹出气泡中的内容
  394. * @return none
  395. *
  396. * @example <b>参考示例:</b><br />
  397. * infoBox.setContent("百度地图API");
  398. */
  399. InfoBox.prototype.setContent = function(content){
  400. this._setContent(content);
  401. this._getInfoBoxSize();
  402. this._adjustPosition(this._point);
  403. }
  404. /**
  405. * 设置信息窗的地理位置
  406. * @param {Point} point 设置position
  407. * @return none
  408. *
  409. * @example <b>参考示例:</b><br />
  410. * infoBox.setPosition(new BMap.Point(116.35,39.911));
  411. */
  412. InfoBox.prototype.setPosition = function(poi){
  413. this._point = poi;
  414. this._adjustPosition(poi);
  415. this._removeMarkerEvt();
  416. }
  417. /**
  418. * 获得信息窗的地理位置
  419. * @param none
  420. * @return {Point} 信息窗的地理坐标
  421. *
  422. * @example <b>参考示例:</b><br />
  423. * infoBox.getPosition();
  424. */
  425. InfoBox.prototype.getPosition = function(){
  426. return this._point;
  427. }
  428. /**
  429. * 返回信息窗口的箭头距离信息窗口在地图
  430. * 上所锚定的地理坐标点的像素偏移量。
  431. * @return {Size} Size
  432. *
  433. * @example <b>参考示例:</b><br />
  434. * infoBox.getOffset();
  435. */
  436. InfoBox.prototype.getOffset = function(){
  437. return this._opts.offset;
  438. },
  439. /**
  440. *@ignore
  441. * 删除overlay,调用Map.removeOverlay时将调用此方法,
  442. * 将移除覆盖物的容器元素
  443. */
  444. InfoBox.prototype.remove = function(){
  445. var me = this;
  446. if(this.domElement && this.domElement.parentNode){
  447. //防止内存泄露
  448. baidu.event.un(this._div.firstChild, "click", me._closeHandler());
  449. this.domElement.parentNode.removeChild(this.domElement);
  450. }
  451. this.domElement = null;
  452. this._isOpen = false;
  453. this.dispatchEvent("onremove");
  454. },
  455. baidu.object.extend(InfoBox.prototype,{
  456. /**
  457. * 获取关闭按钮的html
  458. * @return IMG 关闭按钮的HTML代码
  459. */
  460. _getCloseIcon: function(){
  461. var img = "<img src='"+ this._opts.closeIconUrl +"' onclick='try{this.close();}catch(e){}' alt='Close Form' align='right' style='position:absolute;right:0px;cursor:pointer;margin:"+ this._opts.closeIconMargin +"'/>";
  462. return img;
  463. },
  464. /**
  465. * 设置infoBox的内容
  466. * @param {String|HTMLElement} content 弹出气泡中的内容
  467. * @return none
  468. *
  469. * @example <b>参考示例:</b><br />
  470. * infoBox.setContent("百度地图API");
  471. */
  472. _setContent: function(content){
  473. if(!this._div){
  474. return;
  475. }
  476. var closeHtml = this._getCloseIcon();
  477. //string类型的content
  478. if(typeof content.nodeType === "undefined"){
  479. this._div.innerHTML = closeHtml + content;
  480. }else{
  481. this._div.innerHTML = closeHtml;
  482. this._div.appendChild(content);
  483. }
  484. this._content = content;
  485. //添加click关闭infobox事件
  486. this._addEventToClose();
  487. },
  488. /**
  489. * 调整infobox的position
  490. * @return none
  491. */
  492. _adjustPosition: function(poi){
  493. var pixel = this._getPointPosition(poi);
  494. var icon = this._marker && this._marker.getIcon();
  495. switch(this._opts.align){
  496. case INFOBOX_AT_TOP:
  497. if(this._marker){
  498. this._div.style.bottom = -(pixel.y - this._opts.offset.height - icon.anchor.height + icon.infoWindowAnchor.height) - this._marker.getOffset().height + 2 + "px";
  499. }else{
  500. this._div.style.bottom = -(pixel.y - this._opts.offset.height) + "px";
  501. }
  502. break;
  503. case INFOBOX_AT_BOTTOM:
  504. if(this._marker){
  505. this._div.style.top = pixel.y + this._opts.offset.height - icon.anchor.height + icon.infoWindowAnchor.height + this._marker.getOffset().height + "px";
  506. }else{
  507. this._div.style.top = pixel.y + this._opts.offset.height + "px";
  508. }
  509. break;
  510. }
  511. if (this._marker) {
  512. this._div.style.left = pixel.x - icon.anchor.width + this._opts.offset.width + icon.infoWindowAnchor.width - this._boxWidth / 2 + "px";
  513. }else{
  514. this._div.style.left = pixel.x - this._boxWidth / 2 + this._opts.offset.width + "px";
  515. }
  516. },
  517. /**
  518. * 得到infobox的position
  519. * @return Point infobox当前的position
  520. */
  521. _getPointPosition: function(poi){
  522. this._pointPosition = this._map.pointToOverlayPixel(poi);
  523. return this._pointPosition;
  524. },
  525. /**
  526. * 得到infobox的高度跟宽度
  527. * @return none
  528. */
  529. _getInfoBoxSize: function(){
  530. this._boxWidth = parseInt(this._div.offsetWidth,10);
  531. this._boxHeight = parseInt(this._div.offsetHeight,10);
  532. },
  533. /**
  534. * 添加关闭事件
  535. * @return none
  536. */
  537. _addEventToClose: function(){
  538. var me = this;
  539. baidu.event.on(this._div.firstChild, "click", me._closeHandler());
  540. this._hasBindEventClose = true;
  541. },
  542. /**
  543. * 处理关闭事件
  544. * @return none
  545. */
  546. _closeHandler: function(){
  547. var me = this;
  548. return function(e){
  549. me.close();
  550. }
  551. },
  552. /**
  553. * 阻止事件冒泡
  554. * @return none
  555. */
  556. _stopBubble: function(e){
  557. if(e && e.stopPropagation){
  558. e.stopPropagation();
  559. }else{
  560. window.event.cancelBubble = true;
  561. }
  562. },
  563. /**
  564. * 自动平移infobox,使其在视野中全部显示
  565. * @return none
  566. */
  567. _panBox: function(){
  568. if(!this._opts.enableAutoPan){
  569. return;
  570. }
  571. var mapH = parseInt(this._map.getContainer().offsetHeight,10),
  572. mapW = parseInt(this._map.getContainer().offsetWidth,10),
  573. boxH = this._boxHeight,
  574. boxW = this._boxWidth;
  575. //infobox窗口本身的宽度或者高度超过map container
  576. if(boxH >= mapH || boxW >= mapW){
  577. return;
  578. }
  579. //如果point不在可视区域内
  580. if(!this._map.getBounds().containsPoint(this._point)){
  581. this._map.setCenter(this._point);
  582. }
  583. var anchorPos = this._map.pointToPixel(this._point),
  584. panTop,panBottom,panY,
  585. //左侧超出
  586. panLeft = boxW / 2 - anchorPos.x,
  587. //右侧超出
  588. panRight = boxW / 2 + anchorPos.x - mapW;
  589. if(this._marker){
  590. var icon = this._marker.getIcon();
  591. }
  592. //基于bottom定位,也就是infoBox在上方的情况
  593. switch(this._opts.align){
  594. case INFOBOX_AT_TOP:
  595. //上侧超出
  596. var h = this._marker ? icon.anchor.height + this._marker.getOffset().height - icon.infoWindowAnchor.height : 0;
  597. panTop = boxH - anchorPos.y + this._opts.offset.height + h + 2 ;
  598. break;
  599. case INFOBOX_AT_BOTTOM:
  600. //下侧超出
  601. var h = this._marker ? -icon.anchor.height + icon.infoWindowAnchor.height + this._marker.getOffset().height + this._opts.offset.height : 0;
  602. panBottom = boxH + anchorPos.y - mapH + h + 4;
  603. break;
  604. }
  605. panX = panLeft > 0 ? panLeft : (panRight > 0 ? -panRight : 0);
  606. panY = panTop > 0 ? panTop : (panBottom > 0 ? -panBottom : 0);
  607. this._map.panBy(panX,panY);
  608. },
  609. _removeMarkerEvt: function(){
  610. this._markerDragend && this._marker.removeEventListener("dragend", this._markerDragend);
  611. this._markerDragging && this._marker.removeEventListener("dragging", this._markerDragging);
  612. this._markerDragend = this._markerDragging = null;
  613. },
  614. /**
  615. * 集中派发事件函数
  616. *
  617. * @private
  618. * @param {Object} instance 派发事件的实例
  619. * @param {String} type 派发的事件名
  620. * @param {Json} opts 派发事件里添加的参数,可选
  621. */
  622. _dispatchEvent: function(instance, type, opts) {
  623. type.indexOf("on") != 0 && (type = "on" + type);
  624. var event = new baidu.lang.Event(type);
  625. if (!!opts) {
  626. for (var p in opts) {
  627. event[p] = opts[p];
  628. }
  629. }
  630. instance.dispatchEvent(event);
  631. }
  632. });
  633. })();