OpenLayers實(shí)現(xiàn)點(diǎn)要素圖層的聚合顯示的方法
1、前言
在很多情況下,點(diǎn)要素圖層中的要素?cái)?shù)量可能會(huì)成百上千,這時(shí)候如果不做任何處理直接加載到地圖上不僅會(huì)使用戶視覺體驗(yàn)下降,而且也會(huì)造成地圖界面的卡頓。下面這段代碼創(chuàng)建了1000
個(gè)隨機(jī)點(diǎn)進(jìn)行顯示:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta charset="utf-8" /> <title>OpenLayers</title> <style> html, body, #map { width: 100%; height: 100%; margin: 0; padding: 0; } </style> <link href="libs/ol/ol.css" rel="stylesheet" /> <script src="libs/ol/ol.js"></script> </head> <body> <div id="map"></div> <script> // 隨機(jī)創(chuàng)建1000個(gè)要素 var source = new ol.source.Vector(); for (var i = 1; i <= 200; i++) { var coordinates = [120.00 + Math.random(), 30.00 + Math.random()]; var feature = new ol.Feature(new ol.geom.Point(coordinates)); source.addFeature(feature); } for (var i = 1; i <= 200; i++) { var coordinates = [120.01 + Math.random(), 30.01 + Math.random()]; var feature = new ol.Feature(new ol.geom.Point(coordinates)); source.addFeature(feature); } for (var i = 1; i <= 200; i++) { var coordinates = [120.02 + Math.random(), 30.02 + Math.random()]; var feature = new ol.Feature(new ol.geom.Point(coordinates)); source.addFeature(feature); } for (var i = 1; i <= 200; i++) { var coordinates = [120.03 + Math.random(), 30.03 + Math.random()]; var feature = new ol.Feature(new ol.geom.Point(coordinates)); source.addFeature(feature); } for (var i = 1; i <= 200; i++) { var coordinates = [120.04 + Math.random(), 30.04 + Math.random()]; var feature = new ol.Feature(new ol.geom.Point(coordinates)); source.addFeature(feature); } // 創(chuàng)建圖層 var layer = new ol.layer.Vector({ source: source, style: function (feature, resolution) { var style = new ol.style.Style({ image: new ol.style.Icon({ src: 'img/location.png' }) }) return style; } }); // 創(chuàng)建地圖 var map = new ol.Map({ target: 'map', layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }), layer ], view: new ol.View({ projection: 'EPSG:4326', center: [120, 30], zoom: 10, minZoom: 5, maxZoom: 14 }) }); </script> </body> </html>
運(yùn)行結(jié)果如下圖所示:
這么多點(diǎn)擠在一起,是不是感覺很惡心?一般來說,如果一個(gè)點(diǎn)要素圖層中的點(diǎn)數(shù)量很多,我們就會(huì)采取圖層聚合
的方式對(duì)其進(jìn)行處理。但需要注意:圖層聚合只對(duì)點(diǎn)要素圖層有效,對(duì)線和面圖層無效
。
2、點(diǎn)要素圖層的聚合
在openlayers
中,圖層聚合的一般步驟如下:
- 創(chuàng)建要素
- 創(chuàng)建數(shù)據(jù)源添加要素
- 創(chuàng)建聚合數(shù)據(jù)源,設(shè)置聚合的距離
- 創(chuàng)建圖層,將數(shù)據(jù)源設(shè)置為聚合數(shù)據(jù)源
- 創(chuàng)建地圖,添加聚合圖層
圖層聚合代碼如下:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta charset="utf-8" /> <title>OpenLayers</title> <style> html, body, #map { width: 100%; height: 100%; margin: 0; padding: 0; } </style> <link href="libs/ol/ol.css" rel="stylesheet" /> <script src="libs/ol/ol.js"></script> </head> <body> <div id="map"></div> <script> // 隨機(jī)創(chuàng)建1000個(gè)要素 var source = new ol.source.Vector(); for (var i = 1; i <= 200; i++) { var coordinates = [120.00 + Math.random(), 30.00 + Math.random()]; var feature = new ol.Feature(new ol.geom.Point(coordinates)); source.addFeature(feature); } for (var i = 1; i <= 200; i++) { var coordinates = [120.01 + Math.random(), 30.01 + Math.random()]; var feature = new ol.Feature(new ol.geom.Point(coordinates)); source.addFeature(feature); } for (var i = 1; i <= 200; i++) { var coordinates = [120.02 + Math.random(), 30.02 + Math.random()]; var feature = new ol.Feature(new ol.geom.Point(coordinates)); source.addFeature(feature); } for (var i = 1; i <= 200; i++) { var coordinates = [120.03 + Math.random(), 30.03 + Math.random()]; var feature = new ol.Feature(new ol.geom.Point(coordinates)); source.addFeature(feature); } for (var i = 1; i <= 200; i++) { var coordinates = [120.04 + Math.random(), 30.04 + Math.random()]; var feature = new ol.Feature(new ol.geom.Point(coordinates)); source.addFeature(feature); } // 聚合 var cluster = new ol.source.Cluster({ source: source, distance: 100 }) // 創(chuàng)建圖層 var layer = new ol.layer.Vector({ source: cluster, style: function (feature, resolution) { var size = feature.get('features').length; var style = new ol.style.Style({ image: new ol.style.Circle({ radius: 30, stroke: new ol.style.Stroke({ color: 'white' }), fill: new ol.style.Fill({ color: 'blue' }) }), text: new ol.style.Text({ text: size.toString(), fill: new ol.style.Fill({ color: 'white' }) }) }) return style; } }); // 創(chuàng)建地圖 var map = new ol.Map({ target: 'map', layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }), layer ], view: new ol.View({ projection: 'EPSG:4326', center: [120, 30], zoom: 10, minZoom: 5, maxZoom: 14 }) }); </script> </body> </html>
運(yùn)行結(jié)果如下圖所示:
3、聚合特殊處理一
上面的代碼雖然實(shí)現(xiàn)了點(diǎn)要素圖層的聚合,但其實(shí)存在著一個(gè)問題:地圖縮放層級(jí)最大時(shí)仍然保持著聚合效果
,如下圖所示:
一般來說,當(dāng)某處只有一個(gè)點(diǎn)時(shí)就應(yīng)該取消聚合效果
,這時(shí)候我們就需要在style: function (feature, resolution)
這個(gè)回調(diào)函數(shù)里做文章了,代碼如下:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta charset="utf-8" /> <title>OpenLayers</title> <style> html, body, #map { width: 100%; height: 100%; margin: 0; padding: 0; } </style> <link href="libs/ol/ol.css" rel="stylesheet" /> <script src="libs/ol/ol.js"></script> </head> <body> <div id="map"></div> <script> // 隨機(jī)創(chuàng)建1000個(gè)要素 var source = new ol.source.Vector(); for (var i = 1; i <= 200; i++) { var coordinates = [120.00 + Math.random(), 30.00 + Math.random()]; var feature = new ol.Feature(new ol.geom.Point(coordinates)); source.addFeature(feature); } for (var i = 1; i <= 200; i++) { var coordinates = [120.01 + Math.random(), 30.01 + Math.random()]; var feature = new ol.Feature(new ol.geom.Point(coordinates)); source.addFeature(feature); } for (var i = 1; i <= 200; i++) { var coordinates = [120.02 + Math.random(), 30.02 + Math.random()]; var feature = new ol.Feature(new ol.geom.Point(coordinates)); source.addFeature(feature); } for (var i = 1; i <= 200; i++) { var coordinates = [120.03 + Math.random(), 30.03 + Math.random()]; var feature = new ol.Feature(new ol.geom.Point(coordinates)); source.addFeature(feature); } for (var i = 1; i <= 200; i++) { var coordinates = [120.04 + Math.random(), 30.04 + Math.random()]; var feature = new ol.Feature(new ol.geom.Point(coordinates)); source.addFeature(feature); } // 聚合 var cluster = new ol.source.Cluster({ source: source, distance: 100 }) // 創(chuàng)建圖層 var layer = new ol.layer.Vector({ source: cluster, style: function (feature, resolution) { var size = feature.get('features').length; if (size == 1) { return new ol.style.Style({ image: new ol.style.Icon({ src: 'img/location.png' }) }) } else { return new ol.style.Style({ image: new ol.style.Circle({ radius: 30, stroke: new ol.style.Stroke({ color: 'white' }), fill: new ol.style.Fill({ color: 'blue' }) }), text: new ol.style.Text({ text: size.toString(), fill: new ol.style.Fill({ color: 'white' }) }) }) } } }); // 創(chuàng)建地圖 var map = new ol.Map({ target: 'map', layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }), layer ], view: new ol.View({ projection: 'EPSG:4326', center: [120, 30], zoom: 10, minZoom: 5, maxZoom: 14 }) }); </script> </body> </html>
運(yùn)行結(jié)果如下圖所示:
其實(shí)這個(gè)效果實(shí)現(xiàn)起來很簡單,核心代碼就是:var size = feature.get('features').length;
,如果size>1
,則返回聚合樣式,反之則返回圖片樣式。
4、聚合特殊處理二
在上面的代碼中,我把地圖的最大縮放層級(jí)設(shè)置為14
,這也就導(dǎo)致了一個(gè)問題:當(dāng)?shù)貓D縮放到最大層級(jí)時(shí),還有很多點(diǎn)保持著聚合效果
。有時(shí)候用戶可能會(huì)要求:當(dāng)?shù)貓D縮放到最大層級(jí)時(shí),取消全部聚合效果
。如果要實(shí)現(xiàn)這個(gè)功能,我們就需要對(duì)地圖事件進(jìn)行監(jiān)聽了,代碼如下:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta charset="utf-8" /> <title>OpenLayers</title> <style> html, body, #map { width: 100%; height: 100%; margin: 0; padding: 0; } </style> <link href="libs/ol/ol.css" rel="stylesheet" /> <script src="libs/ol/ol.js"></script> </head> <body> <div id="map"></div> <script> // 隨機(jī)創(chuàng)建1000個(gè)要素 var source = new ol.source.Vector(); for (var i = 1; i <= 200; i++) { var coordinates = [120.00 + Math.random(), 30.00 + Math.random()]; var feature = new ol.Feature(new ol.geom.Point(coordinates)); source.addFeature(feature); } for (var i = 1; i <= 200; i++) { var coordinates = [120.01 + Math.random(), 30.01 + Math.random()]; var feature = new ol.Feature(new ol.geom.Point(coordinates)); source.addFeature(feature); } for (var i = 1; i <= 200; i++) { var coordinates = [120.02 + Math.random(), 30.02 + Math.random()]; var feature = new ol.Feature(new ol.geom.Point(coordinates)); source.addFeature(feature); } for (var i = 1; i <= 200; i++) { var coordinates = [120.03 + Math.random(), 30.03 + Math.random()]; var feature = new ol.Feature(new ol.geom.Point(coordinates)); source.addFeature(feature); } for (var i = 1; i <= 200; i++) { var coordinates = [120.04 + Math.random(), 30.04 + Math.random()]; var feature = new ol.Feature(new ol.geom.Point(coordinates)); source.addFeature(feature); } // 聚合 var cluster = new ol.source.Cluster({ source: source, distance: 100 }) // 創(chuàng)建圖層 var layer = new ol.layer.Vector({ source: cluster, style: function (feature, resolution) { var size = feature.get('features').length; if (size == 1) { return new ol.style.Style({ image: new ol.style.Icon({ src: 'img/location.png' }) }) } else { return new ol.style.Style({ image: new ol.style.Circle({ radius: 30, stroke: new ol.style.Stroke({ color: 'white' }), fill: new ol.style.Fill({ color: 'blue' }) }), text: new ol.style.Text({ text: size.toString(), fill: new ol.style.Fill({ color: 'white' }) }) }) } } }); // 創(chuàng)建地圖 var map = new ol.Map({ target: 'map', layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }), layer ], view: new ol.View({ projection: 'EPSG:4326', center: [120, 30], zoom: 10, minZoom: 5, maxZoom: 14 }) }); // 監(jiān)聽地圖分辨率改變事件 map.getView().on('change:resolution', function (event) { if (map.getView().getZoom() == map.getView().getMaxZoom()) { cluster.setDistance(0); } else { cluster.setDistance(100); } }) </script> </body> </html>
運(yùn)行結(jié)果如下圖所示:
這個(gè)效果的實(shí)現(xiàn)也很簡單,只需要監(jiān)聽當(dāng)前地圖的分辨率變化事件,如果當(dāng)前縮放層級(jí)已經(jīng)是最大層級(jí),則將聚合的距離設(shè)置為0
即可。
5.、結(jié)語
在要素?cái)?shù)量很多的情況下,我們應(yīng)該考慮對(duì)其進(jìn)行聚合處理,這樣不僅提升了用戶的使用感受,而且也可以避免界面卡頓。其實(shí)在上面的代碼中,我對(duì)change:resolution
事件進(jìn)行了監(jiān)聽,你也可以換成另一個(gè)事件——moveend
,代碼如下所示:
map.on('moveend', function (event) { if (map.getView().getZoom() == map.getView().getMaxZoom()) { cluster.setDistance(0); } else { cluster.setDistance(100); } });
對(duì)moveend
事件進(jìn)行監(jiān)聽也可以實(shí)現(xiàn)相同的效果,因?yàn)闊o論是地圖的縮放、平移都會(huì)觸發(fā)該事件。
到此這篇關(guān)于OpenLayers實(shí)現(xiàn)點(diǎn)要素圖層的聚合顯示的方法的文章就介紹到這了,更多相關(guān)OpenLayers 點(diǎn)要素圖層的聚合顯示內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript 中定義函數(shù)用 var foo = function () {} 和 function foo()區(qū)
這篇文章主要介紹了JavaScript 中定義函數(shù)用 var foo = function () {} 和 function foo()區(qū)別介紹,需要的朋友可以參考下2018-03-03JS實(shí)現(xiàn)線性表的順序表示方法示例【經(jīng)典數(shù)據(jù)結(jié)構(gòu)】
這篇文章主要介紹了JS實(shí)現(xiàn)線性表的順序表示方法,簡單分析了線性表的原理并結(jié)合實(shí)例形式給出了線性表的插入與刪除實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-04-04javascript關(guān)于復(fù)選框的實(shí)用腳本代碼
javascript關(guān)于復(fù)選框的實(shí)用腳本代碼...2007-08-08php結(jié)合js實(shí)現(xiàn)多條件組合查詢
這篇文章主要為大家詳細(xì)介紹了php結(jié)合js實(shí)現(xiàn)多條件組合查詢,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05echarts實(shí)現(xiàn)中國地圖下鉆進(jìn)入下一級(jí)(地圖鉆取)
最近在學(xué)習(xí)echarts,今天就來介紹一下echarts實(shí)現(xiàn)中國地圖下鉆進(jìn)入下一級(jí),具有一定的參考價(jià)值,感興趣的可以了解一下2023-08-08javascript移動(dòng)設(shè)備Web開發(fā)中對(duì)touch事件的封裝實(shí)例
這篇文章主要介紹了javascript移動(dòng)設(shè)備Web開發(fā)中對(duì)touch事件的封裝實(shí)例,分別對(duì)tap事件、doubleTap事件、longTap事件、swipe事件做了封裝,需要的朋友可以參考下2014-06-06利用JavaScript編寫Python內(nèi)置函數(shù)查詢工具
Python有豐富的內(nèi)置函數(shù)實(shí)現(xiàn)各種功能,但查詢內(nèi)置函數(shù)時(shí)總是需要百度查,有沒有一個(gè)小工具可以單機(jī)無網(wǎng)絡(luò)查詢Python內(nèi)置函數(shù),方便自己學(xué)習(xí)編寫Python程序呢?本文就來用JavaScript編寫一個(gè)2023-02-02