• 百度地图js lite api 支持点聚合


    百度地图lite api 是专门为h5 绘制海量点设计的,但是偏偏忽略掉了点聚合的需求,所以需要自己动手,做一次二次改造。

    我们知道点聚合需要引入开源库:

    MarkerClusterer:  http://api.map.baidu.com/library/MarkerClusterer/1.2/src/MarkerClusterer.js

    TextIconOverlay: http://api.map.baidu.com/library/TextIconOverlay/1.2/src/TextIconOverlay.js

    由于是开源库,我们可以直接把代码撸下来保存直接放到自己的业务里使用

    我们在  MarkerClusterer  addMarkers的时候浏览器会报错,

    是因为lite api中的map对象及bounds对象缺乏两个方法:

    map.getDistance  及   bounds.containsPoint

    getDistance方法是计算两个点之间的直线距离,返回数值为米,这个方法网上就有

     1 const EARTH_RADIUS = 6378137.0;
     2 const {PI} = Math;
     3 
     4 function getRad(d){
     5     return d*PI/180.0;
     6 }
     7 
     8 function getDistance(start,end){
     9     let lat1 = +start.lat;
    10     let lat2 = +end.lat;
    11     let lng1 = +start.lng;
    12     let lng2 = +end.lng;
    13     if(lat1==lat2 && lng1 == lng2){
    14         return 0;
    15     }
    16     let f = getRad((lat1 + lat2)/2);
    17     let g = getRad((lat1 - lat2)/2);
    18     let l = getRad((lng1 - lng2)/2);
    19     let sg = Math.sin(g);
    20     let sl = Math.sin(l);
    21     let sf = Math.sin(f);
    22     let s,c,w,r,d,h1,h2;
    23     let a = EARTH_RADIUS;
    24     let fl = 1/298.257;
    25     sg = sg*sg;
    26     sl = sl*sl;
    27     sf = sf*sf;
    28     s = sg*(1-sl) + (1-sf)*sl;
    29     c = (1-sg)*(1-sl) + sf*sl;
    30     w = Math.atan(Math.sqrt(s/c));
    31     r = Math.sqrt(s*c)/w;
    32     d = 2*w*a;
    33     h1 = (3*r -1)/2/c;
    34     h2 = (3*r +1)/2/s;
    35     return d*(1 + fl*(h1*sf*(1-sg) - h2*(1-sf)*sg));
    36 }

    我们把这个方法赋到map对象上

     1 var MarkerClusterer = function (map, options) {
     2     if (!map) {
     3         return;
     4     }
     5     map.getDistance = getDistance;  // 这里
     6     this._map = map;
     7     this._markers = [];
     8     this._clusters = [];
     9 
    10     var opts = options || {};
    11     this._gridSize = opts["gridSize"] || 60;
    12     this._maxZoom = opts["maxZoom"] || 18;
    13     this._minClusterSize = opts["minClusterSize"] || 2;
    14     this._isAverageCenter = false;
    15     if (opts['isAverageCenter'] != undefined) {
    16         this._isAverageCenter = opts['isAverageCenter'];
    17     }
    18     this._styles = opts["styles"] || [];
    19 
    20     var that = this;
    21     this._map.addEventListener("zoomend", function () {
    22         that._redraw();
    23     });
    24 
    25     this._map.addEventListener("moveend", function () {
    26         that._redraw();
    27     });
    28 
    29     var mkrs = opts["markers"];
    30     isArray(mkrs) && this.addMarkers(mkrs);
    31 };

    map对象就补齐了

    containsPoint 是计算点是否在bounds给定的区域中,这个更简单

     1 var getExtendedBounds = function (map, bounds, gridSize) {
     2     bounds = cutBoundsInRange(bounds);
     3     var pixelNE = map.pointToPixel(bounds.getNorthEast());
     4     var pixelSW = map.pointToPixel(bounds.getSouthWest());
     5     pixelNE.x += gridSize;
     6     pixelNE.y -= gridSize;
     7     pixelSW.x -= gridSize;
     8     pixelSW.y += gridSize;
     9     var newNE = map.pixelToPoint(pixelNE);
    10     var newSW = map.pixelToPoint(pixelSW);
    11     let nb =  new BMap.Bounds(newSW, newNE);
    12     // 写在这里
    13     nb.containsPoint = function(point){
    14         var lat = point.lat;
    15         var lng = point.lng;
    16         if(!point || !point.lat || !point.lng){
    17             return false;
    18         } else {
    19             return lat>this._swLat && lat < this._neLat && lng<this._neLng && lng>this._swLng;
    20         }
    21     }
    22     return nb;
    23 };

    至此MarkerClusterer 改造完毕

    然后是改造TextIconOverlay

    由于lite api 返回的MarkerPane

     1 TextIconOverlay.prototype.initialize = function (map) {
     2             this._map = map;
     3 
     4             this._domElement = document.createElement('div');
     5             this._updateCss();
     6             this._updateText();
     7             this._updatePosition();
     8 
     9             this._bind();
    10  // 将markerMouseTarget 替换成markerPane
    11 this._map.getPanes().markerPane.appendChild(this._domElement);
    12             return this._domElement;
    13         };

    这样就可以了

  • 相关阅读:
    关于pem与ppk格式的密钥的相互转换
    关于linux免密登录的配置及ssh客户端基于私钥文件的登录
    关于yum update和yum upgrade的区别
    Golang文件操作整理
    整理那些用于基本生存的shell命令
    Docker command line 学习笔记
    关于fork
    tips for using shortcuts
    chapter2
    使用MarkDown的编辑器
  • 原文地址:https://www.cnblogs.com/JhoneLee/p/9925113.html
Copyright © 2020-2023  润新知