前言:一直感觉不论OL还是arcgis 这个地图聚类是真的丑,实在让人看不下去,反观leaflet插件的的聚合效果那叫一个好看,个人感觉好看多了去了,那么把这个聚合效果用到OL上面去啊,这个是一个很好玩的事,本篇文章用到了自定义的聚类的扩展图层,感谢@牛老师源代码启发,在此基础上进行进一步的封装。
先来张效果图:
这张照片整的感觉都变形很多。其实一点没变形
一、自定义扩展图层下载(github)
ol.layer.myClusterLayer =function(options){varself =this;self.styleFunc =function(feat){varattribute = feat.get("attribute");varcount = attribute.cluster.length;if(count <1) {varname = attribute.data.name;returnnewol.style.Style({image:newol.style.Icon(/** @type {olx.style.IconOptions} */({anchor: [0.5,60],anchorOrigin:'top-right',anchorXUnits:'fraction',anchorYUnits:'pixels',offsetOrigin:'top-right',offset: [0,1],//偏移量设置scale:0.7,//图标缩放比例opacity:0.75,//透明度src:'data/marker-icon.png'//图标的url})),text:newol.style.Text({text: name,fill:newol.style.Fill({color:'#000000'}),textAlign:"left",offsetX:5,textBaseline:"middle"}) }) }else{var_smallCorlor;var_bigCorlor;if(count <100) {if(count >50) { _smallCorlor ="#f0cd41"; _bigCorlor ="#f5de8b"; }else{ _smallCorlor ="#94d769"; _bigCorlor ="#cde7b1"; } }else{ _smallCorlor ='#f1964d'; _bigCorlor ="#f9bda2"; } count++; count = count.toString();varsmallRadius = count.length *10; smallRadius = smallRadius <10?12: smallRadius ;varbigRadius = smallRadius +5;return[newol.style.Style({image:newol.style.Circle({radius: bigRadius,fill:newol.style.Fill({color: _bigCorlor }) }), }),newol.style.Style({image:newol.style.Circle({radius: smallRadius,fill:newol.style.Fill({color: _smallCorlor }) }),text:newol.style.Text({text: count,fill:newol.style.Fill({color:'#620022'}),textAlign:"center",textBaseline:"middle"}) }), ] }}vardefaults = {map:null,clusterField:"",zooms: [2,4,8,12],distance:256,data: [],style: self.styleFunc,};//将default和options合并self.options = {map: options.map,clusterField: options.clusterField,zooms: (options.zooms.length >0? options.zooms : defaults.zooms),distance: (options.distance >0? options.distance : defaults.distance),data: options.data,style:(options.style!=null?options.style:defaults.style)}self.proj = self.options.map.getView().getProjection();self.vectorSource =newol.source.Vector({features: []});self.vectorLayer =newol.layer.Vector({source: self.vectorSource,style: self.options.style});self.clusterData = [];//判断该点是否聚合self._clusterTest =function(data, dataCluster){var_flag =false;var_cField = self.options.clusterField;if(_cField !="") { _flag = data[_cField] === dataCluster[_cField]; }else{//将地理坐标转换成屏幕坐标,进行距离判断var_dataCoord = self._getCoordinate(data.lon, data.lat), _cdataCoord = self._getCoordinate(dataCluster.lon, dataCluster.lat);var_dataScrCoord = self.options.map.getPixelFromCoordinate(_dataCoord), _cdataScrCoord = self.options.map.getPixelFromCoordinate(_cdataCoord);var_distance =Math.sqrt(Math.pow((_dataScrCoord[0] - _cdataScrCoord[0]),2) +Math.pow((_dataScrCoord[1] - _cdataScrCoord[1]),2) ); _flag = _distance <= self.options.distance; }//如果超过最大的缩放级别,数据全部展示var_zoom = self.options.map.getView().getZoom(), _maxZoom = self.options.zooms[self.options.zooms.length -1];if(_zoom > _maxZoom) _flag =false;return_flag;};//坐标转换self._getCoordinate =function(lon, lat){returnol.proj.transform([parseFloat(lon),parseFloat(lat)],"EPSG:4326", self.proj );};//添加数据到聚合图self._add2CluserData =function(index, data){ self.clusterData[index].cluster.push(data);};self._clusterCreate =function(data){ self.clusterData.push({data: data,cluster: [] });};//展示数据self._showCluster =function(){ self.vectorSource.clear();var_features = [];for(vari =0, len = self.clusterData.length; i < len; i++) {var_cdata = self.clusterData[i];var_coord = self._getCoordinate(_cdata.data.lon, _cdata.data.lat);var_feature =newol.Feature({geometry:newol.geom.Point(_coord),attribute: _cdata });//如果聚合点里面没有数据就显示该点数据if(_cdata.cluster.length ===0) _feature.attr = _feature.data; _features.push(_feature); } self.vectorSource.addFeatures(_features);};self._clusterFeatures =function(){ self.clusterData = [];//可视域处理var_viewExtent = self.options.map.getView().calculateExtent();//声明一个矩形,范围就是屏幕的四至var_viewGeom =newol.geom.Polygon.fromExtent(_viewExtent);for(vari =0, ilen = self.options.data.length; i < ilen; i++) {var_data = self.options.data[i];var_coord = self._getCoordinate(_data.lon, _data.lat);if(_viewGeom.intersectsCoordinate(_coord)) {//当前点是否聚合,默认是falsevar_clustered =false;for(varj =0, jlen = self.clusterData.length; j < jlen; j++) {var_cdata = self.clusterData[j];if(self._clusterTest(_data, _cdata.data)) { self._add2CluserData(j, _data); _clustered =true;break; } }if(!_clustered) { self._clusterCreate(_data); } } } self.vectorSource.clear(); self._showCluster();};self.init =function(){ self._clusterFeatures(); self.options.map.on("moveend",function(){ self._clusterFeatures(); });};self.init();returnself.vectorLayer;};ol.inherits(ol.layer.myClusterLayer, ol.layer.Vector);
下载地址:点我下载
二、demo示例
myClusterLayer图层参数option
map是就当前地图容器
clusterField 该参数是,是否属性聚合,如果赋值仅需要赋属性字段名即可
distance是聚合的距离(屏幕上距离)
data 是数据
style是样式(不填就有默认样式)
{ map:map, clusterField:"", zooms:[12], distance:100, data:result, style:null}
clusterbody,#map{border:0px;margin:0px;padding:0px;width:100%;height:100%;font-size:13px;overflow: hidden; }varmap;functioninit(){varprojection =newol.proj.Projection({code:'EPSG:4326',units:'degrees'});functiongetNavmapLayer(){returnnewol.layer.Tile({source:newol.source.XYZ({url:'http://webrd01.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8'//7,8}),projection: projection }); }varnavlayer = getNavmapLayer(); map =newol.Map({controls: ol.control.defaults({attribution:false}),target:'map',layers: [navlayer],view:newol.View({projection: projection,center: [116.456,40.251],zoom:4}) }); $.get("data/data.json",function(result){varmycluster =newol.layer.myClusterLayer({map: map,clusterField:"",zooms: [12],distance:100,data: result,style:null}); map.addLayer(mycluster); }) }