点聚合

<script type="text/javascript" src="//api.map.baidu.com/api?v=3.0&ak=xxxx"></script>
<script type="text/javascript" src="//api.map.baidu.com/library/TextIconOverlay/1.2/src/TextIconOverlay_min.js"></script>
<script type="text/javascript" src="//api.map.baidu.com/library/MarkerClusterer/1.2/src/MarkerClusterer_min.js"></script>
var map = new BMap.Map('map');
map.centerAndZoom(new BMap.Point(116.404, 39.915), 5);
map.enableScrollWheelZoom();// 随机生成markers经纬度
var MAX = 20;
var markers = [];
var pt = null;
var i = 0;
for (; i < MAX; i++) {pt = new BMap.Point(Math.random() * 40 + 85, Math.random() * 30 + 21);var myIcon = new BMap.Icon('/images/default.png', new BMap.Size(48, 48));markers.push(new BMap.Marker(pt, { icon: myIcon }));
}//最简单的用法,生成一个marker数组,然后调用markerClusterer类即可。
var markerClusterer = new BMapLib.MarkerClusterer(map, { markers: markers });


点聚合弊端及解决方案

点聚合数量超过1w时,会有卡顿现象

解决方案:用以下代码代替 MarkerClusterer_min.js

/*** @fileoverview MarkerClusterer标记聚合器用来解决加载大量点要素到地图上产生覆盖现象的问题,并提高性能。* 主入口类是<a href="symbols/BMapLib.MarkerClusterer.html">MarkerClusterer</a>,* 基于Baidu Map API 1.2。** @author Baidu Map Api Group* @version 1.2*//*** @namespace BMap的所有library类均放在BMapLib命名空间下*/
var BMapLib = (window.BMapLib = BMapLib || {});
(function () {/*** 获取一个扩展的视图范围,把上下左右都扩大一样的像素值。* @param {Map} map BMap.Map的实例化对象* @param {BMap.Bounds} bounds BMap.Bounds的实例化对象* @param {Number} gridSize 要扩大的像素值** @return {BMap.Bounds} 返回扩大后的视图范围。*/var getExtendedBounds = function (map, bounds, gridSize) {bounds = cutBoundsInRange(bounds);var pixelNE = map.pointToPixel(bounds.getNorthEast());var pixelSW = map.pointToPixel(bounds.getSouthWest());pixelNE.x += gridSize;pixelNE.y -= gridSize;pixelSW.x -= gridSize;pixelSW.y += gridSize;var newNE = map.pixelToPoint(pixelNE);var newSW = map.pixelToPoint(pixelSW);return new BMap.Bounds(newSW, newNE);};/*** 按照百度地图支持的世界范围对bounds进行边界处理* @param {BMap.Bounds} bounds BMap.Bounds的实例化对象** @return {BMap.Bounds} 返回不越界的视图范围*/var cutBoundsInRange = function (bounds) {var maxX = getRange(bounds.getNorthEast().lng, -180, 180);var minX = getRange(bounds.getSouthWest().lng, -180, 180);var maxY = getRange(bounds.getNorthEast().lat, -74, 74);var minY = getRange(bounds.getSouthWest().lat, -74, 74);return new BMap.Bounds(new BMap.Point(minX, minY), new BMap.Point(maxX, maxY));};/*** 对单个值进行边界处理。* @param {Number} i 要处理的数值* @param {Number} min 下边界值* @param {Number} max 上边界值** @return {Number} 返回不越界的数值*/var getRange = function (i, mix, max) {mix && (i = Math.max(i, mix));max && (i = Math.min(i, max));return i;};/*** 判断给定的对象是否为数组* @param {Object} source 要测试的对象** @return {Boolean} 如果是数组返回true,否则返回false*/var isArray = function (source) {return '[object Array]' === Object.prototype.toString.call(source);};/*** 返回item在source中的索引位置* @param {Object} item 要测试的对象* @param {Array} source 数组** @return {Number} 如果在数组内,返回索引,否则返回-1*/var indexOf = function (item, source) {var index = -1;if (isArray(source)) {if (source.indexOf) {index = source.indexOf(item);} else {for (var i = 0, m; (m = source[i]); i++) {if (m === item) {index = i;break;}}}}return index;};/***@exports MarkerClusterer as BMapLib.MarkerClusterer*/var MarkerClusterer =/*** MarkerClusterer* @class 用来解决加载大量点要素到地图上产生覆盖现象的问题,并提高性能* @constructor* @param {Map} map 地图的一个实例。* @param {Json Object} options 可选参数,可选项包括:<br />*    markers {Array<Marker>} 要聚合的标记数组<br />*    girdSize {Number} 聚合计算时网格的像素大小,默认60<br />*    maxZoom {Number} 最大的聚合级别,大于该级别就不进行相应的聚合<br />*    minClusterSize {Number} 最小的聚合数量,小于该数量的不能成为一个聚合,默认为2<br />*    isAverangeCenter {Boolean} 聚合点的落脚位置是否是所有聚合在内点的平均值,默认为否,落脚在聚合内的第一个点<br />*    styles {Array<IconStyle>} 自定义聚合后的图标风格,请参考TextIconOverlay类<br />*/(BMapLib.MarkerClusterer = function (map, options) {if (!map) {return;}this._map = map;this._markers = [];this._clusters = [];var opts = options || {};this._gridSize = opts['gridSize'] || 60;this._maxZoom = opts['maxZoom'] || 18;this._minClusterSize = opts['minClusterSize'] || 2;this._isAverageCenter = false;if (opts['isAverageCenter'] != undefined) {this._isAverageCenter = opts['isAverageCenter'];}this._styles = opts['styles'] || [];var that = this;this._map.addEventListener('zoomend', function () {that._redraw();});this._map.addEventListener('moveend', function () {that._redraw();});var mkrs = opts['markers'];isArray(mkrs) && this.addMarkers(mkrs);});/*** 添加要聚合的标记数组。* @param {Array<Marker>} markers 要聚合的标记数组** @return 无返回值。*/MarkerClusterer.prototype.addMarkers = function (markers) {for (var i = 0, len = markers.length; i < len; i++) {this._pushMarkerTo(markers[i]);}this._createClusters();};/*** 把一个标记添加到要聚合的标记数组中* @param {BMap.Marker} marker 要添加的标记** @return 无返回值。*/MarkerClusterer.prototype._pushMarkerTo = function (marker) {var index = indexOf(marker, this._markers);if (index === -1) {marker.isInCluster = false;this._markers.push(marker); //Marker拖放后enableDragging不做变化,忽略}};/*** 添加一个聚合的标记。* @param {BMap.Marker} marker 要聚合的单个标记。* @return 无返回值。*/MarkerClusterer.prototype.addMarker = function (marker) {this._pushMarkerTo(marker);this._createClusters();};/*** 根据所给定的标记,创建聚合点,并且遍历所有聚合点* @return 无返回值*/MarkerClusterer.prototype._createClusters = function () {var mapBounds = this._map.getBounds();var extendedBounds = getExtendedBounds(this._map, mapBounds, this._gridSize);for (var i = 0, marker; (marker = this._markers[i]); i++) {if (!marker.isInCluster && extendedBounds.containsPoint(marker.getPosition())) {this._addToClosestCluster(marker);}}var len = this._markers.length;for (var i = 0; i < len; i++) {if (this._clusters[i]) {this._clusters[i].render();}}};/*** 根据标记的位置,把它添加到最近的聚合中* @param {BMap.Marker} marker 要进行聚合的单个标记** @return 无返回值。*/MarkerClusterer.prototype._addToClosestCluster = function (marker) {var distance = 4000000;var clusterToAddTo = null;var position = marker.getPosition();for (var i = 0, cluster; (cluster = this._clusters[i]); i++) {var center = cluster.getCenter();if (center) {var d = this._map.getDistance(center, marker.getPosition());if (d < distance) {distance = d;clusterToAddTo = cluster;}}}if (clusterToAddTo && clusterToAddTo.isMarkerInClusterBounds(marker)) {clusterToAddTo.addMarker(marker);} else {var cluster = new Cluster(this);cluster.addMarker(marker);this._clusters.push(cluster);}};/*** 清除上一次的聚合的结果* @return 无返回值。*/MarkerClusterer.prototype._clearLastClusters = function () {for (var i = 0, cluster; (cluster = this._clusters[i]); i++) {cluster.remove();}this._clusters = []; //置空Cluster数组this._removeMarkersFromCluster(); //把Marker的cluster标记设为false};/*** 清除某个聚合中的所有标记* @return 无返回值*/MarkerClusterer.prototype._removeMarkersFromCluster = function () {for (var i = 0, marker; (marker = this._markers[i]); i++) {marker.isInCluster = false;}};/*** 把所有的标记从地图上清除* @return 无返回值*/MarkerClusterer.prototype._removeMarkersFromMap = function () {for (var i = 0, marker; (marker = this._markers[i]); i++) {marker.isInCluster = false;tmplabel = marker.getLabel();this._map.removeOverlay(marker);marker.setLabel(tmplabel);}};/*** 删除单个标记* @param {BMap.Marker} marker 需要被删除的marker** @return {Boolean} 删除成功返回true,否则返回false*/MarkerClusterer.prototype._removeMarker = function (marker) {var index = indexOf(marker, this._markers);if (index === -1) {return false;}tmplabel = marker.getLabel();this._map.removeOverlay(marker);marker.setLabel(tmplabel);this._markers.splice(index, 1);return true;};/*** 删除单个标记* @param {BMap.Marker} marker 需要被删除的marker** @return {Boolean} 删除成功返回true,否则返回false*/MarkerClusterer.prototype.removeMarker = function (marker) {var success = this._removeMarker(marker);if (success) {this._clearLastClusters();this._createClusters();}return success;};/*** 删除一组标记* @param {Array<BMap.Marker>} markers 需要被删除的marker数组** @return {Boolean} 删除成功返回true,否则返回false*/MarkerClusterer.prototype.removeMarkers = function (markers) {var success = false;for (var i = 0; i < markers.length; i++) {var r = this._removeMarker(markers[i]);success = success || r;}if (success) {this._clearLastClusters();this._createClusters();}return success;};/*** 从地图上彻底清除所有的标记* @return 无返回值*/MarkerClusterer.prototype.clearMarkers = function () {this._clearLastClusters();this._removeMarkersFromMap();this._markers = [];};/*** 重新生成,比如改变了属性等* @return 无返回值*/MarkerClusterer.prototype._redraw = function () {this._clearLastClusters();this._createClusters();};/*** 获取网格大小* @return {Number} 网格大小*/MarkerClusterer.prototype.getGridSize = function () {return this._gridSize;};/*** 设置网格大小* @param {Number} size 网格大小* @return 无返回值*/MarkerClusterer.prototype.setGridSize = function (size) {this._gridSize = size;this._redraw();};/*** 获取聚合的最大缩放级别。* @return {Number} 聚合的最大缩放级别。*/MarkerClusterer.prototype.getMaxZoom = function () {return this._maxZoom;};/*** 设置聚合的最大缩放级别* @param {Number} maxZoom 聚合的最大缩放级别* @return 无返回值*/MarkerClusterer.prototype.setMaxZoom = function (maxZoom) {this._maxZoom = maxZoom;this._redraw();};/*** 获取聚合的样式风格集合* @return {Array<IconStyle>} 聚合的样式风格集合*/MarkerClusterer.prototype.getStyles = function () {return this._styles;};/*** 设置聚合的样式风格集合* @param {Array<IconStyle>} styles 样式风格数组* @return 无返回值*/MarkerClusterer.prototype.setStyles = function (styles) {this._styles = styles;this._redraw();};/*** 获取单个聚合的最小数量。* @return {Number} 单个聚合的最小数量。*/MarkerClusterer.prototype.getMinClusterSize = function () {return this._minClusterSize;};/*** 设置单个聚合的最小数量。* @param {Number} size 单个聚合的最小数量。* @return 无返回值。*/MarkerClusterer.prototype.setMinClusterSize = function (size) {this._minClusterSize = size;this._redraw();};/*** 获取单个聚合的落脚点是否是聚合内所有标记的平均中心。* @return {Boolean} true或false。*/MarkerClusterer.prototype.isAverageCenter = function () {return this._isAverageCenter;};/*** 获取聚合的Map实例。* @return {Map} Map的示例。*/MarkerClusterer.prototype.getMap = function () {return this._map;};/*** 获取所有的标记数组。* @return {Array<Marker>} 标记数组。*/MarkerClusterer.prototype.getMarkers = function () {return this._markers;};/*** 获取聚合的总数量。* @return {Number} 聚合的总数量。*/MarkerClusterer.prototype.getClustersCount = function () {var count = 0;for (var i = 0, cluster; (cluster = this._clusters[i]); i++) {cluster.isReal() && count++;}return count;};/*** @ignore* Cluster* @class 表示一个聚合对象,该聚合,包含有N个标记,这N个标记组成的范围,并有予以显示在Map上的TextIconOverlay等。* @constructor* @param {MarkerClusterer} markerClusterer 一个标记聚合器示例。*/function Cluster(markerClusterer) {this._markerClusterer = markerClusterer;this._map = markerClusterer.getMap();this._minClusterSize = markerClusterer.getMinClusterSize();this._isAverageCenter = markerClusterer.isAverageCenter();this._center = null; //落脚位置this._markers = []; //这个Cluster中所包含的markersthis._gridBounds = null; //以中心点为准,向四边扩大gridSize个像素的范围,也即网格范围this._isReal = false; //真的是个聚合this._clusterMarker = new BMapLib.TextIconOverlay(this._center, this._markers.length, { styles: this._markerClusterer.getStyles() });//this._map.addOverlay(this._clusterMarker);}/*** 向该聚合添加一个标记。* @param {Marker} marker 要添加的标记。* @return 无返回值。*/Cluster.prototype.addMarker = function (marker) {if (this.isMarkerInCluster(marker)) {return false;} //也可用marker.isInCluster判断,外面判断OK,这里基本不会命中if (!this._center) {this._center = marker.getPosition();this.updateGridBounds(); //} else {if (this._isAverageCenter) {var l = this._markers.length + 1;var lat = (this._center.lat * (l - 1) + marker.getPosition().lat) / l;var lng = (this._center.lng * (l - 1) + marker.getPosition().lng) / l;this._center = new BMap.Point(lng, lat);this.updateGridBounds();} //计算新的Center}marker.isInCluster = true;this._markers.push(marker);};/*** 进行dom操作* @return 无返回值*/Cluster.prototype.render = function () {var len = this._markers.length;if (len < this._minClusterSize) {for (var i = 0; i < len; i++) {this._map.addOverlay(this._markers[i]);}} else {this._map.addOverlay(this._clusterMarker);this._isReal = true;this.updateClusterMarker();}};/*** 判断一个标记是否在该聚合中。* @param {Marker} marker 要判断的标记。* @return {Boolean} true或false。*/Cluster.prototype.isMarkerInCluster = function (marker) {if (this._markers.indexOf) {return this._markers.indexOf(marker) != -1;} else {for (var i = 0, m; (m = this._markers[i]); i++) {if (m === marker) {return true;}}}return false;};/*** 判断一个标记是否在该聚合网格范围中。* @param {Marker} marker 要判断的标记。* @return {Boolean} true或false。*/Cluster.prototype.isMarkerInClusterBounds = function (marker) {return this._gridBounds.containsPoint(marker.getPosition());};Cluster.prototype.isReal = function (marker) {return this._isReal;};/*** 更新该聚合的网格范围。* @return 无返回值。*/Cluster.prototype.updateGridBounds = function () {var bounds = new BMap.Bounds(this._center, this._center);this._gridBounds = getExtendedBounds(this._map, bounds, this._markerClusterer.getGridSize());};/*** 更新该聚合的显示样式,也即TextIconOverlay。* @return 无返回值。*/Cluster.prototype.updateClusterMarker = function () {if (this._map.getZoom() > this._markerClusterer.getMaxZoom()) {this._clusterMarker && this._map.removeOverlay(this._clusterMarker);for (var i = 0, marker; (marker = this._markers[i]); i++) {this._map.addOverlay(marker);}return;}if (this._markers.length < this._minClusterSize) {this._clusterMarker.hide();return;}this._clusterMarker.setPosition(this._center);this._clusterMarker.setText(this._markers.length);var thatMap = this._map;var thatBounds = this.getBounds();this._clusterMarker.addEventListener('click', function (event) {thatMap.setViewport(thatBounds);});};/*** 删除该聚合。* @return 无返回值。*/Cluster.prototype.remove = function () {for (var i = 0, m; (m = this._markers[i]); i++) {tmplabel = this._markers[i].getLabel();this._markers[i].getMap() && this._map.removeOverlay(this._markers[i]);this._markers[i].setLabel(tmplabel);} //清除散的标记点this._map.removeOverlay(this._clusterMarker);this._markers.length = 0;delete this._markers;};/*** 获取该聚合所包含的所有标记的最小外接矩形的范围。* @return {BMap.Bounds} 计算出的范围。*/Cluster.prototype.getBounds = function () {var bounds = new BMap.Bounds(this._center, this._center);for (var i = 0, marker; (marker = this._markers[i]); i++) {bounds.extend(marker.getPosition());}return bounds;};/*** 获取该聚合的落脚点。* @return {BMap.Point} 该聚合的落脚点。*/Cluster.prototype.getCenter = function () {return this._center;};
})();
/*** @description 封装聚合函数* @param markes 是所有点的集合*/function markerClustersPoint(markers) {if (this.markerClusterer) {this.markerClusterer.clearMarkers(); //清除聚合}this.markerClusterer = new this.baiduMapLib.MarkerClusterer(this.map, {markers: markers,minClusterSize: 2, //最小的聚合数量,小于该数量的不能成为一个聚合,默认为2});// console.log('进入聚合函数markerClusterer', this.markerClusterer)// 拿到所有的聚合点//markerClusterer中的 _clusters是一个数组,包含了可视范围的所有聚合点const cluster = this.markerClusterer._clusters;for (let i = 0; i < cluster.length; i++) {//cluster[i]._markers中包含此聚合点的所有marker集合 //marker长度大于2时不进行聚合效果显示//自定义函数内容,可进行聚合点数据获取操作 //...... //...... //拿到聚合点中的marker数量,用于数字显示if (cluster[i]._markers.length < 2) continue;}
}

把所有图标写在canvas上,然后把canvas写进地图

解决方案1: 用百度地图mapv插件实现

mapv文档地址:https://mapv.baidu.com/

解决方案2: 用百度地图api实现
参考文章:https://blog.csdn.net/qq_23447231/article/details/117961725

百度地图-图标过多卡顿解决方案相关推荐

  1. 百度地图行政区优化卡顿问题

    百度地图行政区优化卡顿 只筛选一个区域 沿海城市会出现多个区域,比如上海有4个区域,一个是主区域,外加三个岛屿,把三个岛屿排除掉 // 获取行政区的时候有可能会出现多个行政区,只获取最大的行政区域le ...

  2. 解决 百度地图多点聚合卡顿问题

    由于百度地图提供的MarkerClusterer_min.js 比较卡顿 特此提供加速后的MarkerClusterer_min.js 源码如下 /*** @fileoverview MarkerCl ...

  3. 使用vue和高德地图,仿58地图找房pc端,且解决marker过多卡顿

    使用vue和高德地图,仿58地图找房pc端,且解决marker过多卡顿 1.在index.html引入高德地图链接 https://webapi.amap.com/maps?v=1.4.15& ...

  4. Android开发之百度地图定位打卡

    Android开发之百度地图定位打卡 一.效果图 二.下载百度地图SDK 三.代码实现 1.布局文件(activity_main) 2.布局文件(activity_map) 3.在res文件夹下新建m ...

  5. iOS进阶--提高XCode编译速度、Xcode卡顿解决方案

    提升编译链接的速度主要有以下三个方式: 1. 提高XCode编译时使用的线程数 defaults write com.apple.Xcode PBXNumberOfParallelBuildSubta ...

  6. IntelliJ IDEA 运行卡顿解决方案

    IntelliJ IDEA 运行卡顿解决方案 1.开启IntelliJ IDEA缓慢,想要提升启动速度)则打开D:\JetBrains\IntelliJ IDEA 2020.3.2\bin(依据实际安 ...

  7. 拯救者 显卡混合模式卡顿 解决方案

    拯救者Y9000/Y7000系列 混合模式卡顿解决方案 拯救者显卡混合模式卡顿 解决方案 第一步 BIOS 驱动更新 第二步 卸载联想电脑管家以及应用商城 第三步 下载并安装legion zone 控 ...

  8. android百度地图overlay卡顿,百度地图maker过多,导致卡顿的优化

    原文:https://blog.csdn.net/yzyssg1/article/details/73130679 百度地图的API虽然说覆盖物多了可以用聚合,但聚合使用下来,性能并不好 目前解决方案 ...

  9. 关于高德地图2.0卡顿问题的解决方案(chrome设置+显卡设置)

    最近笔者开始接触高德地图,发现了一种情况:不论是项目上还是高德官方,2.0版本均存在自定义地图在操作时非常卡顿的现象,而1.4.15版本却仍旧流畅. 项目上存在的"多个接口多个文件调用时阻塞 ...

最新文章

  1. java读取hdfs文件夹_HDFS 读取、写入、遍历文件夹获取文件全路径、append
  2. 图像间距pitch是什么?(linesize、stride)(指图像中的一行图像数据所占的存储空间的长度)
  3. 操作系统(8)-存储系统
  4. ajax struts 返回html,Struts2+ajax 异步请求,向前段返回字符串
  5. 立即修复!微软史上最严重漏洞之一 Netlogon 细节被公开,三秒接管企业网络
  6. Linux下Socket编程的端口问题( Bind error: Address already in use )
  7. 首次出现日访问量突破10000,祝贺
  8. LINUX中信号量的使用
  9. navicat12注册机生成相应注册码
  10. rose oracle双机切换故障,ROSE HA切换节点导致DG失败、恢复
  11. Python精灵模块:走来走去的小猫咪
  12. 《数学之美》读书笔记和知识点总结
  13. 一个简单的java代码,输入当前星期,输出今天是星期几
  14. At least one JAR was scanned for TLDs yet contained no TLDs.问题解决方式
  15. linux连接校园网wifi,Linux/Ubuntu 16.04 使用校园网客户端Dr.com DrClient 有线连网,同时开启WiFi热点...
  16. python爬虫—爬取拉钩网
  17. java实现置顶功能
  18. VLDB2017论文阅读-Cohort Query Processing
  19. pytorch学习笔记(八):PytTorch可视化工具 visdom
  20. Word2Vec解释

热门文章

  1. vue 使用 facebook 分享
  2. 我是吴恩达:人在美国,刚上知乎,先答个「如何系统学习机器学习」
  3. (含代码)基于51单片机的红外遥控(独立按键)舵机开关灯控制
  4. SpringBoot、SpringCloud读取bootstrap.yml或者application.properties配置文件中的参数
  5. ES内部分片处理机制——Segment
  6. 最全unicode编码
  7. ARM-9 4412板、linux-3.14内核、usb转串口pl2303驱动的移植相关问题
  8. 库函数开发与寄存器开发
  9. Android制作的一个通讯录
  10. Android能够获取到唯一的设备ID吗?