Skip to content

Commit

Permalink
feat (cluster layer): cluster layer added
Browse files Browse the repository at this point in the history
  • Loading branch information
NSUWAL123 committed Oct 10, 2023
1 parent 9982c96 commit a04dc8c
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import { useEffect, useState } from 'react';
import AnimatedCluster from 'ol-ext/layer/AnimatedCluster';
import * as olExtent from 'ol/extent';
import GeoJSON from 'ol/format/GeoJSON';
import Stroke from 'ol/style/Stroke';
import Style from 'ol/style/Style';
import Fill from 'ol/style/Fill';
import { Cluster, OSM as OSMSource } from 'ol/source';
import { Text, Circle, Icon } from 'ol/style';
import VectorSource from 'ol/source/Vector';
import { hexToRgba } from '../../../MapComponent/OpenLayersComponent/helpers/styleUtils';

function setAsyncStyle(style, feature, getIndividualStyle) {
const styleCache = {};
const size = feature?.get('features')?.length;
let stylex = styleCache[size];
if (size === 1) {
const featureProperty = feature?.get('features')[0].getProperties();
stylex = getIndividualStyle(featureProperty);
styleCache[size] = stylex;
return stylex;
} else {
stylex = new Style({
image: new Circle({
radius: 23,
stroke: new Stroke({
color: hexToRgba(style.color, style.opacity || 100),
width: 6,
}),
fill: new Fill({
color: hexToRgba(style.background_color, style.opacity || 100),
width: 40,
}),
}),
text: new Text({
text: size.toString(),
fill: new Fill({
color: '#fff',
}),
font: '16px Arial',
}),
});
styleCache[size] = stylex;
return stylex;
}
}

const ClusterLayer = ({
map,
source: layerSource,
zIndex = 999,
zoomToLayer = true,
visibleOnMap = true,
style,
mapOnClick,
getIndividualStyle,
}) => {
const [vectorLayer, setVectorLayer] = useState(null);
useEffect(() => () => map && vectorLayer && map.removeLayer(vectorLayer), [map, vectorLayer]);

useEffect(() => {
if (!map || !layerSource || !layerSource.features) return;
const sourceOSM = new OSMSource();
const vectorSource = new VectorSource({
features: new GeoJSON().readFeatures(layerSource, {
defaultDataProjection: 'EPSG:3857',
featureProjection: sourceOSM.getProjection(),
}),
});

const clusterSource = new Cluster({
distance: parseInt(50, 10),
source: vectorSource,
});

const animatedClusterLayer = new AnimatedCluster({
source: clusterSource,
animationDuration: 700,
distance: 40,
style: (feature) => setAsyncStyle(style, feature, getIndividualStyle),
});

setVectorLayer(animatedClusterLayer);
}, [map, layerSource]);

useEffect(() => {
if (map && vectorLayer) {
vectorLayer.setZIndex(zIndex);
}
}, [map, vectorLayer, zIndex]);

useEffect(() => {
if (map && vectorLayer && zoomToLayer) {
setTimeout(() => {
const features = vectorLayer.getSource().getFeatures();
const extent = olExtent.createEmpty();
features.forEach((feat) =>
feat.values_?.features.forEach((feature) => olExtent.extend(extent, feature.getGeometry().getExtent())),
);
map.getView().fit(extent, {
padding: [50, 50, 50, 50],
});
}, 300);
}
}, [map, vectorLayer, zoomToLayer]);

useEffect(() => {
if (!map) return;
map.on('singleclick', (evt) => {
let area_no_9_extent = null;
map.forEachFeatureAtPixel(
evt.pixel,
(featurex) => {
area_no_9_extent = featurex.getGeometry().getExtent();
return featurex;
},
true,
);
if (area_no_9_extent) {
map.getView().fit(area_no_9_extent, {
duration: 1000,
padding: [50, 50, 50, 50],
// maxZoom: 11,
});
}
});

return () => {
map.un('singleclick', () => {});
};
}, [map]);

useEffect(() => {
if (!map) return;

map.on('singleclick', (evt) => {
const features = map.getFeaturesAtPixel(evt.pixel);
if (features.length > 0) {
const featureProperties = features[0].getProperties();
const feature = featureProperties.features[0].getProperties();
if (featureProperties.features.length === 1) {
mapOnClick(feature);
} else {
return;
}
}
});

return () => {
map.un('singleclick', () => {});
};
}, [map]);

useEffect(() => {
if (!map || !vectorLayer) return;
if (visibleOnMap) {
map.addLayer(vectorLayer);
} else {
map.removeLayer(vectorLayer);
}
}, [map, vectorLayer, visibleOnMap]);

useEffect(() => () => map && map.removeLayer(vectorLayer), [map, vectorLayer]);

return null;
};

export default ClusterLayer;
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { default as VectorTileLayer } from './VectorTileLayer';

export { default as VectorLayer } from './VectorLayer';
export { default as ClusterLayer } from './ClusterLayer';

0 comments on commit a04dc8c

Please sign in to comment.