Testing clustering with a proxy.

This commit is contained in:
Eric van der Vlist 2023-01-19 21:08:06 +01:00
parent 420d75520c
commit 6f359b2e80
2 changed files with 185 additions and 32 deletions

View File

@ -51,6 +51,7 @@ import style from '../gpx/styles';
import { DepartureBoard } from '@suid/icons-material';
import deTileVectorSource from '../../lib/de-tile-vector-source';
import ClusterableVectorTileSource from '../../lib/ClusterableVectorTileSource';
import clusterableVectorTileSourceProxy from '../../lib/ClusterableVectorTileSourceProxy';
const [getState, setState] = createSignal({
lon: 0,
@ -240,22 +241,11 @@ const Map: Component = () => {
zIndex: Infinity,
});
const clusterableVectorTileSource = new ClusterableVectorTileSource({
url: 'https://geo.dyomedea.com/services/spain/tiles/{z}/{x}/{y}.pbf',
maxZoom: 14,
});
console.log({
caller: 'Map / projections',
vector: vectorLayer.getSource()?.getProjection(),
vectorTile: clusterableVectorTileSource.getProjection(),
});
const vectorTileLayer = new VectorTileLayer({
source: clusterableVectorTileSource,
style: [],
declutter: false,
});
// console.log({
// caller: 'Map / projections',
// vector: vectorLayer.getSource()?.getProjection(),
// vectorTile: clusterableVectorTileSource.getProjection(),
// });
const olMap = new OlMap({
view: new View({
@ -263,7 +253,7 @@ const Map: Component = () => {
zoom: +getState().zoom,
rotation: +getState().rotation,
}),
layers: [tileLayer, vectorLayer, vectorTileLayer],
layers: [tileLayer, vectorLayer],
target: target,
controls: new Collection<Control>([
new Attribution({ collapsible: true }),
@ -376,6 +366,26 @@ const Map: Component = () => {
// }
// });
const vectorTileSource = new VectorTileSource({
url: 'https://geo.dyomedea.com/services/spain/tiles/{z}/{x}/{y}.pbf',
format: new MVT({ featureClass: Feature }),
maxZoom: 14,
});
const vectorTileLayer = new VectorTileLayer({
source: vectorTileSource,
style: [],
declutter: false,
});
const clusterableVectorTileSource =
clusterableVectorTileSourceProxy(vectorTileSource);
clusterableVectorTileSource.init({
featureFilter: (feature: Feature, resolution?: number) =>
feature.get('type') === 'poi',
});
let clusterLayer = new VectorLayer({
// source: vectorTileMirrorSource,
source: new Cluster({
@ -419,6 +429,7 @@ const Map: Component = () => {
olMap.getView().getProjection()
)
),
// point,
features: features,
type: 'cluster',
});
@ -447,25 +458,25 @@ const Map: Component = () => {
// }),
// }),
});
olMap.addLayer(clusterLayer);
olMap.addLayer(vectorTileLayer);
olMap.addLayer(clusterLayer);
setMap(olMap);
console.log({
caller: 'Map / projections',
olMap,
projections: {
map: olMap.getView().getProjection(),
vectorSource: vectorLayer.getSource()?.getProjection(),
clusterSource: clusterLayer.getSource().getProjection(),
clusterSourceSource: clusterLayer
.getSource()
?.getSource()
.getProjection(),
},
});
// console.log({
// caller: 'Map / projections',
// olMap,
// projections: {
// map: olMap.getView().getProjection(),
// vectorSource: vectorLayer.getSource()?.getProjection(),
// clusterSource: clusterLayer.getSource().getProjection(),
// clusterSourceSource: clusterLayer
// .getSource()
// ?.getSource()
// .getProjection(),
// },
// });
});
return (

View File

@ -0,0 +1,142 @@
import { cloneDeep } from 'lodash';
import { Feature } from 'ol';
import { equals, Extent } from 'ol/extent';
import { fromLonLat, Projection } from 'ol/proj';
import VectorTileSource from 'ol/source/VectorTile.js';
const CLUSTER_PROPS = '[cluster props]';
type FeatureFilter = (
feature: Feature,
resolution: number | undefined
) => boolean;
const passAllFeatureFilter = (feature: Feature, resolution?: number) => true;
interface Props {
extent: Extent | null;
resolution?: number;
extentProjected: Extent | null;
featuresSent: boolean;
featureFilter: FeatureFilter;
}
interface Options {
featureFilter?: FeatureFilter;
}
const initialProps = {
extent: null,
extentProjected: null,
featuresSent: false,
featureFilter: passAllFeatureFilter,
};
const getProps = (vectorTileSource: VectorTileSource) =>
vectorTileSource.get(CLUSTER_PROPS) as Props;
const setProps = (vectorTileSource: VectorTileSource, props: Props) =>
vectorTileSource.set(CLUSTER_PROPS, props);
const overloads = {
init: (target: VectorTileSource) => {
return (options?: Options) => {
let props = cloneDeep(initialProps);
if (options) {
props = { ...props, ...options };
}
setProps(target, props);
};
},
loadFeatures: (target: VectorTileSource) => {
return (extent: Extent, resolution: number, projection: Projection) => {
let props = getProps(target);
props.resolution = resolution;
if (props.extent === null || !equals(props.extent, extent)) {
props.extent = extent;
if (target.getProjection() != null) {
props.extentProjected = fromLonLat(
extent.slice(0, 2),
target.getProjection()
).concat(fromLonLat(extent.slice(2), props.projection));
}
}
if (!props.featuresSent) {
target.dispatchEvent('change');
}
props.featuresSent = false;
setProps(target, props);
console.log({
caller: 'clusterableVectorTileSourceProxy',
overload: 'loadFeatures',
extent,
resolution,
projection,
target: target,
props,
});
};
},
getFeatures: (target: VectorTileSource) => {
return () => {
let props = getProps(target);
const result = (
props.extentProjected !== null
? target.getFeaturesInExtent(props.extentProjected)
: []
).filter((feature) => props.featureFilter(feature, props.resolution));
//console.trace();
props.featuresSent = true;
setProps(target, props);
console.log({
caller: 'clusterableVectorTileSourceProxy',
overload: 'getFeatures',
result,
props,
target,
});
return result;
};
},
addEventListener: (target: VectorTileSource) => {
return (type: string, listener: any) => {
console.log({
caller: 'clusterableVectorTileSourceProxy',
overload: 'addEventListener',
type,
listener,
target,
});
target.addEventListener(type, listener);
if (type === 'change') {
target.addEventListener('tileloadend', listener);
}
};
},
};
const clusterableVectorTileSourceProxy = (vectorTileSource: VectorTileSource) =>
new Proxy(vectorTileSource, {
get: (target, prop, receiver) => {
let result;
if (prop in overloads) {
result = overloads[prop as keyof typeof overloads](target);
} else {
result = Reflect.get(target, prop, receiver);
}
// console.log({
// caller: 'clusterableVectorTileSourceProxy',
// trap: 'get',
// target,
// prop,
// receiver,
// result,
// });
return result;
},
});
export default clusterableVectorTileSourceProxy;