Vue2+OpenLayers点聚合功能实现(提供Gitee源码)
目录
一、案例截图
二、安装OpenLayers库
三、代码实现
3.1、初始化点位
3.2、初始化VectorSource
3.3、初始化Cluster
3.4、初始化VectorLayer
3.5、完整代码
四、Gitee源码
一、案例截图
一定距离的点(可配置)系统会自动聚合:
二、安装OpenLayers库
npm install ol
三、代码实现
3.1、初始化点位
这里返回一个Features集合,也就是点位集合。
关键代码:
createFeatures() {
const pointList = [
[118.948627, 32.120428],
[118.96233518104327, 32.132747608006014],
[118.958412, 32.119130],
[118.96025438585423, 32.11912102446365],
[118.95747155302206, 32.12247160889601],
[118.96085782572982, 32.122218561916334],
[118.91074424415842, 32.138229548887665],
];
let list = [];
for(let i = 0 ; i < pointList.length ; i++){
let feature = new Feature({
geometry: new Point(pointList[i]),
});
list.push(feature);
}
return list;
},
3.2、初始化VectorSource
VectorSource是一种数据源,专门用于存储和管理矢量图形特征。
功能:它可以存储多个特征(如点、线、多边形),并提供相应的功能用于添加、移除或修改这些特征。features通常是一个特征数组,这些特征被添加到当前的矢量源中。
关键代码:
let features = this.createFeatures();
const source = new VectorSource({
features: features,
});
3.3、初始化Cluster
Cluster是一个用于将相近的特征聚合(分组)的数据源。
功能:通过将特征进行聚合,Cluster 可以减少地图上的标记数量,使得在高密度区域中更易于视觉分析。当多个特征在地图上相互接近(在distance指定的像素范围内)时,它们会被聚合成一个集群,从而提高地图的可读性和交互性。
关键代码:
const clusterSource = new Cluster({
source: source,
distance: 80,
});
3.4、初始化VectorLayer
VectorLayer 是一个图层类,用于在地图上展示矢量数据。它可以包含来自多个源的数据,允许通过不同的样式对其进行可视化。
功能:可以将 vectorLayer 用于配置、渲染和互动特性,例如展示点、线或多边形等。
source属性指定了要在图层中使用的数据源。在这种情况下,它是clusterSource,可以将地图上的点进行聚合,集中显示在一起,提高地图的可读性。
style属性定义了如何绘制图层中显示的特征,可以使用一个函数来动态设置样式。在这里,样式是根据单个特征的聚合大小(集群中的特征数量)来进行配置的。
关键代码:
const vectorLayer = new VectorLayer({
source: clusterSource,
style: (feature) => {
const size = feature.get('features').length;
return new Style({
image: new CircleStyle({
radius: 25,
stroke: new Stroke({
color: '#fff',
}),
fill: new Fill({
color: '#ff3d00',
}),
}),
text: new Text({
font: '25px Arial',
text: size.toString(),
fill: new Fill({
color: '#fff',
}),
}),
});
},
});
map.addLayer(vectorLayer);
3.5、完整代码
<template>
<div id="map-container"></div>
</template>
<script>
import { Map, View } from 'ol';
import { Tile as TileLayer } from 'ol/layer';
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import { Cluster } from 'ol/source';
import Text from 'ol/style/Text'
import CircleStyle from 'ol/style/Circle';
import Fill from 'ol/style/Fill';
import Stroke from 'ol/style/Stroke';
import Point from 'ol/geom/Point';
import Feature from 'ol/Feature';
import {Icon, Style} from "ol/style";
import { get } from 'ol/proj';
import { getWidth, getTopLeft } from 'ol/extent';
import { WMTS } from 'ol/source';
import WMTSTileGrid from 'ol/tilegrid/WMTS';
import { defaults as defaultControls } from 'ol/control';
export const projection = get("EPSG:4326");
const projectionExtent = projection.getExtent();
const size = getWidth(projectionExtent) / 256;
const resolutions = [];
for (let z = 0; z < 19; ++z) {
resolutions[z] = size / Math.pow(2, z);
}
let map;
export default {
data() {
return {
}
},
mounted(){
this.initMap() // 加载矢量底图
},
methods:{
initMap() {
const KEY = '你申请的KEY'
map = new Map({
target: 'map-container',
layers: [
// 底图
new TileLayer({
source: new WMTS({
url: `http://t{0-6}.tianditu.com/vec_c/wmts?tk=${KEY}`,
layer: 'vec', // 矢量底图
matrixSet: 'c', // c: 经纬度投影 w: 球面墨卡托投影
style: "default",
crossOrigin: 'anonymous', // 解决跨域问题 如无该需求可不添加
format: "tiles", //请求的图层格式,这里指定为瓦片格式
wrapX: true, // 允许地图在 X 方向重复(环绕)
tileGrid: new WMTSTileGrid({
origin: getTopLeft(projectionExtent),
resolutions: resolutions,
matrixIds: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15','16','17','18']
})
})
}),
// 标注
new TileLayer({
source: new WMTS({
url: `http://t{0-6}.tianditu.com/cva_c/wmts?tk=${KEY}`,
layer: 'cva', //矢量注记
matrixSet: 'c',
style: "default",
crossOrigin: 'anonymous',
format: "tiles",
wrapX: true,
tileGrid: new WMTSTileGrid({
origin: getTopLeft(projectionExtent),
resolutions: resolutions,
matrixIds: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15','16','17','18']
})
})
})
],
view: new View({
center: [118.958366,32.119577],
projection: projection,
zoom: 13,
maxZoom: 17,
minZoom: 1
}),
//加载控件到地图容器中
controls: defaultControls({
zoom: false,
rotate: false,
attribution: false
})
});
let features = this.createFeatures();
const source = new VectorSource({
features: features,
});
const clusterSource = new Cluster({
source: source,
distance: 80,
});
const vectorLayer = new VectorLayer({
source: clusterSource,
style: (feature) => {
const size = feature.get('features').length;
return new Style({
image: new CircleStyle({
radius: 25,
stroke: new Stroke({
color: '#fff',
}),
fill: new Fill({
color: '#ff3d00',
}),
}),
text: new Text({
font: '25px Arial',
text: size.toString(),
fill: new Fill({
color: '#fff',
}),
}),
});
},
});
map.addLayer(vectorLayer);
},
createFeatures() {
const pointList = [
[118.948627, 32.120428],
[118.96233518104327, 32.132747608006014],
[118.958412, 32.119130],
[118.96025438585423, 32.11912102446365],
[118.95747155302206, 32.12247160889601],
[118.96085782572982, 32.122218561916334],
[118.91074424415842, 32.138229548887665],
];
let list = [];
for(let i = 0 ; i < pointList.length ; i++){
let feature = new Feature({
geometry: new Point(pointList[i]),
});
list.push(feature);
}
return list;
},
}
}
</script>
<style scoped>
#map-container {
width: 100%;
height: 100vh;
}
</style>
四、Gitee源码
地址:Vue2+OpenLayers点聚合功能实现