openlayers6聚合圖(附源碼下載)

前言

以前寫過一篇openlayers4版本的地圖聚合圖文章,可是因爲是封裝一層 js代碼寫的,不少初學者看起來比較有點吃力,因此本篇文章從新寫一篇地圖熱力圖文章,直接基於最新版本openlayers6寫的,純粹html + js + css形式,沒有任何封裝。css

內容概覽

1.基於openlayers6實現地圖聚合圖效果
2.源代碼demo下載
html

效果圖以下:

json

大概實現思路以下:讀取聚合圖模擬數據源json,構造openlayers聚合圖數據源features,而後建立聚合圖圖層(核心數據源類Cluster),設置Cluster的初始化一些參數值,參數詳細說明自行看openlayers官網文檔api。api

  • 部分核心代碼,完整的見源碼demo下載
import {Map, View} from 'ol'; import XYZ from 'ol/source/XYZ'; import {Circle as CircleStyle, Fill, Stroke, Style, Text} from 'ol/style'; import {Heatmap as HeatmapLayer, Tile as TileLayer} from 'ol/layer'; import VectorSource from 'ol/source/Vector'; import VectorLayer from 'ol/layer/Vector'; import Feature from 'ol/Feature'; import Point from 'ol/geom/Point'; import {Cluster} from 'ol/source'; import {createEmpty} from 'ol/extent'; import {extend} from 'ol/extent'; import {getWidth} from 'ol/extent'; import {getHeight} from 'ol/extent'; import Overlay from 'ol/Overlay'; var layer = null;//聚合圖圖層
var isLoad = false; //設置原始樣式
var originalStyle = new Style({ image: new CircleStyle({ radius: 5, stroke: new Stroke({ color: '#fff' }), fill: new Fill({ color: '#3399CC' }) }) }); var container = document.getElementById('popup'); var content = document.getElementById('popup-content'); var closer = document.getElementById('popup-closer'); var overlay = new Overlay({ element: container, autoPan: true, autoPanAnimation: { duration: 250 } }); closer.onclick = function() { overlay.setPosition(undefined); closer.blur(); return false; }; var view = new View({ zoom: 13 }) var map = new Map({ target: 'map', layers: [ new TileLayer({ source: new XYZ({ //url: 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png'
url: 'http://cache1.arcgisonline.cn/arcgis/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}' }) }) ], overlays: [overlay], view: view }); map.on("click", function (e) {//鼠標單擊圖標事件
if (e.dragging) { return; } var feature = map.forEachFeatureAtPixel(e.pixel, function(feature) { return feature; }); if(feature){//點擊查詢的搜索結果要素,彈出氣泡窗口
console.log(feature); if(feature.values_.features[0].values_.weight){ //彈出氣泡窗口
var coordinate = e.coordinate; content.innerHTML = 'weight:'+feature.values_.features[0].values_.weight+'</br>region:'+feature.values_.features[0].values_.region+'</br>name:'+feature.values_.features[0].values_.name; overlay.setPosition(coordinate); } else{ //隱藏氣泡窗口
overlay.setPosition(undefined); closer.blur(); } } else{ //隱藏氣泡窗口
overlay.setPosition(undefined); closer.blur(); } }); //初始化熱力圖
initClusterLayer(qy); //熱力圖勾選監聽事件
$("#clustermapFeatureLayer input").bind("click", function () { if (this.checked) { if(!isLoad){ initClusterLayer(qy); } else{ showClusterLayer(); } } else { hideClusterLayer(); } }) /** * 初始化加載-熱力圖 */
function initClusterLayer(data){ isLoad = true; var num = data.features.length; if (num > 0) { var features = new Array(num); for (var i = 0; i < num; i++) { var geo = data.features[i].geometry; var coordinate = [geo.x, geo.y]; features[i] = new Feature({ geometry: new Point(coordinate), weight: data.features[i].attributes[field_qy], region: data.features[i].attributes[field_region], name: data.features[i].attributes[field_company_na] }); } loadClusterLayer(features,originalStyle); } } /** * 建立聚合圖層 * @method loadClusterLayer * @param features 渲染聚合圖層的要素集 * @param originalStyle圖層的原始樣式style * @return null */
 
