Testing clustering with a proxy.
This commit is contained in:
parent
420d75520c
commit
6f359b2e80
|
@ -51,6 +51,7 @@ import style from '../gpx/styles';
|
||||||
import { DepartureBoard } from '@suid/icons-material';
|
import { DepartureBoard } from '@suid/icons-material';
|
||||||
import deTileVectorSource from '../../lib/de-tile-vector-source';
|
import deTileVectorSource from '../../lib/de-tile-vector-source';
|
||||||
import ClusterableVectorTileSource from '../../lib/ClusterableVectorTileSource';
|
import ClusterableVectorTileSource from '../../lib/ClusterableVectorTileSource';
|
||||||
|
import clusterableVectorTileSourceProxy from '../../lib/ClusterableVectorTileSourceProxy';
|
||||||
|
|
||||||
const [getState, setState] = createSignal({
|
const [getState, setState] = createSignal({
|
||||||
lon: 0,
|
lon: 0,
|
||||||
|
@ -240,22 +241,11 @@ const Map: Component = () => {
|
||||||
zIndex: Infinity,
|
zIndex: Infinity,
|
||||||
});
|
});
|
||||||
|
|
||||||
const clusterableVectorTileSource = new ClusterableVectorTileSource({
|
// console.log({
|
||||||
url: 'https://geo.dyomedea.com/services/spain/tiles/{z}/{x}/{y}.pbf',
|
// caller: 'Map / projections',
|
||||||
maxZoom: 14,
|
// vector: vectorLayer.getSource()?.getProjection(),
|
||||||
});
|
// vectorTile: clusterableVectorTileSource.getProjection(),
|
||||||
|
// });
|
||||||
console.log({
|
|
||||||
caller: 'Map / projections',
|
|
||||||
vector: vectorLayer.getSource()?.getProjection(),
|
|
||||||
vectorTile: clusterableVectorTileSource.getProjection(),
|
|
||||||
});
|
|
||||||
|
|
||||||
const vectorTileLayer = new VectorTileLayer({
|
|
||||||
source: clusterableVectorTileSource,
|
|
||||||
style: [],
|
|
||||||
declutter: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const olMap = new OlMap({
|
const olMap = new OlMap({
|
||||||
view: new View({
|
view: new View({
|
||||||
|
@ -263,7 +253,7 @@ const Map: Component = () => {
|
||||||
zoom: +getState().zoom,
|
zoom: +getState().zoom,
|
||||||
rotation: +getState().rotation,
|
rotation: +getState().rotation,
|
||||||
}),
|
}),
|
||||||
layers: [tileLayer, vectorLayer, vectorTileLayer],
|
layers: [tileLayer, vectorLayer],
|
||||||
target: target,
|
target: target,
|
||||||
controls: new Collection<Control>([
|
controls: new Collection<Control>([
|
||||||
new Attribution({ collapsible: true }),
|
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({
|
let clusterLayer = new VectorLayer({
|
||||||
// source: vectorTileMirrorSource,
|
// source: vectorTileMirrorSource,
|
||||||
source: new Cluster({
|
source: new Cluster({
|
||||||
|
@ -419,6 +429,7 @@ const Map: Component = () => {
|
||||||
olMap.getView().getProjection()
|
olMap.getView().getProjection()
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
// point,
|
||||||
features: features,
|
features: features,
|
||||||
type: 'cluster',
|
type: 'cluster',
|
||||||
});
|
});
|
||||||
|
@ -447,25 +458,25 @@ const Map: Component = () => {
|
||||||
// }),
|
// }),
|
||||||
// }),
|
// }),
|
||||||
});
|
});
|
||||||
olMap.addLayer(clusterLayer);
|
|
||||||
|
|
||||||
|
olMap.addLayer(vectorTileLayer);
|
||||||
|
olMap.addLayer(clusterLayer);
|
||||||
|
|
||||||
setMap(olMap);
|
setMap(olMap);
|
||||||
|
|
||||||
console.log({
|
// console.log({
|
||||||
caller: 'Map / projections',
|
// caller: 'Map / projections',
|
||||||
olMap,
|
// olMap,
|
||||||
projections: {
|
// projections: {
|
||||||
map: olMap.getView().getProjection(),
|
// map: olMap.getView().getProjection(),
|
||||||
vectorSource: vectorLayer.getSource()?.getProjection(),
|
// vectorSource: vectorLayer.getSource()?.getProjection(),
|
||||||
clusterSource: clusterLayer.getSource().getProjection(),
|
// clusterSource: clusterLayer.getSource().getProjection(),
|
||||||
clusterSourceSource: clusterLayer
|
// clusterSourceSource: clusterLayer
|
||||||
.getSource()
|
// .getSource()
|
||||||
?.getSource()
|
// ?.getSource()
|
||||||
.getProjection(),
|
// .getProjection(),
|
||||||
},
|
// },
|
||||||
});
|
// });
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -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;
|
Loading…
Reference in New Issue