效果展示

初始化地图
Javascript
<template>
<div id="map" class="map"></div>
</template>
<script>
import Map from "ol/Map.js";
import View from "ol/View.js";
import { centerPoint } from "@/utils/showPage.js";
import { gaodeMapLayer } from "@/utils/MapLayer.js";
import { clusters, clusterCircleStyle, clusterCircles } from "@/utils/cluster";
import { createEmpty, extend, getHeight, getWidth } from "ol/extent.js";
export default {
name: "cluster",
data() {
return {
map: null
};
},
mounted() {
const map = new Map({
layers: [gaodeMapLayer, clusters, clusterCircles],
target: "map",
view: new View({
center: centerPoint,
zoom: 11,
minZoom: 2,
maxZoom: 30,
projection: "EPSG:4326",
rotation: 0,
}),
});
},
};
</script>
<style scoped>
.map {
width: 100%;
height: 900px;
}
</style>
图层详解
-
公共方法和样式
Javascriptfunction gasPointType() { let customPoint = config.CUSTOM_POINT.val, GAS_POINT_TYPE = config.GAS_POINT_TYPE.children; GAS_POINT_TYPE.forEach((item) => { item.type = item.val.typeId.value; }); return [ ...GAS_POINT_TYPE, { type: customPoint.typeId.value, val: customPoint }, ]; } function getICon(properties) { let typeId = properties.typeId || "1", allPoint = gasPointType(); return allPoint.find((i) => i.type == typeId).val; } function clusterMemberStyle(clusterMember) { let properties = clusterMember.getProperties(); let item = getICon(properties); return new Style({ geometry: clusterMember.getGeometry(), image: new Icon({ rotation: 0, src: item.iconUrl.value, anchorXUnits: "fraction", imgSize: [item.width.value, item.height.value], }), }); } function generatePointsCircle(count, clusterCenter, resolution) { const circumference = circleDistanceMultiplier * circleFootSeparation * (2 + count); let legLength = circumference / (Math.PI * 2); const angleStep = (Math.PI * 2) / count; const res = []; let angle; legLength = Math.max(legLength, 35) * resolution; for (let i = 0; i < count; ++i) { angle = circleStartAngle + i * angleStep; res.push([ clusterCenter[0] + legLength * Math.cos(angle), clusterCenter[1] + legLength * Math.sin(angle), ]); } return res; }
-
clusters图层
Javascriptconst vectorSource = new VectorSource({ features: new GeoJSON().readFeatures({ type: devList.type, features: _devList, }), }); const clusterSource = new Cluster({ distance: 35, source: vectorSource, }); } function clusterStyle(feature) { const size = feature.get("features").length; if (size > 1) { return [ new Style({ image: outerCircle, }), new Style({ image: innerCircle, text: new Text({ text: size.toString(), fill: textFill, stroke: textStroke, }), }), ]; } const originalFeature = feature.get("features")[0]; return clusterMemberStyle(originalFeature); } const clusters = new VectorLayer({ source: clusterSource, style: clusterStyle, });
-
clusterCircles图层
Javascriptconst clusterCircles = new VectorLayer({ source: clusterSource, style: clusterCircleStyle, }); function clusterCircleStyle( cluster, resolution, clickFeature, clickResolution ) { if (cluster !== clickFeature || resolution !== clickResolution) { return null; } const clusterMembers = cluster.get("features"); const centerCoordinates = cluster.getGeometry().getCoordinates(); return generatePointsCircle( clusterMembers.length, cluster.getGeometry().getCoordinates(), resolution ).reduce((styles, coordinates, i) => { const point = new Point(coordinates); const line = new LineString([centerCoordinates, coordinates]); styles.unshift( new Style({ geometry: line, stroke: convexHullStroke, }) ); styles.push( clusterMemberStyle( new Feature({ ...clusterMembers[i].getProperties(), geometry: point, }) ) ); return styles; }, []); }
地图pointermove和click
Javascript
map.on("pointermove", (event) => {
clusters.getFeatures(event.pixel).then((features) => {
map.getTargetElement().style.cursor =
features[0] && features[0].get("features").length > 1
? "pointer"
: "";
});
});
map.on("click", (event) => {
clusters.getFeatures(event.pixel).then((features) => {
if (features.length > 0) {
const clusterMembers = features[0].get("features");
if (clusterMembers.length > 1) {
// Calculate the extent of the cluster members.
const extent = createEmpty();
clusterMembers.forEach((feature) =>
extend(extent, feature.getGeometry().getExtent())
);
const view = map.getView();
const resolution = map.getView().getResolution();
if (
view.getZoom() === view.getMaxZoom() ||
(getWidth(extent) < resolution && getHeight(extent) < resolution)
) {
// Show an expanded view of the cluster members.
let clickFeature = features[0];
let clickResolution = resolution;
clusterCircles.setStyle((cluster, resolution) => {
clusterCircleStyle(
cluster,
resolution,
clickFeature,
clickResolution
);
});
} else {
// Zoom to the extent of the cluster members.
view.fit(extent, { duration: 500, padding: [50, 50, 50, 50] });
}
}
}
});
});