Skip to content

Commit 947a275

Browse files
committed
Add clusterization
1 parent 8005992 commit 947a275

File tree

1 file changed

+49
-24
lines changed

1 file changed

+49
-24
lines changed

src/map.js

Lines changed: 49 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,38 @@
11
const photosSource = new ol.source.Vector();
2+
const clusterSource = new ol.source.Cluster({
3+
distance: 30,
4+
minDistance: 10,
5+
source: photosSource
6+
});
27

38
// Configure map layers: bottom - OpenStreetMap map, top - photo thumbnails
49
const layerOSM = new ol.layer.Tile({
510
source: new ol.source.OSM()
611
});
7-
const layerThumbs = new ol.layer.Vector({
8-
source: photosSource,
9-
style: thumbStyle,
12+
const layerClusters = new ol.layer.Vector({
13+
source: clusterSource,
14+
style: clusterStyle,
1015
updateWhileAnimating: true,
1116
updateWhileInteracting: true,
1217
});
1318
const map = new ol.Map({
1419
target: 'map',
15-
layers: [layerOSM, layerThumbs],
20+
layers: [layerOSM, layerClusters],
1621
view: new ol.View({
1722
center: ol.proj.transform([20, 47], 'EPSG:4326', 'EPSG:3857'),
18-
zoom: 4
23+
zoom: 4,
24+
maxZoom: 20
1925
})
2026
});
2127

22-
// Configure thumbnail selector
23-
const thumbSelector = new ol.interaction.Select({
24-
layers: [layerThumbs],
25-
style: selectedStyle
26-
});
27-
map.addInteraction(thumbSelector);
28-
29-
const selectedFeatures = thumbSelector.getFeatures();
30-
selectedFeatures.on('add', event => {
31-
const feature = event.target.item(0);
32-
const details = photoDetails(feature);
33-
document.getElementById('photo-details').innerHTML = details;
34-
});
35-
selectedFeatures.on('remove', () => {
36-
document.getElementById('photo-details').innerHTML = '';
28+
map.on('click', event => {
29+
layerClusters.getFeatures(event.pixel).then(clickedFeatures => {
30+
if (!clickedFeatures.length) return;
31+
const features = clickedFeatures[0].get('features');
32+
// Show photo details
33+
const details = features.map(f => photoDetails(f));
34+
document.getElementById('photo-details').innerHTML = details.join();
35+
});
3736
});
3837

3938
const handleMapDataLoaded = items => {
@@ -55,6 +54,15 @@ handleMapDataLoaded([{
5554
"make": "Sony Ericsson",
5655
"model": "MK16i",
5756
"date": "2017-06-02 19:30:08"
57+
},{
58+
"name": "dsc03425_1211.jpg",
59+
"path": "https://annimon.com/albums/files/dsc03425_1211.jpg",
60+
"preview": "https://annimon.com/albums/screens/dsc03425_1211.jpg.250.png",
61+
"lat": 47.8,
62+
"lon": 37.27,
63+
"make": "Sony Ericsson",
64+
"model": "C510i",
65+
"date": "2011-06-03 16:55:23"
5866
}]);
5967

6068
// -- photo details --
@@ -71,6 +79,27 @@ function photoDetails(feature) {
7179
// -- icon styles --
7280
const cache = {};
7381

82+
function clusterStyle(feature, resolution) {
83+
const features = feature.get('features');
84+
const size = features.length;
85+
const key = `cl-${size}`;
86+
if (!cache[key]) {
87+
cache[key] = new ol.style.Style({
88+
zIndex: 110,
89+
image: new ol.style.Circle({
90+
radius: 12,
91+
stroke: new ol.style.Stroke({color: '#8AFFD9'}),
92+
fill: new ol.style.Fill({color: '#229D75'})
93+
}),
94+
text: new ol.style.Text({
95+
text: `${size}`,
96+
fill: new ol.style.Fill({color: '#fff'})
97+
}),
98+
});
99+
}
100+
return cache[key];
101+
}
102+
74103
function photoStyle(feature, scale) {
75104
const url = feature.get('url');
76105
const key = `${scale}${url}`;
@@ -86,10 +115,6 @@ function thumbStyle(feature, resolution) {
86115
return [photoStyle(feature, clamp(0.2, 0.1 / resolution, 1))];
87116
}
88117

89-
function selectedStyle(feature, resolution) {
90-
return [photoStyle(feature, clamp(0.4, 0.14 / resolution, 1.2))];
91-
}
92-
93118
function clamp(min, value, max) {
94119
if (value < min) return min;
95120
if (value > max) return max;

0 commit comments

Comments
 (0)