Refactoring and implementing the actual selection of features to display.

This commit is contained in:
Eric van der Vlist 2023-01-21 21:22:36 +01:00
parent 8ddbe1bdee
commit 36337623ca
5 changed files with 137 additions and 64 deletions

View File

@ -23,6 +23,7 @@ import { createDefaultStyle } from 'ol/style/Style';
import osmIcons, { highlight } from './osm-icons';
import { indexOf } from 'lodash';
import { getZoomInteger } from '../map/Map';
import { isHighlighted } from '../map-tile-provider';
interface StyleParameters {
type: string;
@ -327,17 +328,16 @@ const styles = {
poi: {
getParameters: (feature: Feature) => {
const klass: string = feature.get('class');
const isHighlighted = highlight.hasOwnProperty(klass);
const isHighlightedFeature = isHighlighted(feature);
return {
isSelected: feature.get('isSelected') ?? false,
name: feature.get('name'),
klass,
isHighlighted,
isHighlighted: isHighlightedFeature,
isTextHidden: getZoomInteger() < 19,
// isHidden: !isHighlighted && getZoomInteger() < 16,
isHidden:
(feature.get('sub-type') === 'tourism' && getZoomInteger() < 14) ||
(feature.get('sub-type') !== 'tourism' && getZoomInteger() < 16),
(isHighlightedFeature && getZoomInteger() < 14) ||
(!isHighlightedFeature && getZoomInteger() < 16),
};
},
getStyle: memoize((params: any) => {

View File

@ -22,6 +22,7 @@ import Tree from '../tree';
import { createCachedSignal } from '../../workers/cached-signals';
import dispatch from '../../workers/dispatcher-main';
import getUri from '../../lib/ids';
import { Feature } from 'ol';
const id = getUri('overlays', undefined);
@ -176,13 +177,35 @@ const currentOverlayKey = () =>
const currentOverlay = () =>
getOverlays() ? getOverlays()[currentOverlayKey()] : {};
const currentOverlayDefinition = () => overlayDefinitions[currentOverlayKey()];
export const currentOverlayDefinition = () =>
overlayDefinitions[currentOverlayKey()];
const currentOverlayHighlightedKey = () =>
currentOverlay() && currentOverlay().highlighted
? Object.keys(currentOverlay().highlighted)[0]
: 'none';
export const currentOverlayHighlightedDefinition = () =>
currentOverlayDefinition()[currentOverlayHighlightedKey()];
export const isHighlighted = (feature: Feature) => {
const type = feature.get('sub-type');
const subType = feature.get('class');
const highlightedType = currentOverlayHighlightedDefinition()[type];
if (!highlightedType) {
return false;
}
// console.log({
// caller: 'Overlays / isHighlighted',
// feature,
// type,
// subType,
// currentOverlayHighlightedDefinition: currentOverlayHighlightedDefinition(),
// highlightedType,
// });
return highlightedType === '*' || highlightedType.includes(subType);
};
const MapTilesProvider: Component<{}> = (props) => {
const [open, setOpen] = createSignal(false);

View File

@ -1 +1,7 @@
export { default, mapTileProviders } from './MapTileProvider';
export {
default,
mapTileProviders,
currentOverlayDefinition,
currentOverlayHighlightedDefinition,
isHighlighted,
} from './MapTileProvider';

View File

@ -49,6 +49,7 @@ import VectorTileSource from 'ol/source/VectorTile.js';
import MVT from 'ol/format/MVT.js';
import style from '../gpx/styles';
import ClusterableVectorTileSourceProxy from '../../lib/ClusterableVectorTileSourceProxy';
import { Overlays } from './Overlays';
const [getState, setState] = createSignal({
lon: 0,
@ -277,69 +278,14 @@ const Map: Component = () => {
olMap.on(['moveend'], changeListener);
olMap.on(['singleclick'], clickHandler);
// // cf https://stackoverflow.com/questions/55161380/openlayers-cluster-with-mvt-vectortilesource-impossible
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 = new ClusterableVectorTileSourceProxy({
source: vectorTileSource,
});
const clusterSource = new Cluster({
source: clusterableVectorTileSource,
distance: 30,
minDistance: 10,
geometryFunction: (feature: Feature) => {
// console.log({
// caller: 'Map / Cluster / geometryFunction',
// feature,
// });
if (getZoomInteger() < 14 && feature.get('sub-type') === 'tourism') {
return feature.getGeometry();
}
return null;
},
createCluster: (point: Point, features: Feature[]) => {
// console.log({
// caller: 'Map / Cluster / createCluster',
// point,
// features,
// });
return new Feature({
geometry: point,
features: features,
type: 'cluster',
});
},
});
let clusterLayer = new VectorLayer({
source: clusterSource,
zIndex: Infinity,
style,
});
olMap.addLayer(vectorTileLayer);
olMap.addLayer(clusterLayer);
setMap(olMap);
});
return (
//<OsmFetch map={getMap} />
// @ts-ignore
<div class='ol-map' ref={target}>
<OsmFetch map={getMap} />
<Overlays map={getMap} />
<GetLocation />
<Forward />
<Back />

View File

@ -0,0 +1,98 @@
import { Component, createEffect, onMount } from 'solid-js';
import OlMap from 'ol/Map';
import {
currentOverlayDefinition,
currentOverlayHighlightedDefinition,
isHighlighted,
} from '../map-tile-provider';
import { Feature } from 'ol';
import MVT from 'ol/format/MVT';
import { Point } from 'ol/geom';
import VectorLayer from 'ol/layer/Vector';
import VectorTileLayer from 'ol/layer/VectorTile';
import VectorTileSource from 'ol/source/VectorTile.js';
import Cluster from 'ol/source/Cluster';
import { style } from '../gpx/styles';
import ClusterableVectorTileSourceProxy from '../../lib/ClusterableVectorTileSourceProxy';
import { getMap, getZoomInteger } from './Map';
interface Props {
map: () => OlMap | null;
}
let clusterLayer: VectorLayer;
let vectorTileLayer: VectorTileLayer;
export const Overlays: Component<Props> = ({ map }) => {
onMount(() => {
const vectorTileSource = new VectorTileSource({
url: 'https://geo.dyomedea.com/services/spain/tiles/{z}/{x}/{y}.pbf',
format: new MVT({ featureClass: Feature }),
maxZoom: 14,
});
vectorTileLayer = new VectorTileLayer({
source: vectorTileSource,
style,
declutter: false,
});
const clusterableVectorTileSource = new ClusterableVectorTileSourceProxy({
source: vectorTileSource,
});
const clusterSource = new Cluster({
source: clusterableVectorTileSource,
distance: 30,
minDistance: 10,
geometryFunction: (feature: Feature) => {
// console.log({
// caller: 'Map / Cluster / geometryFunction',
// feature,
// });
if (getZoomInteger() < 14 && isHighlighted(feature)) {
return feature.getGeometry();
}
return null;
},
createCluster: (point: Point, features: Feature[]) => {
// console.log({
// caller: 'Map / Cluster / createCluster',
// point,
// features,
// });
return new Feature({
geometry: point,
features: features,
type: 'cluster',
});
},
});
clusterLayer = new VectorLayer({
source: clusterSource,
zIndex: Infinity,
style,
});
});
createEffect(() => {
const overlayDefinition = currentOverlayDefinition();
const overlayHighlightedDefinition = currentOverlayHighlightedDefinition();
const olMap = getMap();
if (olMap) {
olMap.removeLayer(clusterLayer);
olMap.removeLayer(vectorTileLayer);
if (Object.keys(overlayDefinition).length > 0) {
vectorTileLayer.changed();
clusterLayer.changed();
olMap.addLayer(vectorTileLayer);
olMap.addLayer(clusterLayer);
}
}
});
return <></>;
};