index.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. (function (root, factory) {
  2. if (typeof exports === 'object') {
  3. module.exports = factory();
  4. } else if (typeof define === 'function' && define.amd) {
  5. define(factory);
  6. } else {
  7. root.BMapLib = root.BMapLib || {};
  8. root.BMapLib.LuShu = root.BMapLib.Lushu || factory();
  9. }
  10. })(this, function() {
  11. var baidu = {};
  12. baidu.dom = {};
  13. baidu.dom.g = function(id) {
  14. if ('string' == typeof id || id instanceof String) {
  15. return document.getElementById(id);
  16. } else if (id && id.nodeName && (id.nodeType == 1 || id.nodeType == 9)) {
  17. return id;
  18. }
  19. return null;
  20. };
  21. baidu.g = baidu.G = baidu.dom.g;
  22. baidu.lang = baidu.lang || {};
  23. baidu.lang.isString = function(source) {
  24. return '[object String]' == Object.prototype.toString.call(source);
  25. };
  26. baidu.isString = baidu.lang.isString;
  27. baidu.dom._g = function(id) {
  28. if (baidu.lang.isString(id)) {
  29. return document.getElementById(id);
  30. }
  31. return id;
  32. };
  33. baidu._g = baidu.dom._g;
  34. baidu.dom.getDocument = function(element) {
  35. element = baidu.dom.g(element);
  36. return element.nodeType == 9 ? element : element.ownerDocument || element.document;
  37. };
  38. baidu.browser = baidu.browser || {};
  39. baidu.browser.ie = baidu.ie = /msie (\d+\.\d+)/i.test(navigator.userAgent) ? (document.documentMode || + RegExp['\x241']) : undefined;
  40. baidu.dom.getComputedStyle = function(element, key) {
  41. element = baidu.dom._g(element);
  42. var doc = baidu.dom.getDocument(element),
  43. styles;
  44. if (doc.defaultView && doc.defaultView.getComputedStyle) {
  45. styles = doc.defaultView.getComputedStyle(element, null);
  46. if (styles) {
  47. return styles[key] || styles.getPropertyValue(key);
  48. }
  49. }
  50. return '';
  51. };
  52. baidu.dom._styleFixer = baidu.dom._styleFixer || {};
  53. baidu.dom._styleFilter = baidu.dom._styleFilter || [];
  54. baidu.dom._styleFilter.filter = function(key, value, method) {
  55. for (var i = 0, filters = baidu.dom._styleFilter, filter; filter = filters[i]; i++) {
  56. if (filter = filter[method]) {
  57. value = filter(key, value);
  58. }
  59. }
  60. return value;
  61. };
  62. baidu.string = baidu.string || {};
  63. baidu.string.toCamelCase = function(source) {
  64. if (source.indexOf('-') < 0 && source.indexOf('_') < 0) {
  65. return source;
  66. }
  67. return source.replace(/[-_][^-_]/g, function(match) {
  68. return match.charAt(1).toUpperCase();
  69. });
  70. };
  71. baidu.dom.getStyle = function(element, key) {
  72. var dom = baidu.dom;
  73. element = dom.g(element);
  74. key = baidu.string.toCamelCase(key);
  75. var value = element.style[key] ||
  76. (element.currentStyle ? element.currentStyle[key] : '') ||
  77. dom.getComputedStyle(element, key);
  78. if (!value) {
  79. var fixer = dom._styleFixer[key];
  80. if (fixer) {
  81. value = fixer.get ? fixer.get(element) : baidu.dom.getStyle(element, fixer);
  82. }
  83. }
  84. if (fixer = dom._styleFilter) {
  85. value = fixer.filter(key, value, 'get');
  86. }
  87. return value;
  88. };
  89. baidu.getStyle = baidu.dom.getStyle;
  90. baidu.dom._NAME_ATTRS = (function() {
  91. var result = {
  92. 'cellpadding': 'cellPadding',
  93. 'cellspacing': 'cellSpacing',
  94. 'colspan': 'colSpan',
  95. 'rowspan': 'rowSpan',
  96. 'valign': 'vAlign',
  97. 'usemap': 'useMap',
  98. 'frameborder': 'frameBorder'
  99. };
  100. if (baidu.browser.ie < 8) {
  101. result['for'] = 'htmlFor';
  102. result['class'] = 'className';
  103. } else {
  104. result['htmlFor'] = 'for';
  105. result['className'] = 'class';
  106. }
  107. return result;
  108. })();
  109. baidu.dom.setAttr = function(element, key, value) {
  110. element = baidu.dom.g(element);
  111. if ('style' == key) {
  112. element.style.cssText = value;
  113. } else {
  114. key = baidu.dom._NAME_ATTRS[key] || key;
  115. element.setAttribute(key, value);
  116. }
  117. return element;
  118. };
  119. baidu.setAttr = baidu.dom.setAttr;
  120. baidu.dom.setAttrs = function(element, attributes) {
  121. element = baidu.dom.g(element);
  122. for (var key in attributes) {
  123. baidu.dom.setAttr(element, key, attributes[key]);
  124. }
  125. return element;
  126. };
  127. baidu.setAttrs = baidu.dom.setAttrs;
  128. baidu.dom.create = function(tagName, opt_attributes) {
  129. var el = document.createElement(tagName),
  130. attributes = opt_attributes || {};
  131. return baidu.dom.setAttrs(el, attributes);
  132. };
  133. baidu.object = baidu.object || {};
  134. baidu.extend =
  135. baidu.object.extend = function(target, source) {
  136. for (var p in source) {
  137. if (source.hasOwnProperty(p)) {
  138. target[p] = source[p];
  139. }
  140. }
  141. return target;
  142. };
  143. /**
  144. * @exports LuShu as BMapLib.LuShu
  145. */
  146. var LuShu = function(map, path, opts) {
  147. try {
  148. BMap;
  149. } catch (e) {
  150. throw Error('Baidu Map JS API is not ready yet!');
  151. }
  152. if (!path || path.length < 1) {
  153. return;
  154. }
  155. this._map = map;
  156. this._path = path;
  157. this.i = 0;
  158. this._setTimeoutQuene = [];
  159. this._projection = this._map.getMapType().getProjection();
  160. this._opts = {
  161. icon: null,
  162. speed: 4000,
  163. defaultContent: '',
  164. showInfoWindow: false
  165. };
  166. this._setOptions(opts);
  167. this._rotation = 0;
  168. if (!this._opts.icon instanceof BMap.Icon) {
  169. this._opts.icon = defaultIcon;
  170. }
  171. }
  172. LuShu.prototype._setOptions = function(opts) {
  173. if (!opts) {
  174. return;
  175. }
  176. for (var p in opts) {
  177. if (opts.hasOwnProperty(p)) {
  178. this._opts[p] = opts[p];
  179. }
  180. }
  181. }
  182. LuShu.prototype.start = function() {
  183. var me = this,
  184. len = me._path.length;
  185. this._opts.onstart && this._opts.onstart(me)
  186. if (me.i && me.i < len - 1) {
  187. if (!me._fromPause) {
  188. return;
  189. }else if(!me._fromStop){
  190. me._moveNext(++me.i);
  191. }
  192. }else {
  193. !me._marker && me._addMarker();
  194. me._timeoutFlag = setTimeout(function() {
  195. !me._overlay && me._addInfoWin();
  196. me._moveNext(me.i);
  197. },400);
  198. }
  199. this._fromPause = false;
  200. this._fromStop = false;
  201. },
  202. LuShu.prototype.stop = function() {
  203. this.i = 0;
  204. this._fromStop = true;
  205. clearInterval(this._intervalFlag);
  206. this._clearTimeout();
  207. for (var i = 0, t = this._opts.landmarkPois, len = t.length; i < len; i++) {
  208. t[i].bShow = false;
  209. }
  210. this._opts.onstop && this._opts.onstop(this)
  211. };
  212. LuShu.prototype.pause = function() {
  213. clearInterval(this._intervalFlag);
  214. this._fromPause = true;
  215. this._clearTimeout();
  216. this._opts.onpause && this._opts.onpause(this)
  217. };
  218. LuShu.prototype.hideInfoWindow = function() {
  219. this._opts.showInfoWindow = false;
  220. this._overlay && (this._overlay._div.style.visibility = 'hidden');
  221. };
  222. LuShu.prototype.showInfoWindow = function() {
  223. this._opts.showInfoWindow = true;
  224. this._overlay && (this._overlay._div.style.visibility = 'visible');
  225. };
  226. LuShu.prototype.dispose = function () {
  227. clearInterval(this._intervalFlag);
  228. this._setTimeoutQuene && this._clearTimeout();
  229. if (this._map) {
  230. this._map.removeOverlay(this._overlay);
  231. this._map.removeOverlay(this._marker);
  232. }
  233. };
  234. baidu.object.extend(LuShu.prototype, {
  235. _addMarker: function(callback) {
  236. if (this._marker) {
  237. this.stop();
  238. this._map.removeOverlay(this._marker);
  239. clearTimeout(this._timeoutFlag);
  240. }
  241. this._overlay && this._map.removeOverlay(this._overlay);
  242. var marker = new BMap.Marker(this._path[0]);
  243. this._opts.icon && marker.setIcon(this._opts.icon);
  244. this._map.addOverlay(marker);
  245. marker.setAnimation(BMAP_ANIMATION_DROP);
  246. this._marker = marker;
  247. },
  248. _addInfoWin: function() {
  249. var me = this;
  250. !CustomOverlay.prototype.initialize && initCustomOverlay();
  251. var overlay = new CustomOverlay(me._marker.getPosition(), me._opts.defaultContent);
  252. overlay.setRelatedClass(this);
  253. this._overlay = overlay;
  254. this._map.addOverlay(overlay);
  255. this._opts.showInfoWindow ? this.showInfoWindow() : this.hideInfoWindow()
  256. },
  257. _getMercator: function(poi) {
  258. return this._map.getMapType().getProjection().lngLatToPoint(poi);
  259. },
  260. _getDistance: function(pxA, pxB) {
  261. return Math.sqrt(Math.pow(pxA.x - pxB.x, 2) + Math.pow(pxA.y - pxB.y, 2));
  262. },
  263. _move: function(initPos,targetPos,effect) {
  264. var me = this,
  265. currentCount = 0,
  266. timer = 10,
  267. step = this._opts.speed / (1000 / timer),
  268. init_pos = this._projection.lngLatToPoint(initPos),
  269. target_pos = this._projection.lngLatToPoint(targetPos),
  270. count = Math.round(me._getDistance(init_pos, target_pos) / step);
  271. if (count < 1) {
  272. me._moveNext(++me.i);
  273. return;
  274. }
  275. me._intervalFlag = setInterval(function() {
  276. if (currentCount >= count) {
  277. clearInterval(me._intervalFlag);
  278. if(me.i > me._path.length){
  279. return;
  280. }
  281. me._moveNext(++me.i);
  282. } else {
  283. currentCount++;
  284. var x = effect(init_pos.x, target_pos.x, currentCount, count),
  285. y = effect(init_pos.y, target_pos.y, currentCount, count),
  286. pos = me._projection.pointToLngLat(new BMap.Pixel(x, y));
  287. if(currentCount == 1){
  288. var proPos = null;
  289. if(me.i - 1 >= 0){
  290. proPos = me._path[me.i - 1];
  291. }
  292. if(me._opts.enableRotation == true){
  293. me.setRotation(proPos,initPos,targetPos);
  294. }
  295. if(me._opts.autoView){
  296. if(!me._map.getBounds().containsPoint(pos)){
  297. me._map.setCenter(pos);
  298. }
  299. }
  300. }
  301. me._marker.setPosition(pos);
  302. me._setInfoWin(pos);
  303. }
  304. },timer);
  305. },
  306. setRotation : function(prePos,curPos,targetPos){
  307. var me = this;
  308. var deg = 0;
  309. //start!
  310. curPos = me._map.pointToPixel(curPos);
  311. targetPos = me._map.pointToPixel(targetPos);
  312. if(targetPos.x != curPos.x){
  313. var tan = (targetPos.y - curPos.y)/(targetPos.x - curPos.x),
  314. atan = Math.atan(tan);
  315. deg = atan*360/(2*Math.PI);
  316. //degree correction;
  317. if(targetPos.x < curPos.x){
  318. deg = -deg + 90 + 90;
  319. } else {
  320. deg = -deg;
  321. }
  322. me._marker.setRotation(-deg);
  323. }else {
  324. var disy = targetPos.y- curPos.y ;
  325. var bias = 0;
  326. if(disy > 0)
  327. bias=-1
  328. else
  329. bias = 1
  330. me._marker.setRotation(-bias * 90);
  331. }
  332. return;
  333. },
  334. linePixellength : function(from,to){
  335. return Math.sqrt(Math.abs(from.x- to.x) * Math.abs(from.x- to.x) + Math.abs(from.y- to.y) * Math.abs(from.y- to.y) );
  336. },
  337. pointToPoint : function(from,to ){
  338. return Math.abs(from.x- to.x) * Math.abs(from.x- to.x) + Math.abs(from.y- to.y) * Math.abs(from.y- to.y)
  339. },
  340. _moveNext: function(index) {
  341. var me = this;
  342. if (index < this._path.length - 1) {
  343. me._move(me._path[index], me._path[index + 1], me._tween.linear);
  344. } else {
  345. me.stop()
  346. }
  347. },
  348. _setInfoWin: function(pos) {
  349. var me = this;
  350. me._overlay.setPosition(pos, me._marker.getIcon().size);
  351. var index = me._troughPointIndex(pos);
  352. if (index != -1) {
  353. clearInterval(me._intervalFlag);
  354. me._overlay.setHtml(me._opts.landmarkPois[index].html);
  355. me._overlay.setPosition(pos, me._marker.getIcon().size);
  356. me._pauseForView(index);
  357. }else {
  358. me._overlay.setHtml(me._opts.defaultContent);
  359. }
  360. },
  361. _pauseForView: function(index) {
  362. var me = this;
  363. var t = setTimeout(function() {
  364. me._moveNext(++me.i);
  365. },me._opts.landmarkPois[index].pauseTime * 1000);
  366. me._setTimeoutQuene.push(t);
  367. },
  368. _clearTimeout: function() {
  369. for (var i in this._setTimeoutQuene) {
  370. clearTimeout(this._setTimeoutQuene[i]);
  371. }
  372. this._setTimeoutQuene.length = 0;
  373. },
  374. _tween: {
  375. linear: function(initPos, targetPos, currentCount, count) {
  376. var b = initPos, c = targetPos - initPos, t = currentCount,
  377. d = count;
  378. return c * t / d + b;
  379. }
  380. },
  381. _troughPointIndex: function(markerPoi) {
  382. var t = this._opts.landmarkPois, distance;
  383. for (var i = 0, len = t.length; i < len; i++) {
  384. if (!t[i].bShow) {
  385. distance = this._map.getDistance(new BMap.Point(t[i].lng, t[i].lat), markerPoi);
  386. if (distance < 10) {
  387. t[i].bShow = true;
  388. return i;
  389. }
  390. }
  391. }
  392. return -1;
  393. }
  394. });
  395. function CustomOverlay(point,html) {
  396. this._point = point;
  397. this._html = html;
  398. }
  399. function initCustomOverlay() {
  400. CustomOverlay.prototype = new BMap.Overlay();
  401. CustomOverlay.prototype.initialize = function(map) {
  402. var div = this._div = baidu.dom.create('div', {style: 'border:solid 1px #ccc;width:auto;min-width:50px;text-align:center;position:absolute;background:#fff;color:#000;font-size:12px;border-radius: 10px;padding:5px;white-space: nowrap;'});
  403. div.innerHTML = this._html;
  404. map.getPanes().floatPane.appendChild(div);
  405. this._map = map;
  406. return div;
  407. }
  408. CustomOverlay.prototype.draw = function() {
  409. this.setPosition(this.lushuMain._marker.getPosition(), this.lushuMain._marker.getIcon().size);
  410. }
  411. baidu.object.extend(CustomOverlay.prototype, {
  412. setPosition: function(poi,markerSize) {
  413. var px = this._map.pointToOverlayPixel(poi),
  414. styleW = baidu.dom.getStyle(this._div, 'width'),
  415. styleH = baidu.dom.getStyle(this._div, 'height'),
  416. overlayW = parseInt(this._div.clientWidth || styleW, 10),
  417. overlayH = parseInt(this._div.clientHeight || styleH, 10);
  418. this._div.style.left = px.x - overlayW / 2 + 'px';
  419. this._div.style.bottom = -(px.y - markerSize.height) + 'px';
  420. },
  421. setHtml: function(html) {
  422. this._div.innerHTML = html;
  423. },
  424. setRelatedClass: function(lushuMain) {
  425. this.lushuMain = lushuMain;
  426. }
  427. });
  428. }
  429. return LuShu
  430. });