function loadClusterLayer(features, originalStyle){ var maxFeatureCount, currentResolution; var textFill = new Fill({ color: '#fff' }); var textStroke = new Stroke({ color: 'rgba(0, 0, 0, 0.6)', width: 3 }); var invisibleFill = new Fill({ color: 'rgba(255, 255, 255, 0.01)' }); var earthquakeFill = new Fill({ color: 'rgba(255, 153, 0, 0.8)' }); var earthquakeStroke = new Stroke({ color: 'rgba(255, 204, 0, 0.2)', width: 1 }); function createEarthquakeStyle(feature, style) { return new Style({ geometry: feature.getGeometry(), image: new CircleStyle({ radius: 5, stroke: new Stroke({ color: '#fff' }), fill: new Fill({ color: '#3399CC' }) }) }); } /* *選中樣式 */
function selectStyleFunction(feature) { var styles = [new Style({ image: new CircleStyle({ radius: feature.get('radius'), fill: invisibleFill }) })]; var originalFeatures = feature.get('features'); var originalFeature; for (var i = originalFeatures.length - 1; i >= 0; --i) { originalFeature = originalFeatures[i]; styles.push(createEarthquakeStyle(originalFeature, originalStyle)); //styles.push(originalstyle);
} return styles; } /* *設置沒有聚合效果的原始樣式 */
function createOriginalStyle(feature) { return new Style({ image: new CircleStyle({ radius: 8, stroke: new Stroke({ color: '#fff' }), fill: new Fill({ color: '#3399CC' }) }) }); } /* *計算每一個聚合點的半徑大小 */
function calculateClusterInfo(resolution) { maxFeatureCount = 0; var features = layer.getSource().getFeatures(); var feature, radius; for (var i = features.length - 1; i >= 0; --i) { feature = features[i]; var originalFeatures = feature.get('features'); var extent = createEmpty(); var j, jj; for (j = 0, jj = originalFeatures.length; j < jj; ++j) { extend(extent, originalFeatures[j].getGeometry().getExtent()); } maxFeatureCount = Math.max(maxFeatureCount, jj); radius = 0.25 * (getWidth(extent) + getHeight(extent)) / resolution; feature.set('radius', radius); } } /* *設置聚合樣式 */
function styleFunction(feature, resolution) { //計算每一個聚合點的半徑大小
if (resolution != currentResolution) { calculateClusterInfo(resolution); currentResolution = resolution; } var style; var size = feature.get('features').length;//每一個點當前的聚合點數
if (size > 1) {//設置聚合效果樣式
style = new Style({ image: new CircleStyle({ radius: feature.get('radius'),//獲取聚合圓圈的半徑大小,聚合的點數越多,圓圈的半徑越大
fill: new Fill({ color: [255, 153, 0, Math.min(0.8, 0.4 + (size / maxFeatureCount))] }) }), text: new Text({ text: size.toString(), fill: textFill, stroke: textStroke }) }); } else {//設置沒有聚合效果的原始樣式
style = originalStyle; } return style; } layer = new VectorLayer({ source: new Cluster({//矢量圖層的數據源爲聚合類型
distance: 40,//聚合距離
source: new VectorSource({//聚合數據來源
features: features }) }), style: styleFunction//聚合樣式
}); //selectStyleFunction = selectStyleFunction;
map.addLayer(layer); //縮放至範圍
map.getView().setCenter([12637973.949997703, 2657176.0178779177]); map.getView().setZoom(10); } function showClusterLayer(){ if (layer) { layer.setVisible(true); //縮放至範圍
map.getView().setCenter([12637973.949997703, 2657176.0178779177]); map.getView().setZoom(10); } } function hideClusterLayer(){ if (layer) { layer.setVisible(false); } }

完整源碼demo在此篇文章尾部下載,感興趣的話,能夠關注一波ide

相關文章
相關標籤/搜索