Trying clustering...

This commit is contained in:
Eric van der Vlist 2023-01-17 17:34:36 +01:00
parent 0ef74d94be
commit 370a4fa90c
1 changed files with 95 additions and 16 deletions

View File

@ -17,7 +17,7 @@ import 'ol/ol.css';
import './Map.css'; import './Map.css';
import { Collection, VectorTile } from 'ol'; import { Collection, VectorTile } from 'ol';
import { Point } from 'ol/geom'; import { Point } from 'ol/geom';
import { Style, Icon } from 'ol/style'; import { Style, Icon, Circle, Fill } from 'ol/style';
import GetLocation, { getCurrentLocation } from '../get-location'; import GetLocation, { getCurrentLocation } from '../get-location';
import ShowLocationIcon from '../get-location/ShowLocationIcon.svg'; import ShowLocationIcon from '../get-location/ShowLocationIcon.svg';
import { Back, Forward } from '../back-forward'; import { Back, Forward } from '../back-forward';
@ -32,12 +32,14 @@ import PinchZoom from 'ol/interaction/PinchZoom';
import KeyboardPan from 'ol/interaction/KeyboardPan'; import KeyboardPan from 'ol/interaction/KeyboardPan';
import KeyboardZoom from 'ol/interaction/KeyboardZoom'; import KeyboardZoom from 'ol/interaction/KeyboardZoom';
import MouseWheelZoom from 'ol/interaction/MouseWheelZoom'; import MouseWheelZoom from 'ol/interaction/MouseWheelZoom';
import Cluster from 'ol/source/Cluster.js';
import * as olExtent from 'ol/extent';
import DragZoom from 'ol/interaction/DragZoom'; import DragZoom from 'ol/interaction/DragZoom';
import Infos, { clickHandler } from '../infos'; import Infos, { clickHandler } from '../infos';
import GpxDialog from '../gpx-dialog'; import GpxDialog from '../gpx-dialog';
import GpxRecord from '../gpx-record'; import GpxRecord from '../gpx-record';
import dispatch from '../../workers/dispatcher-main'; import dispatch from '../../workers/dispatcher-main';
import { debounce } from 'lodash'; import { debounce, floor } from 'lodash';
import { AndroidFullScreen } from '@awesome-cordova-plugins/android-full-screen'; import { AndroidFullScreen } from '@awesome-cordova-plugins/android-full-screen';
import Account from '../account'; import Account from '../account';
@ -235,34 +237,25 @@ const Map: Component = () => {
zIndex: Infinity, zIndex: Infinity,
}); });
const vectorTileSource1 = new VectorTileSource({ const vectorTileSource = new VectorTileSource({
format: new MVT({ featureClass: Feature }), format: new MVT({ featureClass: Feature }),
url: 'https://geo.dyomedea.com/services/spain/tiles/{z}/{x}/{y}.pbf', url: 'https://geo.dyomedea.com/services/spain/tiles/{z}/{x}/{y}.pbf',
maxZoom: 14, maxZoom: 14,
}); });
const vectorTileLayer1 = new VectorTileLayer({ const vectorTileLayer = new VectorTileLayer({
source: vectorTileSource1, source: vectorTileSource,
style: style, style: [],
declutter: false, declutter: false,
}); });
const vectorTileSource2 = new VectorTileSource({
format: new MVT(),
url: 'http://localhost:8080/geoserver/gwc/service/tms/1.0.0/dyomedea%3Ahiking_routes@EPSG%3A900913@pbf/{z}/{x}/{-y}.pbf',
});
const vectorTileLayer2 = new VectorTileLayer({
source: vectorTileSource2,
});
const olMap = new OlMap({ const olMap = new OlMap({
view: new View({ view: new View({
center: [+getState().lon, +getState().lat], center: [+getState().lon, +getState().lat],
zoom: +getState().zoom, zoom: +getState().zoom,
rotation: +getState().rotation, rotation: +getState().rotation,
}), }),
layers: [tileLayer, vectorTileLayer1, vectorLayer], layers: [tileLayer, vectorTileLayer, vectorLayer],
target: target, target: target,
controls: new Collection<Control>([ controls: new Collection<Control>([
new Attribution({ collapsible: true }), new Attribution({ collapsible: true }),
@ -285,6 +278,92 @@ const Map: Component = () => {
olMap.on(['moveend'], changeListener); olMap.on(['moveend'], changeListener);
olMap.on(['singleclick'], clickHandler); olMap.on(['singleclick'], clickHandler);
// cf https://stackoverflow.com/questions/55161380/openlayers-cluster-with-mvt-vectortilesource-impossible
const vectorTileMirrorSource = new VectorSource();
let featuresForZ: Feature[] = [];
let viewZ: number = floor(+getState().zoom) - 1;
const vectorMirrorRefresh = () => {
console.log({
caller: 'Map / Cluster / vectorMirrorRefresh',
olMap,
vectorMirrorLayer,
viewZ,
featuresForZ,
});
vectorTileMirrorSource.clear();
if (featuresForZ[viewZ]) {
vectorTileMirrorSource.addFeatures(featuresForZ[viewZ]);
}
};
vectorTileLayer.getSource()?.on('tileloadend', (evt) => {
const z = evt.tile.getTileCoord()[0];
const features = evt.tile.getFeatures();
features.forEach((feature: Feature) => {
feature.setId(undefined);
});
if (!Array.isArray(featuresForZ[z])) {
featuresForZ[z] = [];
}
featuresForZ[z] = featuresForZ[z].concat(features);
if (z === viewZ) {
vectorMirrorRefresh();
}
console.log({
caller: 'Map / Cluster / on tileloadend',
olMap,
z,
viewZ,
features,
vectorMirrorLayer,
featuresForZ,
});
});
olMap.getView().on('change:resolution', function () {
// use VT features from the tile z level corresponding to view resolution
const newZ = vectorTileLayer
.getSource()
.getTileGrid()
.getZForResolution(olMap.getView().getResolution());
console.log({
caller: 'Map / Cluster / on change:resolution',
olMap,
newZ,
viewZ,
vectorMirrorLayer,
featuresForZ,
});
if (newZ !== viewZ) {
viewZ = newZ;
vectorMirrorRefresh();
}
});
let vectorMirrorLayer = new VectorLayer({
source: new Cluster({
source: vectorTileMirrorSource,
geometryFunction: function (feature: Feature) {
// test data is linestrings
return new Point(
olExtent.getCenter(feature.getGeometry().getExtent())
);
},
}),
style,
// style: function (feature) {
// return new Style({
// image: new Circle({
// radius: feature.get('features').length * 5,
// fill: new Fill({ color: 'black' }),
// }),
// });
// },
});
olMap.addLayer(vectorMirrorLayer);
setMap(olMap); setMap(olMap);
}); });