import OSM from 'ol/source/OSM'; import XYZ from 'ol/source/XYZ'; import { Component, createEffect, createSignal, For, Show } from 'solid-js'; import { I18nContext, createI18nContext, useI18n, } from '@solid-primitives/i18n'; import style from './MapTileProvider.module.css'; import LayersIcon from '@suid/icons-material/Layers'; import CloseIcon from '@suid/icons-material/Close'; import { FormControlLabel, IconButton, Radio, RadioGroup, } from '@suid/material'; import { useNavigate, useParams } from '@solidjs/router'; import Dialog from '../dialog'; import Tree from '../tree'; import { createCachedSignal } from '../../workers/cached-signals'; import dispatch from '../../workers/dispatcher-main'; import getUri from '../../lib/ids'; const id = getUri('overlays', undefined); interface TileProvider { name: string; language: string; source: XYZ; } type TileProviders = { [key: string]: TileProvider; }; export const mapTileProviders: TileProviders = { osm: { name: 'Open Street Map', language: 'int', source: new OSM(), }, osmfr: { name: 'Open Street Map France', language: 'fr', source: new XYZ({ minZoom: 0, maxZoom: 20, url: 'https://{a-c}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png', }), }, otm: { name: 'Open Topo Map', language: 'int', source: new XYZ({ minZoom: 0, maxZoom: 16, url: 'https://{a-c}.tile.opentopomap.org/{z}/{x}/{y}.png', }), }, cyclosm: { name: 'CyclOSM', language: 'int', source: new XYZ({ minZoom: 0, maxZoom: 19, url: 'https://{a-c}.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png', }), }, //https://b.tile.openstreetmap.fr/openriverboatmap/20/535762/382966.png openriverboatmap: { name: 'Open River Boat Map', language: 'int', source: new XYZ({ minZoom: 0, maxZoom: 19, url: 'https://{a-c}.tile.openstreetmap.fr/openriverboatmap/{z}/{x}/{y}.png', }), }, rasterIgnEs: { name: 'Cartografía Ráster de España del IGN', language: 'es', source: new XYZ({ minZoom: 0, maxZoom: 19, url: 'http://www.ign.es/wmts/mapa-raster?request=getTile&layer=MTN&TileMatrixSet=GoogleMapsCompatible&TileMatrix={z}&TileCol={x}&TileRow={y}&format=image/jpeg', }), }, pnoaMaEs: { name: 'Ortoimágenes de España', language: 'es', source: new XYZ({ minZoom: 0, maxZoom: 19, url: 'http://www.ign.es/wmts/pnoa-ma?request=getTile&layer=MTN&TileMatrixSet=GoogleMapsCompatible&TileMatrix={z}&TileCol={x}&TileRow={y}&format=image/jpeg', }), }, }; type FeatureSubTypes = Array | '*'; type FeatureTypes = Record; type Overlay = { selected: boolean; highlighted: FeatureTypes; hidden: FeatureTypes; }; type Overlays = Record; const defaultOverlays: Overlays = { none: { selected: true, highlighted: { none: [] }, hidden: {} }, hiking: { selected: false, highlighted: { none: [], }, hidden: { none: [] }, }, }; type OverlayDefinition = Record; type OverlayDefinitions = Record; export const overlayDefinitions: OverlayDefinitions = { none: {}, hiking: { none: {}, sleeping: { tourism: '*', }, drinking: { amenity: ['bar', 'cafe', 'pub', 'drinking_water', 'water_point'], }, eating: { amenity: ['fast_food', 'pub', 'restaurant'], shop: [ 'bakery', 'butcher', 'cheese', 'chocolate', 'convenience', 'dairy', 'farm', 'greengrocer', 'health_food', 'pastry', 'seafood', 'department_store', 'supermarket', ], }, health: { amenity: ['doctors', 'hospital', 'pharmacy'], }, security: { amenity: ['police', 'fire_station'], }, dayToDay: { amenity: ['waste_basket', 'waste_disposal'], shop: ['laundry'], }, }, }; const getOverlays = createCachedSignal({ id, method: 'getOverlays', defaultOverlays, }) as () => Overlays; const currentOverlayKey = () => getOverlays() ? Object.keys(getOverlays()).filter((key) => getOverlays()[key].selected)[0] : 'none'; const currentOverlay = () => getOverlays() ? getOverlays()[currentOverlayKey()] : {}; const currentOverlayDefinition = () => overlayDefinitions[currentOverlayKey()]; const currentOverlayHighlightedKey = () => currentOverlay() && currentOverlay().highlighted ? Object.keys(currentOverlay().highlighted)[0] : 'none'; const MapTilesProvider: Component<{}> = (props) => { const [open, setOpen] = createSignal(false); const navigate = useNavigate(); const handleClickOpen = () => { setOpen(true); }; const handleClose = () => { setOpen(false); }; const params = useParams(); const [t] = useI18n(); const handleChange = (ev: any) => { navigate( `/map/${ev.target.value}/${params.lon}/${params.lat}/${params.zoom}/${params.rotation}` ); setOpen(false); }; createEffect(() => { console.log({ caller: 'MapTilesProvider', overlays: getOverlays(), currentOverlayKey: currentOverlayKey(), currentOverlay: currentOverlay(), currentOverlayDefinition: currentOverlayDefinition(), currentOverlayHighlightedKey: currentOverlayHighlightedKey(), }); }); const handleOverlayChange = (ev: any) => { const value = ev.target.value; console.log({ caller: 'MapTilesProvider / handleOverlayChange', ev, value, }); const newOverlays = getOverlays(); Object.keys(newOverlays).forEach((key) => { newOverlays[key].selected = key === value; }); dispatch({ action: 'putOverlays', params: { id, overlays: newOverlays }, }); }; const handleOverlayHighlightChange = (ev: any) => { const value = ev.target.value; console.log({ caller: 'MapTilesProvider / handleOverlayHighlightChange', ev, value, }); const newOverlays = getOverlays(); newOverlays[currentOverlayKey()].highlighted = {}; newOverlays[currentOverlayKey()].highlighted[value] = []; dispatch({ action: 'putOverlays', params: { id, overlays: newOverlays }, }); }; return ( <>
{(p: string) => ( } label={p} /> )} 0}> {' '}
---
Highlight
{(p: string) => ( } label={p} /> )}
} subTree={undefined} >
{(p: string) => ( } label={mapTileProviders[p].name} /> )} } subTree={undefined} >
); }; export default MapTilesProvider;