百度地图点聚合MarkerClusterer,性能优化

前端之家收集整理的这篇文章主要介绍了百度地图点聚合MarkerClusterer,性能优化前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

参考文献:http://www.cnblogs.com/lightnull/p/6184867.html

百度的点聚合算法 是基于方格和距离的聚合算法,即开始的时候地图上没有任何已知的聚合点,然后遍历所有的点,去计算点的外包正方形(由gridSize指定),若此点的外包正方形与现有的聚合点的外包正方形不相交,则新建聚合点,若相交就把该点加到该聚合点,效果如下图,为了便于查看,我们特地把外包正方形画了出来。

好的,笔者开始了作死之旅。上面笔者只是生成了50个随机点。

接下来要测试下1000个点,嗯有点小卡,但是还能操作,

2000个点,我的天,这shit一样的卡顿是什么鬼!!

5000个点,好的,完美,动也动不了 简直漂亮

10000个点,页面无响应。。。。。。。

----------我只是一条漂亮的分割线----------

百度地图 点聚合的部分源码:

  1. /**
  2.      * 根据所给定的标记,创建聚合点
  3.      * @return 无返回值
  4.      */
  5.     MarkerClusterer.prototype._createClusters = function(){
  6.         var mapBounds = this._map.getBounds();
  7.         var extendedBounds = getExtendedBounds(this._map,mapBounds,this._gridSize);
  8.         for(var i = 0,marker; marker = this._markers[i]; i++){
  9.             if(!marker.isInCluster && extendedBounds.containsPoint(marker.getPosition()) ){ 
  10.                 this._addToClosestCluster(marker);
  11.             }
  12.         }   
  13.     };
  14.     /**
  15.      * 根据标记的位置,把它添加到最近的聚合中
  16.      * @param {BMap.Marker} marker 要进行聚合的单个标记
  17.      *
  18.      * @return 无返回值。
  19.      */
  20.     MarkerClusterer.prototype._addToClosestCluster = function (marker){
  21.         var distance = 4000000;
  22.         var clusterToAddTo = null;
  23.         var position = marker.getPosition();
  24.         for(var i = 0,cluster; cluster = this._clusters[i]; i++){
  25.             var center = cluster.getCenter();
  26.             if(center){
  27.                 var d = this._map.getDistance(center,marker.getPosition());
  28.                 if(d < distance){
  29.                     distance = d;
  30.                     clusterToAddTo = cluster;
  31.                 }
  32.             }
  33.         }
  34.     
  35.         if (clusterToAddTo && clusterToAddTo.isMarkerInClusterBounds(marker)){
  36.             clusterToAddTo.addMarker(marker);
  37.         } else {
  38.             var cluster = new Cluster(this);
  39.             cluster.addMarker(marker);            
  40.             this._clusters.push(cluster);
  41.         }    
  42.     };

以上两个方法就是前文所述的算法的具体实现,

先排除所有不在可视范围的点,然后通过比较marker点和聚合点的距离,拿到距离最近的聚合点,判断marker点是否在聚合点的外包正方形内;

这一段是正常算法需要没啥问题,看起来问题只能出在 cluster.addMarker(marker);

  1. if(this.isMarkerInCluster(marker)){
  2. return false;
  3. }//也可用marker.isInCluster判断,外面判断OK,这里基本不会命中
  4. if (!this._center){
  5. this._center = marker.getPosition();
  6. this.updateGridBounds();//
  7. } else {
  8. if(this._isAverageCenter){
  9. var l = this._markers.length + 1;
  10. var lat = (this._center.lat * (l - 1) + marker.getPosition().lat) / l;
  11. var lng = (this._center.lng * (l - 1) + marker.getPosition().lng) / l;
  12. this._center = new BMap.Point(lng,lat);
  13. this.updateGridBounds();
  14. }//计算新的Center
  15. }
  16. marker.isInCluster = true;
  17. this._markers.push(marker);
  18. var len = this._markers.length; if(len < this._minClusterSize ){ this._map.addOverlay(marker); //this.updateClusterMarker();
  19. return true; } else if (len === this._minClusterSize) { for (var i = 0; i < len; i++) { this._markers[i].getMap() && this._map.removeOverlay(this._markers[i]); } } this._map.addOverlay(this._clusterMarker); this._isReal = true; this.updateClusterMarker(); return true;
  20. };

果然不出所料,在addMarker() 方法内不停的去进行dom操作,不卡才怪。为什么度娘就不等计算结束后,在去一次操作完呢,

