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

相關文章
相關標籤/搜索