于是笔者把标黄的代码抽离了出来给cluster类加了一个render方法, 然后在MarkerClusterer.createClusters方法最后加了一个遍历所有聚合点的操作,代码如下:

  1. Cluster.prototype.render = function(){
  2. var len = this._markers.length;
  3. if (len < this._minClusterSize) {
  4. for (var i = 0; i < len; i++) {
  5. this._map.addOverlay(this._markers[i]);
  6. }
  7. } else {
  8. this._map.addOverlay(this._clusterMarker);
  9. this._isReal = true;
  10. this.updateClusterMarker();
  11. }
  12. }
  1. var len = this._markers.length;
  2. for (var i = 0; i < len; i++) {
  3. if(this._clusters[i]){
  4. this._clusters[i].render();
  5. }
  6. }

测试比较一下吧!

Maker数量 原版点聚合js(时间:毫秒 ms) 优化后点聚合js(时间:毫秒 ms)
100 95 88 60 65
1000 588 612 146 133
10000 5840 5772 439 424
30000 19987 20170 1334 1457

新手上路!!

贴上修改后的代码

  1. /**
  2. * @fileoverview MarkerClusterer标记聚合器用来解决加载大量点要素到地图上产生覆盖现象的问题,并提高性能
  3. * 主入口类是<a href="symbols/BMapLib.MarkerClusterer.html">MarkerClusterer</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. * 获取一个扩展的视图范围,把上下左右都扩大一样的像素值。
  16. * @param {Map} map BMap.Map的实例化对象
  17. * @param {BMap.Bounds} bounds BMap.Bounds的实例化对象
  18. * @param {Number} gridSize 要扩大的像素值
  19. *
  20. * @return {BMap.Bounds} 返回扩大后的视图范围。
  21. */
  22. var getExtendedBounds = function(map,bounds,gridSize){
  23. bounds = cutBoundsInRange(bounds);
  24. var pixelNE = map.pointToPixel(bounds.getNorthEast());
  25. var pixelSW = map.pointToPixel(bounds.getSouthWest());
  26. pixelNE.x += gridSize;
  27. pixelNE.y -= gridSize;
  28. pixelSW.x -= gridSize;
  29. pixelSW.y += gridSize;
  30. var newNE = map.pixelToPoint(pixelNE);
  31. var newSW = map.pixelToPoint(pixelSW);
  32. return new BMap.Bounds(newSW,newNE);
  33. };
  34. /**
  35. * 按照百度地图支持的世界范围对bounds进行边界处理
  36. * @param {BMap.Bounds} bounds BMap.Bounds的实例化对象
  37. *
  38. * @return {BMap.Bounds} 返回不越界的视图范围
  39. */
  40. var cutBoundsInRange = function (bounds) {
  41. var maxX = getRange(bounds.getNorthEast().lng,-180,180);
  42. var minX = getRange(bounds.getSouthWest().lng,180);
  43. var maxY = getRange(bounds.getNorthEast().lat,-74,74);
  44. var minY = getRange(bounds.getSouthWest().lat,74);
  45. return new BMap.Bounds(new BMap.Point(minX,minY),new BMap.Point(maxX,maxY));
  46. };
  47. /**
  48. * 对单个值进行边界处理。
  49. * @param {Number} i 要处理的数值
  50. * @param {Number} min 下边界值
  51. * @param {Number} max 上边界值
  52. *
  53. * @return {Number} 返回不越界的数值
  54. */
  55. var getRange = function (i,mix,max) {
  56. mix && (i = Math.max(i,mix));
  57. max && (i = Math.min(i,max));
  58. return i;
  59. };
  60. /**
  61. * 判断给定的对象是否为数组
  62. * @param {Object} source 要测试的对象
  63. *
  64. * @return {Boolean} 如果是数组返回true,否则返回false
  65. */
  66. var isArray = function (source) {
  67. return '[object Array]' === Object.prototype.toString.call(source);
  68. };
  69. /**
  70. * 返回item在source中的索引位置
  71. * @param {Object} item 要测试的对象
  72. * @param {Array} source 数组
  73. *
  74. * @return {Number} 如果在数组内,返回索引,否则返回-1
  75. */
  76. var indexOf = function(item,source){
  77. var index = -1;
  78. if(isArray(source)){
  79. if (source.indexOf) {
  80. index = source.indexOf(item);
  81. } else {
  82. for (var i = 0,m; m = source[i]; i++) {
  83. if (m === item) {
  84. index = i;
  85. break;
  86. }
  87. }
  88. }
  89. }
  90. return index;
  91. };
  92. /**
  93. *@exports MarkerClusterer as BMapLib.MarkerClusterer
  94. */
  95. var MarkerClusterer =
  96. /**
  97. * MarkerClusterer
  98. * @class 用来解决加载大量点要素到地图上产生覆盖现象的问题,并提高性能
  99. * @constructor
  100. * @param {Map} map 地图的一个实例。
  101. * @param {Json Object} options 可选参数,可选项包括:<br />
  102. * markers {Array<Marker>} 要聚合的标记数组<br />
  103. * girdSize {Number} 聚合计算时网格的像素大小,默认60<br />
  104. * maxZoom {Number} 最大的聚合级别,大于该级别就不进行相应的聚合<br />
  105. * minClusterSize {Number} 最小的聚合数量,小于该数量的不能成为一个聚合,默认为2<br />
  106. * isAverangeCenter {Boolean} 聚合点的落脚位置是否是所有聚合在内点的平均值,默认为否,落脚在聚合内的第一个点<br />
  107. * styles {Array<IconStyle>} 自定义聚合后的图标风格,请参考TextIconOverlay类<br />
  108. */
  109. BMapLib.MarkerClusterer = function(map,options){
  110. if (!map){
  111. return;
  112. }
  113. this._map = map;
  114. this._markers = [];
  115. this._clusters = [];
  116. var opts = options || {};
  117. this._gridSize = opts["gridSize"] || 60;
  118. this._maxZoom = opts["maxZoom"] || 18;
  119. this._minClusterSize = opts["minClusterSize"] || 2;
  120. this._isAverageCenter = false;
  121. if (opts['isAverageCenter'] != undefined) {
  122. this._isAverageCenter = opts['isAverageCenter'];
  123. }
  124. this._styles = opts["styles"] || [];
  125. var that = this;
  126. this._map.addEventListener("zoomend",function(){
  127. that._redraw();
  128. });
  129. this._map.addEventListener("moveend",function(){
  130. that._redraw();
  131. });
  132. var mkrs = opts["markers"];
  133. isArray(mkrs) && this.addMarkers(mkrs);
  134. };
  135. /**
  136. * 添加要聚合的标记数组。
  137. * @param {Array<Marker>} markers 要聚合的标记数组
  138. *
  139. * @return 无返回值。
  140. */
  141. MarkerClusterer.prototype.addMarkers = function(markers){
  142. for(var i = 0,len = markers.length; i <len ; i++){
  143. this._pushMarkerTo(markers[i]);
  144. }
  145. this._createClusters();
  146. };
  147. /**
  148. * 把一个标记添加到要聚合的标记数组中
  149. * @param {BMap.Marker} marker 要添加标记
  150. *
  151. * @return 无返回值。
  152. */
  153. MarkerClusterer.prototype._pushMarkerTo = function(marker){
  154. var index = indexOf(marker,this._markers);
  155. if(index === -1){
  156. marker.isInCluster = false;
  157. this._markers.push(marker);//Marker拖放后enableDragging不做变化,忽略
  158. }
  159. };
  160. /**
  161. * 添加一个聚合的标记
  162. * @param {BMap.Marker} marker 要聚合的单个标记
  163. * @return 无返回值。
  164. */
  165. MarkerClusterer.prototype.addMarker = function(marker) {
  166. this._pushMarkerTo(marker);
  167. this._createClusters();
  168. };
  169. /**
  170. * 根据所给定的标记,创建聚合点,并且遍历所有聚合点
  171. * @return 无返回值
  172. */
  173. MarkerClusterer.prototype._createClusters = function(){
  174. var mapBounds = this._map.getBounds();
  175. var extendedBounds = getExtendedBounds(this._map,marker; marker = this._markers[i]; i++){
  176. if(!marker.isInCluster && extendedBounds.containsPoint(marker.getPosition()) ){
  177. this._addToClosestCluster(marker);
  178. }
  179. }
  180.  
  181. var len = this._markers.length;
  182. for (var i = 0; i < len; i++) {
  183. if(this._clusters[i]){
  184. this._clusters[i].render();
  185. }
  186. }
  187. };
  188. /**
  189. * 根据标记的位置,把它添加到最近的聚合中
  190. * @param {BMap.Marker} marker 要进行聚合的单个标记
  191. *
  192. * @return 无返回值。
  193. */
  194. MarkerClusterer.prototype._addToClosestCluster = function (marker){
  195. var distance = 4000000;
  196. var clusterToAddTo = null;
  197. var position = marker.getPosition();
  198. for(var i = 0,marker.getPosition());
  199. if(d < distance){
  200. distance = d;
  201. clusterToAddTo = cluster;
  202. }
  203. }
  204. }
  205. if (clusterToAddTo && clusterToAddTo.isMarkerInClusterBounds(marker)){
  206. clusterToAddTo.addMarker(marker);
  207. } else {
  208. var cluster = new Cluster(this);
  209. cluster.addMarker(marker);
  210. this._clusters.push(cluster);
  211. }
  212. };
  213. /**
  214. * 清除上一次的聚合的结果
  215. * @return 无返回值。
  216. */
  217. MarkerClusterer.prototype._clearLastClusters = function(){
  218. for(var i = 0,cluster; cluster = this._clusters[i]; i++){
  219. cluster.remove();
  220. }
  221. this._clusters = [];//置空Cluster数组
  222. this._removeMarkersFromCluster();//把Marker的cluster标记设为false
  223. };
  224. /**
  225. * 清除某个聚合中的所有标记
  226. * @return 无返回值
  227. */
  228. MarkerClusterer.prototype._removeMarkersFromCluster = function(){
  229. for(var i = 0,marker; marker = this._markers[i]; i++){
  230. marker.isInCluster = false;
  231. }
  232. };
  233. /**
  234. * 把所有的标记从地图上清除
  235. * @return 无返回值
  236. */
  237. MarkerClusterer.prototype._removeMarkersFromMap = function(){
  238. for(var i = 0,marker; marker = this._markers[i]; i++){
  239. marker.isInCluster = false;
  240. tmplabel = marker.getLabel();
  241. this._map.removeOverlay(marker);
  242. marker.setLabel(tmplabel);
  243. }
  244. };
  245. /**
  246. * 删除单个标记
  247. * @param {BMap.Marker} marker 需要被删除的marker
  248. *
  249. * @return {Boolean} 删除成功返回true,否则返回false
  250. */
  251. MarkerClusterer.prototype._removeMarker = function(marker) {
  252. var index = indexOf(marker,this._markers);
  253. if (index === -1) {
  254. return false;
  255. }
  256. tmplabel = marker.getLabel();
  257. this._map.removeOverlay(marker);
  258. marker.setLabel(tmplabel);
  259. this._markers.splice(index,1);
  260. return true;
  261. };
  262. /**
  263. * 删除单个标记
  264. * @param {BMap.Marker} marker 需要被删除的marker
  265. *
  266. * @return {Boolean} 删除成功返回true,否则返回false
  267. */
  268. MarkerClusterer.prototype.removeMarker = function(marker) {
  269. var success = this._removeMarker(marker);
  270. if (success) {
  271. this._clearLastClusters();
  272. this._createClusters();
  273. }
  274. return success;
  275. };
  276. /**
  277. * 删除一组标记
  278. * @param {Array<BMap.Marker>} markers 需要被删除的marker数组
  279. *
  280. * @return {Boolean} 删除成功返回true,否则返回false
  281. */
  282. MarkerClusterer.prototype.removeMarkers = function(markers) {
  283. var success = false;
  284. for (var i = 0; i < markers.length; i++) {
  285. var r = this._removeMarker(markers[i]);
  286. success = success || r;
  287. }
  288. if (success) {
  289. this._clearLastClusters();
  290. this._createClusters();
  291. }
  292. return success;
  293. };
  294. /**
  295. * 从地图上彻底清除所有的标记
  296. * @return 无返回值
  297. */
  298. MarkerClusterer.prototype.clearMarkers = function() {
  299. this._clearLastClusters();
  300. this._removeMarkersFromMap();
  301. this._markers = [];
  302. };
  303. /**
  304. * 重新生成,比如改变了属性
  305. * @return 无返回值
  306. */
  307. MarkerClusterer.prototype._redraw = function () {
  308. this._clearLastClusters();
  309. this._createClusters();
  310. };
  311. /**
  312. * 获取网格大小
  313. * @return {Number} 网格大小
  314. */
  315. MarkerClusterer.prototype.getGridSize = function() {
  316. return this._gridSize;
  317. };
  318. /**
  319. * 设置网格大小
  320. * @param {Number} size 网格大小
  321. * @return 无返回值
  322. */
  323. MarkerClusterer.prototype.setGridSize = function(size) {
  324. this._gridSize = size;
  325. this._redraw();
  326. };
  327. /**
  328. * 获取聚合的最大缩放级别。
  329. * @return {Number} 聚合的最大缩放级别。
  330. */
  331. MarkerClusterer.prototype.getMaxZoom = function() {
  332. return this._maxZoom;
  333. };
  334. /**
  335. * 设置聚合的最大缩放级别
  336. * @param {Number} maxZoom 聚合的最大缩放级别
  337. * @return 无返回值
  338. */
  339. MarkerClusterer.prototype.setMaxZoom = function(maxZoom) {
  340. this._maxZoom = maxZoom;
  341. this._redraw();
  342. };
  343. /**
  344. * 获取聚合的样式风格集合
  345. * @return {Array<IconStyle>} 聚合的样式风格集合
  346. */
  347. MarkerClusterer.prototype.getStyles = function() {
  348. return this._styles;
  349. };
  350. /**
  351. * 设置聚合的样式风格集合
  352. * @param {Array<IconStyle>} styles 样式风格数组
  353. * @return 无返回值
  354. */
  355. MarkerClusterer.prototype.setStyles = function(styles) {
  356. this._styles = styles;
  357. this._redraw();
  358. };
  359. /**
  360. * 获取单个聚合的最小数量
  361. * @return {Number} 单个聚合的最小数量
  362. */
  363. MarkerClusterer.prototype.getMinClusterSize = function() {
  364. return this._minClusterSize;
  365. };
  366. /**
  367. * 设置单个聚合的最小数量
  368. * @param {Number} size 单个聚合的最小数量
  369. * @return 无返回值。
  370. */
  371. MarkerClusterer.prototype.setMinClusterSize = function(size) {
  372. this._minClusterSize = size;
  373. this._redraw();
  374. };
  375. /**
  376. * 获取单个聚合的落脚点是否是聚合内所有标记的平均中心。
  377. * @return {Boolean} true或false。
  378. */
  379. MarkerClusterer.prototype.isAverageCenter = function() {
  380. return this._isAverageCenter;
  381. };
  382. /**
  383. * 获取聚合的Map实例。
  384. * @return {Map} Map的示例。
  385. */
  386. MarkerClusterer.prototype.getMap = function() {
  387. return this._map;
  388. };
  389. /**
  390. * 获取所有的标记数组。
  391. * @return {Array<Marker>} 标记数组。
  392. */
  393. MarkerClusterer.prototype.getMarkers = function() {
  394. return this._markers;
  395. };
  396. /**
  397. * 获取聚合的总数量
  398. * @return {Number} 聚合的总数量
  399. */
  400. MarkerClusterer.prototype.getClustersCount = function() {
  401. var count = 0;
  402. for(var i = 0,cluster; cluster = this._clusters[i]; i++){
  403. cluster.isReal() && count++;
  404. }
  405. return count;
  406. };
  407. /**
  408. * @ignore
  409. * Cluster
  410. * @class 表示一个聚合对象,该聚合,包含有N个标记,这N个标记组成的范围,并有予以显示在Map上的TextIconOverlay等。
  411. * @constructor
  412. * @param {MarkerClusterer} markerClusterer 一个标记聚合器示例。
  413. */
  414. function Cluster(markerClusterer){
  415. this._markerClusterer = markerClusterer;
  416. this._map = markerClusterer.getMap();
  417. this._minClusterSize = markerClusterer.getMinClusterSize();
  418. this._isAverageCenter = markerClusterer.isAverageCenter();
  419. this._center = null;//落脚位置
  420. this._markers = [];//这个Cluster中所包含的markers
  421. this._gridBounds = null;//以中心点为准,向四边扩大gridSize个像素的范围,也即网格范围
  422. this._isReal = false; //真的是个聚合
  423. this._clusterMarker = new BMapLib.TextIconOverlay(this._center,this._markers.length,{"styles":this._markerClusterer.getStyles()});
  424. //this._map.addOverlay(this._clusterMarker);
  425. }
  426. /**
  427. * 向该聚合添加一个标记
  428. * @param {Marker} marker 要添加标记
  429. * @return 无返回值。
  430. */
  431. Cluster.prototype.addMarker = function(marker){
  432. if(this.isMarkerInCluster(marker)){
  433. return false;
  434. }//也可用marker.isInCluster判断,外面判断OK,这里基本不会命中
  435. if (!this._center){
  436. this._center = marker.getPosition();
  437. this.updateGridBounds();//
  438. } else {
  439. if(this._isAverageCenter){
  440. var l = this._markers.length + 1;
  441. var lat = (this._center.lat * (l - 1) + marker.getPosition().lat) / l;
  442. var lng = (this._center.lng * (l - 1) + marker.getPosition().lng) / l;
  443. this._center = new BMap.Point(lng,lat);
  444. this.updateGridBounds();
  445. }//计算新的Center
  446. }
  447. marker.isInCluster = true;
  448. this._markers.push(marker);
  449. };
  450. /**
  451. * 进行dom操作
  452. * @return 无返回值
  453. */
  454. Cluster.prototype.render = function(){
  455. var len = this._markers.length;
  456. if (len < this._minClusterSize) {
  457. for (var i = 0; i < len; i++) {
  458. this._map.addOverlay(this._markers[i]);
  459. }
  460. } else {
  461. this._map.addOverlay(this._clusterMarker);
  462. this._isReal = true;
  463. this.updateClusterMarker();
  464. }
  465. }
  466.  
  467. /**
  468. * 判断一个标记是否在该聚合中。
  469. * @param {Marker} marker 要判断的标记
  470. * @return {Boolean} true或false。
  471. */
  472. Cluster.prototype.isMarkerInCluster= function(marker){
  473. if (this._markers.indexOf) {
  474. return this._markers.indexOf(marker) != -1;
  475. } else {
  476. for (var i = 0,m; m = this._markers[i]; i++) {
  477. if (m === marker) {
  478. return true;
  479. }
  480. }
  481. }
  482. return false;
  483. };
  484. /**
  485. * 判断一个标记是否在该聚合网格范围中。
  486. * @param {Marker} marker 要判断的标记
  487. * @return {Boolean} true或false。
  488. */
  489. Cluster.prototype.isMarkerInClusterBounds = function(marker) {
  490. return this._gridBounds.containsPoint(marker.getPosition());
  491. };
  492. Cluster.prototype.isReal = function(marker) {
  493. return this._isReal;
  494. };
  495. /**
  496. * 更新该聚合的网格范围。
  497. * @return 无返回值。
  498. */
  499. Cluster.prototype.updateGridBounds = function() {
  500. var bounds = new BMap.Bounds(this._center,this._center);
  501. this._gridBounds = getExtendedBounds(this._map,this._markerClusterer.getGridSize());
  502. };
  503. /**
  504. * 更新该聚合的显示样式,也即TextIconOverlay。
  505. * @return 无返回值。
  506. */
  507. Cluster.prototype.updateClusterMarker = function () {
  508. if (this._map.getZoom() > this._markerClusterer.getMaxZoom()) {
  509. this._clusterMarker && this._map.removeOverlay(this._clusterMarker);
  510. for (var i = 0,marker; marker = this._markers[i]; i++) {
  511. this._map.addOverlay(marker);
  512. }
  513. return;
  514. }
  515. if (this._markers.length < this._minClusterSize) {
  516. this._clusterMarker.hide();
  517. return;
  518. }
  519. this._clusterMarker.setPosition(this._center);
  520. this._clusterMarker.setText(this._markers.length);
  521. var thatMap = this._map;
  522. var thatBounds = this.getBounds();
  523. this._clusterMarker.addEventListener("click",function(event){
  524. thatMap.setViewport(thatBounds);
  525. });
  526. };
  527. /**
  528. * 删除该聚合。
  529. * @return 无返回值。
  530. */
  531. Cluster.prototype.remove = function(){
  532. for (var i = 0,m; m = this._markers[i]; i++) {
  533. tmplabel = this._markers[i].getLabel();
  534. this._markers[i].getMap() && this._map.removeOverlay(this._markers[i])
  535. this._markers[i].setLabel(tmplabel)
  536. }//清除散的标记
  537. this._map.removeOverlay(this._clusterMarker);
  538. this._markers.length = 0;
  539. delete this._markers;
  540. }
  541. /**
  542. * 获取该聚合所包含的所有标记的最小外接矩形的范围。
  543. * @return {BMap.Bounds} 计算出的范围。
  544. */
  545. Cluster.prototype.getBounds = function() {
  546. var bounds = new BMap.Bounds(this._center,this._center);
  547. for (var i = 0,marker; marker = this._markers[i]; i++) {
  548. bounds.extend(marker.getPosition());
  549. }
  550. return bounds;
  551. };
  552. /**
  553. * 获取该聚合的落脚点。
  554. * @return {BMap.Point} 该聚合的落脚点。
  555. */
  556. Cluster.prototype.getCenter = function() {
  557. return this._center;
  558. };
  559. })();

猜你在找的设计模式相关文章