From a6047a9341fb8726cc7ba82ac81d05e10a71214b Mon Sep 17 00:00:00 2001 From: William Lima Date: Mon, 13 May 2024 12:51:28 -0100 Subject: [PATCH 1/8] Implements Custom Tile Layer #1121 adds default tile layer and allows user to pass a tile object to map --- packages/components/src/components/Map.tsx | 15 +++++++++++---- packages/components/stories/Map.stories.ts | 7 +++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/components/src/components/Map.tsx b/packages/components/src/components/Map.tsx index 722740f71..212efd794 100644 --- a/packages/components/src/components/Map.tsx +++ b/packages/components/src/components/Map.tsx @@ -14,6 +14,11 @@ import 'leaflet/dist/leaflet.css'; import * as L from 'leaflet'; export type MapProps = { + tile?: { + attribution?: string; + url: string; + data?: any; + }; layers: { data: GeospatialData; name: string; @@ -37,6 +42,11 @@ export type MapProps = { }; export function Map({ + tile = { + url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', + attribution: + '© OpenStreetMap contributors', + }, layers = [ { data: null, @@ -144,10 +154,7 @@ export function Map({ map.target.fitBounds(layerToZoomBounds); }} > - + {layers.map((layer) => { const data = layersData.find( diff --git a/packages/components/stories/Map.stories.ts b/packages/components/stories/Map.stories.ts index c7bc80818..343d1587d 100644 --- a/packages/components/stories/Map.stories.ts +++ b/packages/components/stories/Map.stories.ts @@ -43,6 +43,13 @@ type Story = StoryObj; export const GeoJSONPolygons: Story = { name: 'GeoJSON polygons map', args: { + tile : { + url : 'https://tiles.stadiamaps.com/tiles/alidade_satellite/{z}/{x}/{y}{r}.{ext}', + attribution:'© CNES, Distribution Airbus DS, © Airbus DS, © PlanetObserver (Contains Copernicus Data) | © Stadia Maps © OpenMapTiles © OpenStreetMap contributors', + data: { + ext: 'jpg' + } + }, layers: [ { data: { From d1a5138c6e5bc9d4c935b0797a5bb581a04e6bc3 Mon Sep 17 00:00:00 2001 From: William Lima Date: Wed, 22 May 2024 11:48:20 -0100 Subject: [PATCH 2/8] include configs on .env vars or pass through props --- packages/components/.storybook/preview.ts | 9 ++++-- packages/components/src/components/Map.tsx | 34 ++++++++++++++++++---- packages/components/stories/Map.stories.ts | 9 +++--- 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/packages/components/.storybook/preview.ts b/packages/components/.storybook/preview.ts index 1ec353c50..a1d3914d4 100644 --- a/packages/components/.storybook/preview.ts +++ b/packages/components/.storybook/preview.ts @@ -1,9 +1,14 @@ import 'tailwindcss/tailwind.css' import '../src/index.css' - - import type { Preview } from '@storybook/react'; +window.process = { + ...window.process, + env:{ + ...window.process?.env + } +}; + const preview: Preview = { parameters: { actions: { argTypesRegex: '^on[A-Z].*' }, diff --git a/packages/components/src/components/Map.tsx b/packages/components/src/components/Map.tsx index 212efd794..70af81f0e 100644 --- a/packages/components/src/components/Map.tsx +++ b/packages/components/src/components/Map.tsx @@ -8,17 +8,14 @@ import { TileLayer, GeoJSON as GeoJSONLayer, LayersControl, + TileLayerProps, } from 'react-leaflet'; import 'leaflet/dist/leaflet.css'; import * as L from 'leaflet'; export type MapProps = { - tile?: { - attribution?: string; - url: string; - data?: any; - }; + tile?: TileLayerProps; layers: { data: GeospatialData; name: string; @@ -64,6 +61,30 @@ export function Map({ const [isLoading, setIsLoading] = useState(false); const [layersData, setLayersData] = useState([]); + /* + tileEnvVars + extract all environment variables thats starts with NEXT_PUBLIC_MAP_TILE_. + the variables names are the same as the TileLayer object properties: + - url: + - attribution + - accessToken + - id + - ext + - bounds + - maxZoom + - minZoom + see TileLayerOptions inteface + */ + const tileEnvVars = Object.keys(process?.env) + .filter((key) => key.startsWith('NEXT_PUBLIC_MAP_TILE_')) + .reduce((obj, key) => { + obj[key.split('NEXT_PUBLIC_MAP_TILE_')[1]] = process.env[key]; + return obj; + }, {}); + + //tileData prioritizes properties passed through component over those passed through .env variables + const tileData = Object.assign(tileEnvVars, tile); + useEffect(() => { const loadDataPromises = layers.map(async (layer) => { const url = layer.data.url; @@ -154,7 +175,8 @@ export function Map({ map.target.fitBounds(layerToZoomBounds); }} > - + {tileData.url && } + {layers.map((layer) => { const data = layersData.find( diff --git a/packages/components/stories/Map.stories.ts b/packages/components/stories/Map.stories.ts index 343d1587d..0da60f03c 100644 --- a/packages/components/stories/Map.stories.ts +++ b/packages/components/stories/Map.stories.ts @@ -44,11 +44,10 @@ export const GeoJSONPolygons: Story = { name: 'GeoJSON polygons map', args: { tile : { - url : 'https://tiles.stadiamaps.com/tiles/alidade_satellite/{z}/{x}/{y}{r}.{ext}', - attribution:'© CNES, Distribution Airbus DS, © Airbus DS, © PlanetObserver (Contains Copernicus Data) | © Stadia Maps © OpenMapTiles © OpenStreetMap contributors', - data: { - ext: 'jpg' - } + url : 'https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', + attribution:'© OpenStreetMap contributors © Mapbox', + accessToken : 'pk.eyJ1Ijoid2lsbHktcGFsbWFyZWpvIiwiYSI6ImNqNzk5NmRpNDFzb2cyeG9sc2luMHNjajUifQ.lkoVRFSI8hOLH4uJeOzwXw', + id: 'mapbox/streets-v10' }, layers: [ { From 31406d48e3378524461cdbfca5e7448559637d63 Mon Sep 17 00:00:00 2001 From: William Lima Date: Fri, 31 May 2024 10:29:15 -0100 Subject: [PATCH 3/8] Update Map.tsx --- packages/components/src/components/Map.tsx | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/components/src/components/Map.tsx b/packages/components/src/components/Map.tsx index 70af81f0e..b0439b36c 100644 --- a/packages/components/src/components/Map.tsx +++ b/packages/components/src/components/Map.tsx @@ -39,11 +39,7 @@ export type MapProps = { }; export function Map({ - tile = { - url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', - attribution: - '© OpenStreetMap contributors', - }, + tile = undefined, layers = [ { data: null, @@ -63,7 +59,7 @@ export function Map({ /* tileEnvVars - extract all environment variables thats starts with NEXT_PUBLIC_MAP_TILE_. + extract all environment variables thats starts with NEXT_PUBLIC_MAP_TILE_PROVIDER_. the variables names are the same as the TileLayer object properties: - url: - attribution @@ -76,14 +72,22 @@ export function Map({ see TileLayerOptions inteface */ const tileEnvVars = Object.keys(process?.env) - .filter((key) => key.startsWith('NEXT_PUBLIC_MAP_TILE_')) + .filter((key) => key.startsWith('NEXT_PUBLIC_MAP_TILE_PROVIDER_')) .reduce((obj, key) => { - obj[key.split('NEXT_PUBLIC_MAP_TILE_')[1]] = process.env[key]; + obj[key.split('NEXT_PUBLIC_MAP_TILE_PROVIDER_')[1]] = process.env[key]; return obj; }, {}); //tileData prioritizes properties passed through component over those passed through .env variables - const tileData = Object.assign(tileEnvVars, tile); + let tileData = Object.assign(tileEnvVars, tile); + + tileData = tileData.url + ? tileData + : { + url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', + attribution: + '© OpenStreetMap contributors', + }; useEffect(() => { const loadDataPromises = layers.map(async (layer) => { From 134f72948ce4dad9742f41305a14e38577648b3b Mon Sep 17 00:00:00 2001 From: William Lima Date: Tue, 18 Jun 2024 22:01:59 -0100 Subject: [PATCH 4/8] Add TileLayer Presets configuration --- packages/components/.storybook/preview.ts | 7 +- packages/components/src/components/Map.tsx | 151 +- .../components/src/lib/tileLayerPresets.tsx | 1211 +++++++++++++++++ packages/components/stories/Map.stories.ts | 6 +- 4 files changed, 1340 insertions(+), 35 deletions(-) create mode 100644 packages/components/src/lib/tileLayerPresets.tsx diff --git a/packages/components/.storybook/preview.ts b/packages/components/.storybook/preview.ts index a1d3914d4..93bbee20e 100644 --- a/packages/components/.storybook/preview.ts +++ b/packages/components/.storybook/preview.ts @@ -5,7 +5,12 @@ import type { Preview } from '@storybook/react'; window.process = { ...window.process, env:{ - ...window.process?.env + ...window.process?.env, + + NEXT_PUBLIC_MAP_TILE_LAYER_NAME:'MapBox', + NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_accessToken: 'pk.eyJ1Ijoid2lsbHktcGFsbWFyZWpvIiwiYSI6ImNqNzk5NmRpNDFzb2cyeG9sc2luMHNjajUifQ.lkoVRFSI8hOLH4uJeOzwXw', + + } }; diff --git a/packages/components/src/components/Map.tsx b/packages/components/src/components/Map.tsx index b0439b36c..9bbc099d4 100644 --- a/packages/components/src/components/Map.tsx +++ b/packages/components/src/components/Map.tsx @@ -8,14 +8,36 @@ import { TileLayer, GeoJSON as GeoJSONLayer, LayersControl, - TileLayerProps, } from 'react-leaflet'; import 'leaflet/dist/leaflet.css'; import * as L from 'leaflet'; +import providers from '../lib/tileLayerPresets'; + +type VariantKeys = T extends { variants: infer V } + ? { + [K in keyof V]: K extends string + ? `${K}` | `${K}.${VariantKeys}` + : never; + }[keyof V] + : never; + +type ProviderVariantKeys = { + [K in keyof T]: K extends string + ? `${K}` | `${K}.${VariantKeys}` + : never; +}[keyof T]; + +type TileLayerPreset = ProviderVariantKeys | 'custom'; + +interface TileLayerSettings extends L.TileLayerOptions { + url?: string; + variant?: string | any; +} export type MapProps = { - tile?: TileLayerProps; + tileLayerName: TileLayerPreset; + tileLayerOptions?: TileLayerSettings | undefined; layers: { data: GeospatialData; name: string; @@ -38,8 +60,19 @@ export type MapProps = { }; }; +const tileLayerDefaultName = process?.env + .NEXT_PUBLIC_MAP_TILE_LAYER_NAME as TileLayerPreset; + +const tileLayerDefaultOptions = Object.keys(process?.env) + .filter((key) => key.startsWith('NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_')) + .reduce((obj, key) => { + obj[key.split('NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_')[1]] = process.env[key]; + return obj; + }, {}) as TileLayerSettings; + export function Map({ - tile = undefined, + tileLayerName = tileLayerDefaultName || 'OpenStreetMap', + tileLayerOptions, layers = [ { data: null, @@ -58,36 +91,94 @@ export function Map({ const [layersData, setLayersData] = useState([]); /* - tileEnvVars - extract all environment variables thats starts with NEXT_PUBLIC_MAP_TILE_PROVIDER_. + tileLayerDefaultOptions + extract all environment variables thats starts with NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_. the variables names are the same as the TileLayer object properties: - - url: - - attribution - - accessToken - - id - - ext - - bounds - - maxZoom - - minZoom + - NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_url: + - NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_attribution + - NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_accessToken + - NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_id + - NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_ext + - NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_bounds + - NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_maxZoom + - NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_minZoom see TileLayerOptions inteface */ - const tileEnvVars = Object.keys(process?.env) - .filter((key) => key.startsWith('NEXT_PUBLIC_MAP_TILE_PROVIDER_')) - .reduce((obj, key) => { - obj[key.split('NEXT_PUBLIC_MAP_TILE_PROVIDER_')[1]] = process.env[key]; - return obj; - }, {}); - - //tileData prioritizes properties passed through component over those passed through .env variables - let tileData = Object.assign(tileEnvVars, tile); - - tileData = tileData.url - ? tileData - : { - url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', - attribution: - '© OpenStreetMap contributors', + + //tileLayerData prioritizes properties passed through component over those passed through .env variables + tileLayerOptions = Object.assign(tileLayerDefaultOptions, tileLayerOptions); + + let provider = { + url: tileLayerOptions.url, + options: tileLayerOptions, + }; + + if (tileLayerName != 'custom') { + var parts = tileLayerName.split('.'); + var providerName = parts[0]; + var variantName: string = parts[1]; + + //make sure to declare a variant if url depends on a variant: assume first + if (providers[providerName].url?.includes('{variant}') && !variantName) + variantName = Object.keys(providers[providerName].variants)[0]; + + console.log(variantName); + + if (!providers[providerName]) { + throw 'No such provider (' + providerName + ')'; + } + + provider = { + url: providers[providerName].url, + options: providers[providerName].options, + }; + + // overwrite values in provider from variant. + if (variantName && 'variants' in providers[providerName]) { + if (!(variantName in providers[providerName].variants)) { + throw 'No such variant of ' + providerName + ' (' + variantName + ')'; + } + var variant = providers[providerName].variants[variantName]; + var variantOptions; + if (typeof variant === 'string') { + variantOptions = { + variant: variant, + }; + } else { + variantOptions = variant.options; + } + provider = { + url: variant.url || provider.url, + options: L.Util.extend({}, provider.options, variantOptions), }; + } + + var attributionReplacer = function (attr) { + if (attr.indexOf('{attribution.') === -1) { + return attr; + } + return attr.replace( + /\{attribution.(\w*)\}/g, + function (match, attributionName) { + return attributionReplacer( + providers[attributionName].options.attribution + ); + } + ); + }; + + provider.options.attribution = attributionReplacer( + provider.options.attribution + ); + } + + var tileLayerData = L.Util.extend( + { + url: provider.url, + }, + provider.options, + tileLayerOptions + ); useEffect(() => { const loadDataPromises = layers.map(async (layer) => { @@ -179,7 +270,7 @@ export function Map({ map.target.fitBounds(layerToZoomBounds); }} > - {tileData.url && } + {tileLayerData.url && } {layers.map((layer) => { diff --git a/packages/components/src/lib/tileLayerPresets.tsx b/packages/components/src/lib/tileLayerPresets.tsx new file mode 100644 index 000000000..7ef68b939 --- /dev/null +++ b/packages/components/src/lib/tileLayerPresets.tsx @@ -0,0 +1,1211 @@ +const TileLayerPresets = { + OpenStreetMap: { + url: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', + options: { + maxZoom: 19, + attribution: + '© OpenStreetMap contributors', + }, + variants: { + Mapnik: {}, + DE: { + url: 'https://tile.openstreetmap.de/{z}/{x}/{y}.png', + options: { + maxZoom: 18, + }, + }, + CH: { + url: 'https://tile.osm.ch/switzerland/{z}/{x}/{y}.png', + options: { + maxZoom: 18, + bounds: [ + [45, 5], + [48, 11], + ], + }, + }, + France: { + url: 'https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png', + options: { + maxZoom: 20, + attribution: + '© OpenStreetMap France | {attribution.OpenStreetMap}', + }, + }, + HOT: { + url: 'https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', + options: { + attribution: + '{attribution.OpenStreetMap}, ' + + 'Tiles style by Humanitarian OpenStreetMap Team ' + + 'hosted by OpenStreetMap France', + }, + }, + BZH: { + url: 'https://tile.openstreetmap.bzh/br/{z}/{x}/{y}.png', + options: { + attribution: + '{attribution.OpenStreetMap}, Tiles courtesy of Breton OpenStreetMap Team', + bounds: [ + [46.2, -5.5], + [50, 0.7], + ], + }, + }, + }, + }, + MapTilesAPI: { + url: 'https://maptiles.p.rapidapi.com/{variant}/{z}/{x}/{y}.png?rapidapi-key={apikey}', + options: { + attribution: + '© MapTiles API, {attribution.OpenStreetMap}', + variant: 'en/map/v1', + // Get your own MapTiles API access token here : https://www.maptilesapi.com/ + // NB : this is a demonstration key that comes with no guarantee and not to be used in production + apikey: '', + maxZoom: 19, + }, + variants: { + OSMEnglish: { + options: { + variant: 'en/map/v1', + }, + }, + OSMFrancais: { + options: { + variant: 'fr/map/v1', + }, + }, + OSMEspagnol: { + options: { + variant: 'es/map/v1', + }, + }, + }, + }, + OpenSeaMap: { + url: 'https://tiles.openseamap.org/seamark/{z}/{x}/{y}.png', + options: { + attribution: + 'Map data: © OpenSeaMap contributors', + }, + }, + OPNVKarte: { + url: 'https://tileserver.memomaps.de/tilegen/{z}/{x}/{y}.png', + options: { + maxZoom: 18, + attribution: + 'Map memomaps.de CC-BY-SA, map data {attribution.OpenStreetMap}', + }, + }, + OpenTopoMap: { + url: 'https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', + options: { + maxZoom: 17, + attribution: + 'Map data: {attribution.OpenStreetMap}, SRTM | Map style: © OpenTopoMap (CC-BY-SA)', + }, + }, + OpenRailwayMap: { + url: 'https://{s}.tiles.openrailwaymap.org/standard/{z}/{x}/{y}.png', + options: { + maxZoom: 19, + attribution: + 'Map data: {attribution.OpenStreetMap} | Map style: © OpenRailwayMap (CC-BY-SA)', + }, + }, + OpenFireMap: { + url: 'http://openfiremap.org/hytiles/{z}/{x}/{y}.png', + options: { + maxZoom: 19, + attribution: + 'Map data: {attribution.OpenStreetMap} | Map style: © OpenFireMap (CC-BY-SA)', + }, + }, + SafeCast: { + url: 'https://s3.amazonaws.com/te512.safecast.org/{z}/{x}/{y}.png', + options: { + maxZoom: 16, + attribution: + 'Map data: {attribution.OpenStreetMap} | Map style: © SafeCast (CC-BY-SA)', + }, + }, + Stadia: { + url: 'https://tiles.stadiamaps.com/tiles/{variant}/{z}/{x}/{y}{r}.{ext}', + options: { + minZoom: 0, + maxZoom: 20, + attribution: + '© Stadia Maps ' + + '© OpenMapTiles ' + + '{attribution.OpenStreetMap}', + variant: 'alidade_smooth', + ext: 'png', + }, + variants: { + AlidadeSmooth: 'alidade_smooth', + AlidadeSmoothDark: 'alidade_smooth_dark', + AlidadeSatellite: { + options: { + attribution: + '© CNES, Distribution Airbus DS, © Airbus DS, © PlanetObserver (Contains Copernicus Data) | ' + + '© Stadia Maps ' + + '© OpenMapTiles ' + + '{attribution.OpenStreetMap}', + variant: 'alidade_satellite', + ext: 'jpg', + }, + }, + OSMBright: 'osm_bright', + Outdoors: 'outdoors', + StamenToner: { + options: { + attribution: + '© Stadia Maps ' + + '© Stamen Design ' + + '© OpenMapTiles ' + + '{attribution.OpenStreetMap}', + variant: 'stamen_toner', + }, + }, + StamenTonerBackground: { + options: { + attribution: + '© Stadia Maps ' + + '© Stamen Design ' + + '© OpenMapTiles ' + + '{attribution.OpenStreetMap}', + variant: 'stamen_toner_background', + }, + }, + StamenTonerLines: { + options: { + attribution: + '© Stadia Maps ' + + '© Stamen Design ' + + '© OpenMapTiles ' + + '{attribution.OpenStreetMap}', + variant: 'stamen_toner_lines', + }, + }, + StamenTonerLabels: { + options: { + attribution: + '© Stadia Maps ' + + '© Stamen Design ' + + '© OpenMapTiles ' + + '{attribution.OpenStreetMap}', + variant: 'stamen_toner_labels', + }, + }, + StamenTonerLite: { + options: { + attribution: + '© Stadia Maps ' + + '© Stamen Design ' + + '© OpenMapTiles ' + + '{attribution.OpenStreetMap}', + variant: 'stamen_toner_lite', + }, + }, + StamenWatercolor: { + url: 'https://tiles.stadiamaps.com/tiles/{variant}/{z}/{x}/{y}.{ext}', + options: { + attribution: + '© Stadia Maps ' + + '© Stamen Design ' + + '© OpenMapTiles ' + + '{attribution.OpenStreetMap}', + variant: 'stamen_watercolor', + ext: 'jpg', + minZoom: 1, + maxZoom: 16, + }, + }, + StamenTerrain: { + options: { + attribution: + '© Stadia Maps ' + + '© Stamen Design ' + + '© OpenMapTiles ' + + '{attribution.OpenStreetMap}', + variant: 'stamen_terrain', + minZoom: 0, + maxZoom: 18, + }, + }, + StamenTerrainBackground: { + options: { + attribution: + '© Stadia Maps ' + + '© Stamen Design ' + + '© OpenMapTiles ' + + '{attribution.OpenStreetMap}', + variant: 'stamen_terrain_background', + minZoom: 0, + maxZoom: 18, + }, + }, + StamenTerrainLabels: { + options: { + attribution: + '© Stadia Maps ' + + '© Stamen Design ' + + '© OpenMapTiles ' + + '{attribution.OpenStreetMap}', + variant: 'stamen_terrain_labels', + minZoom: 0, + maxZoom: 18, + }, + }, + StamenTerrainLines: { + options: { + attribution: + '© Stadia Maps ' + + '© Stamen Design ' + + '© OpenMapTiles ' + + '{attribution.OpenStreetMap}', + variant: 'stamen_terrain_lines', + minZoom: 0, + maxZoom: 18, + }, + }, + }, + }, + Thunderforest: { + url: 'https://{s}.tile.thunderforest.com/{variant}/{z}/{x}/{y}.png?apikey={apikey}', + options: { + attribution: + '© Thunderforest, {attribution.OpenStreetMap}', + variant: 'cycle', + apikey: '', + maxZoom: 22, + }, + variants: { + OpenCycleMap: 'cycle', + Transport: { + options: { + variant: 'transport', + }, + }, + TransportDark: { + options: { + variant: 'transport-dark', + }, + }, + SpinalMap: { + options: { + variant: 'spinal-map', + }, + }, + Landscape: 'landscape', + Outdoors: 'outdoors', + Pioneer: 'pioneer', + MobileAtlas: 'mobile-atlas', + Neighbourhood: 'neighbourhood', + }, + }, + BaseMapDE: { + url: 'https://sgx.geodatenzentrum.de/wmts_basemapde/tile/1.0.0/{variant}/default/GLOBAL_WEBMERCATOR/{z}/{y}/{x}.png', + options: { + attribution: + 'Map data: © dl-de/by-2-0', + variant: 'de_basemapde_web_raster_farbe', + }, + variants: { + Color: 'de_basemapde_web_raster_farbe', + Grey: 'de_basemapde_web_raster_grau', + }, + }, + CyclOSM: { + url: 'https://{s}.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png', + options: { + maxZoom: 20, + attribution: + 'CyclOSM | Map data: {attribution.OpenStreetMap}', + }, + }, + Jawg: { + url: 'https://tile.jawg.io/{variant}/{z}/{x}/{y}{r}.png?access-token={accessToken}', + options: { + attribution: + '© JawgMaps ' + + '{attribution.OpenStreetMap}', + minZoom: 0, + maxZoom: 22, + variant: 'jawg-streets', + // Get your own Jawg access token here : https://www.jawg.io/lab/ + // NB : this is a demonstration key that comes with no guarantee + accessToken: '', + }, + variants: { + Streets: 'jawg-streets', + Terrain: 'jawg-terrain', + Lagoon: 'jawg-lagoon', + Sunny: 'jawg-sunny', + Dark: 'jawg-dark', + Light: 'jawg-light', + Matrix: 'jawg-matrix', + }, + }, + MapBox: { + url: 'https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}{r}?access_token={accessToken}', + options: { + attribution: + '© Mapbox ' + + '{attribution.OpenStreetMap} ' + + 'Improve this map', + tileSize: 512, + maxZoom: 18, + zoomOffset: -1, + id: 'mapbox/streets-v11', + accessToken: '', + }, + }, + MapTiler: { + url: 'https://api.maptiler.com/maps/{variant}/{z}/{x}/{y}{r}.{ext}?key={key}', + options: { + attribution: + '© MapTiler © OpenStreetMap contributors', + variant: 'streets', + ext: 'png', + key: '', + tileSize: 512, + zoomOffset: -1, + minZoom: 0, + maxZoom: 21, + }, + variants: { + Streets: 'streets', + Basic: 'basic', + Bright: 'bright', + Pastel: 'pastel', + Positron: 'positron', + Hybrid: { + options: { + variant: 'hybrid', + ext: 'jpg', + }, + }, + Toner: 'toner', + Topo: 'topo', + Voyager: 'voyager', + Ocean: 'ocean', + Backdrop: 'backdrop', + Dataviz: 'dataviz', + }, + }, + TomTom: { + url: 'https://{s}.api.tomtom.com/map/1/tile/{variant}/{style}/{z}/{x}/{y}.{ext}?key={apikey}', + options: { + variant: 'basic', + maxZoom: 22, + attribution: + '© 1992 - ' + + new Date().getFullYear() + + ' TomTom. ', + subdomains: 'abcd', + style: 'main', + ext: 'png', + apikey: '', + }, + variants: { + Basic: 'basic', + Hybrid: 'hybrid', + Labels: 'labels', + }, + }, + Esri: { + url: 'https://server.arcgisonline.com/ArcGIS/rest/services/{variant}/MapServer/tile/{z}/{y}/{x}', + options: { + variant: 'World_Street_Map', + attribution: 'Tiles © Esri', + }, + variants: { + WorldStreetMap: { + options: { + attribution: + '{attribution.Esri} — ' + + 'Source: Esri, DeLorme, NAVTEQ, USGS, Intermap, iPC, NRCAN, Esri Japan, METI, Esri China (Hong Kong), Esri (Thailand), TomTom, 2012', + }, + }, + DeLorme: { + options: { + variant: 'Specialty/DeLorme_World_Base_Map', + minZoom: 1, + maxZoom: 11, + attribution: + '{attribution.Esri} — Copyright: ©2012 DeLorme', + }, + }, + WorldTopoMap: { + options: { + variant: 'World_Topo_Map', + attribution: + '{attribution.Esri} — ' + + 'Esri, DeLorme, NAVTEQ, TomTom, Intermap, iPC, USGS, FAO, NPS, NRCAN, GeoBase, Kadaster NL, Ordnance Survey, Esri Japan, METI, Esri China (Hong Kong), and the GIS User Community', + }, + }, + WorldImagery: { + options: { + variant: 'World_Imagery', + attribution: + '{attribution.Esri} — ' + + 'Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community', + }, + }, + WorldTerrain: { + options: { + variant: 'World_Terrain_Base', + maxZoom: 13, + attribution: + '{attribution.Esri} — ' + + 'Source: USGS, Esri, TANA, DeLorme, and NPS', + }, + }, + WorldShadedRelief: { + options: { + variant: 'World_Shaded_Relief', + maxZoom: 13, + attribution: '{attribution.Esri} — Source: Esri', + }, + }, + WorldPhysical: { + options: { + variant: 'World_Physical_Map', + maxZoom: 8, + attribution: + '{attribution.Esri} — Source: US National Park Service', + }, + }, + OceanBasemap: { + options: { + variant: 'Ocean/World_Ocean_Base', + maxZoom: 13, + attribution: + '{attribution.Esri} — Sources: GEBCO, NOAA, CHS, OSU, UNH, CSUMB, National Geographic, DeLorme, NAVTEQ, and Esri', + }, + }, + NatGeoWorldMap: { + options: { + variant: 'NatGeo_World_Map', + maxZoom: 16, + attribution: + '{attribution.Esri} — National Geographic, Esri, DeLorme, NAVTEQ, UNEP-WCMC, USGS, NASA, ESA, METI, NRCAN, GEBCO, NOAA, iPC', + }, + }, + WorldGrayCanvas: { + options: { + variant: 'Canvas/World_Light_Gray_Base', + maxZoom: 16, + attribution: '{attribution.Esri} — Esri, DeLorme, NAVTEQ', + }, + }, + }, + }, + OpenWeatherMap: { + url: 'http://{s}.tile.openweathermap.org/map/{variant}/{z}/{x}/{y}.png?appid={apiKey}', + options: { + maxZoom: 19, + attribution: + 'Map data © OpenWeatherMap', + apiKey: '', + opacity: 0.5, + }, + variants: { + Clouds: 'clouds', + CloudsClassic: 'clouds_cls', + Precipitation: 'precipitation', + PrecipitationClassic: 'precipitation_cls', + Rain: 'rain', + RainClassic: 'rain_cls', + Pressure: 'pressure', + PressureContour: 'pressure_cntr', + Wind: 'wind', + Temperature: 'temp', + Snow: 'snow', + }, + }, + HERE: { + /* + * HERE maps, formerly Nokia maps. + * These basemaps are free, but you need an api id and app key. Please sign up at + * https://developer.here.com/plans + */ + url: + 'https://{s}.{base}.maps.api.here.com/maptile/2.1/' + + '{type}/{mapID}/{variant}/{z}/{x}/{y}/{size}/{format}?' + + 'app_id={app_id}&app_code={app_code}&lg={language}', + options: { + attribution: + 'Map © 1987-' + + new Date().getFullYear() + + ' HERE', + subdomains: '1234', + mapID: 'newest', + app_id: '', + app_code: '', + base: 'base', + variant: 'normal.day', + maxZoom: 20, + type: 'maptile', + language: 'eng', + format: 'png8', + size: '256', + }, + variants: { + normalDay: 'normal.day', + normalDayCustom: 'normal.day.custom', + normalDayGrey: 'normal.day.grey', + normalDayMobile: 'normal.day.mobile', + normalDayGreyMobile: 'normal.day.grey.mobile', + normalDayTransit: 'normal.day.transit', + normalDayTransitMobile: 'normal.day.transit.mobile', + normalDayTraffic: { + options: { + variant: 'normal.traffic.day', + base: 'traffic', + type: 'traffictile', + }, + }, + normalNight: 'normal.night', + normalNightMobile: 'normal.night.mobile', + normalNightGrey: 'normal.night.grey', + normalNightGreyMobile: 'normal.night.grey.mobile', + normalNightTransit: 'normal.night.transit', + normalNightTransitMobile: 'normal.night.transit.mobile', + reducedDay: 'reduced.day', + reducedNight: 'reduced.night', + basicMap: { + options: { + type: 'basetile', + }, + }, + mapLabels: { + options: { + type: 'labeltile', + format: 'png', + }, + }, + trafficFlow: { + options: { + base: 'traffic', + type: 'flowtile', + }, + }, + carnavDayGrey: 'carnav.day.grey', + hybridDay: { + options: { + base: 'aerial', + variant: 'hybrid.day', + }, + }, + hybridDayMobile: { + options: { + base: 'aerial', + variant: 'hybrid.day.mobile', + }, + }, + hybridDayTransit: { + options: { + base: 'aerial', + variant: 'hybrid.day.transit', + }, + }, + hybridDayGrey: { + options: { + base: 'aerial', + variant: 'hybrid.grey.day', + }, + }, + hybridDayTraffic: { + options: { + variant: 'hybrid.traffic.day', + base: 'traffic', + type: 'traffictile', + }, + }, + pedestrianDay: 'pedestrian.day', + pedestrianNight: 'pedestrian.night', + satelliteDay: { + options: { + base: 'aerial', + variant: 'satellite.day', + }, + }, + terrainDay: { + options: { + base: 'aerial', + variant: 'terrain.day', + }, + }, + terrainDayMobile: { + options: { + base: 'aerial', + variant: 'terrain.day.mobile', + }, + }, + }, + }, + HEREv3: { + /* + * HERE maps API Version 3. + * These basemaps are free, but you need an API key. Please sign up at + * https://developer.here.com/plans + * Version 3 deprecates the app_id and app_code access in favor of apiKey + * + * Supported access methods as of 2019/12/21: + * @see https://developer.here.com/faqs#access-control-1--how-do-you-control-access-to-here-location-services + */ + url: + 'https://{s}.{base}.maps.ls.hereapi.com/maptile/2.1/' + + '{type}/{mapID}/{variant}/{z}/{x}/{y}/{size}/{format}?' + + 'apiKey={apiKey}&lg={language}', + options: { + attribution: + 'Map © 1987-' + + new Date().getFullYear() + + ' HERE', + subdomains: '1234', + mapID: 'newest', + apiKey: '', + base: 'base', + variant: 'normal.day', + maxZoom: 20, + type: 'maptile', + language: 'eng', + format: 'png8', + size: '256', + }, + variants: { + normalDay: 'normal.day', + normalDayCustom: 'normal.day.custom', + normalDayGrey: 'normal.day.grey', + normalDayMobile: 'normal.day.mobile', + normalDayGreyMobile: 'normal.day.grey.mobile', + normalDayTransit: 'normal.day.transit', + normalDayTransitMobile: 'normal.day.transit.mobile', + normalNight: 'normal.night', + normalNightMobile: 'normal.night.mobile', + normalNightGrey: 'normal.night.grey', + normalNightGreyMobile: 'normal.night.grey.mobile', + normalNightTransit: 'normal.night.transit', + normalNightTransitMobile: 'normal.night.transit.mobile', + reducedDay: 'reduced.day', + reducedNight: 'reduced.night', + basicMap: { + options: { + type: 'basetile', + }, + }, + mapLabels: { + options: { + type: 'labeltile', + format: 'png', + }, + }, + trafficFlow: { + options: { + base: 'traffic', + type: 'flowtile', + }, + }, + carnavDayGrey: 'carnav.day.grey', + hybridDay: { + options: { + base: 'aerial', + variant: 'hybrid.day', + }, + }, + hybridDayMobile: { + options: { + base: 'aerial', + variant: 'hybrid.day.mobile', + }, + }, + hybridDayTransit: { + options: { + base: 'aerial', + variant: 'hybrid.day.transit', + }, + }, + hybridDayGrey: { + options: { + base: 'aerial', + variant: 'hybrid.grey.day', + }, + }, + pedestrianDay: 'pedestrian.day', + pedestrianNight: 'pedestrian.night', + satelliteDay: { + options: { + base: 'aerial', + variant: 'satellite.day', + }, + }, + terrainDay: { + options: { + base: 'aerial', + variant: 'terrain.day', + }, + }, + terrainDayMobile: { + options: { + base: 'aerial', + variant: 'terrain.day.mobile', + }, + }, + }, + }, + FreeMapSK: { + url: 'https://{s}.freemap.sk/T/{z}/{x}/{y}.jpeg', + options: { + minZoom: 8, + maxZoom: 16, + subdomains: 'abcd', + bounds: [ + [47.204642, 15.996093], + [49.830896, 22.576904], + ], + attribution: + '{attribution.OpenStreetMap}, visualization CC-By-SA 2.0 Freemap.sk', + }, + }, + MtbMap: { + url: 'http://tile.mtbmap.cz/mtbmap_tiles/{z}/{x}/{y}.png', + options: { + attribution: '{attribution.OpenStreetMap} & USGS', + }, + }, + CartoDB: { + url: 'https://{s}.basemaps.cartocdn.com/{variant}/{z}/{x}/{y}{r}.png', + options: { + attribution: + '{attribution.OpenStreetMap} © CARTO', + subdomains: 'abcd', + maxZoom: 20, + variant: 'light_all', + }, + variants: { + Positron: 'light_all', + PositronNoLabels: 'light_nolabels', + PositronOnlyLabels: 'light_only_labels', + DarkMatter: 'dark_all', + DarkMatterNoLabels: 'dark_nolabels', + DarkMatterOnlyLabels: 'dark_only_labels', + Voyager: 'rastertiles/voyager', + VoyagerNoLabels: 'rastertiles/voyager_nolabels', + VoyagerOnlyLabels: 'rastertiles/voyager_only_labels', + VoyagerLabelsUnder: 'rastertiles/voyager_labels_under', + }, + }, + HikeBike: { + url: 'https://tiles.wmflabs.org/{variant}/{z}/{x}/{y}.png', + options: { + maxZoom: 19, + attribution: '{attribution.OpenStreetMap}', + variant: 'hikebike', + }, + variants: { + HikeBike: {}, + HillShading: { + options: { + maxZoom: 15, + variant: 'hillshading', + }, + }, + }, + }, + BasemapAT: { + url: 'https://mapsneu.wien.gv.at/basemap/{variant}/{type}/google3857/{z}/{y}/{x}.{format}', + options: { + maxZoom: 19, + attribution: + 'Datenquelle: basemap.at', + type: 'normal', + format: 'png', + bounds: [ + [46.35877, 8.782379], + [49.037872, 17.189532], + ], + variant: 'geolandbasemap', + }, + variants: { + basemap: { + options: { + maxZoom: 20, // currently only in Vienna + variant: 'geolandbasemap', + }, + }, + grau: 'bmapgrau', + overlay: 'bmapoverlay', + terrain: { + options: { + variant: 'bmapgelaende', + type: 'grau', + format: 'jpeg', + }, + }, + surface: { + options: { + variant: 'bmapoberflaeche', + type: 'grau', + format: 'jpeg', + }, + }, + highdpi: { + options: { + variant: 'bmaphidpi', + format: 'jpeg', + }, + }, + orthofoto: { + options: { + maxZoom: 20, // currently only in Vienna + variant: 'bmaporthofoto30cm', + format: 'jpeg', + }, + }, + }, + }, + nlmaps: { + url: 'https://service.pdok.nl/brt/achtergrondkaart/wmts/v2_0/{variant}/EPSG:3857/{z}/{x}/{y}.png', + options: { + minZoom: 6, + maxZoom: 19, + bounds: [ + [50.5, 3.25], + [54, 7.6], + ], + attribution: + 'Kaartgegevens © Kadaster', + }, + variants: { + standaard: 'standaard', + pastel: 'pastel', + grijs: 'grijs', + water: 'water', + luchtfoto: { + url: 'https://service.pdok.nl/hwh/luchtfotorgb/wmts/v1_0/Actueel_ortho25/EPSG:3857/{z}/{x}/{y}.jpeg', + }, + }, + }, + NASAGIBS: { + url: 'https://map1.vis.earthdata.nasa.gov/wmts-webmerc/{variant}/default/{time}/{tilematrixset}{maxZoom}/{z}/{y}/{x}.{format}', + options: { + attribution: + 'Imagery provided by services from the Global Imagery Browse Services (GIBS), operated by the NASA/GSFC/Earth Science Data and Information System ' + + '(ESDIS) with funding provided by NASA/HQ.', + bounds: [ + [-85.0511287776, -179.999999975], + [85.0511287776, 179.999999975], + ], + minZoom: 1, + maxZoom: 9, + format: 'jpg', + time: '', + tilematrixset: 'GoogleMapsCompatible_Level', + }, + variants: { + ModisTerraTrueColorCR: 'MODIS_Terra_CorrectedReflectance_TrueColor', + ModisTerraBands367CR: 'MODIS_Terra_CorrectedReflectance_Bands367', + ViirsEarthAtNight2012: { + options: { + variant: 'VIIRS_CityLights_2012', + maxZoom: 8, + }, + }, + ModisTerraLSTDay: { + options: { + variant: 'MODIS_Terra_Land_Surface_Temp_Day', + format: 'png', + maxZoom: 7, + opacity: 0.75, + }, + }, + ModisTerraSnowCover: { + options: { + variant: 'MODIS_Terra_NDSI_Snow_Cover', + format: 'png', + maxZoom: 8, + opacity: 0.75, + }, + }, + ModisTerraAOD: { + options: { + variant: 'MODIS_Terra_Aerosol', + format: 'png', + maxZoom: 6, + opacity: 0.75, + }, + }, + ModisTerraChlorophyll: { + options: { + variant: 'MODIS_Terra_L2_Chlorophyll_A', + format: 'png', + maxZoom: 7, + opacity: 0.75, + }, + }, + }, + }, + NLS: { + // NLS maps are copyright National library of Scotland. + // http://maps.nls.uk/projects/subscription-api + // Please contact NLS for anything other than non-commercial low volume usage + // + // Map sources: Ordnance Survey 1:1m to 1:63K, 1880s-1961 + // z0-9 - 1:1m + // z10-11 - quarter inch (1:253440) + // z12-18 - one inch (1:63360) + url: 'https://api.maptiler.com/tiles/{variant}/{z}/{x}/{y}.jpg?key={apikey}', + options: { + attribution: + 'National Library of Scotland Historic Maps', + bounds: [ + [49.6, -12], + [61.7, 3], + ], + minZoom: 1, + maxZoom: 18, + apikey: '', + }, + variants: { + osgb63k1885: 'uk-osgb63k1885', + osgb1888: 'uk-osgb1888', + osgb10k1888: 'uk-osgb10k1888', + osgb1919: 'uk-osgb1919', + osgb25k1937: 'uk-osgb25k1937', + osgb63k1955: 'uk-osgb63k1955', + oslondon1k1893: 'uk-oslondon1k1893', + }, + }, + JusticeMap: { + // Justice Map (http://www.justicemap.org/) + // Visualize race and income data for your community, county and country. + // Includes tools for data journalists, bloggers and community activists. + url: 'https://www.justicemap.org/tile/{size}/{variant}/{z}/{x}/{y}.png', + options: { + attribution: + 'Justice Map', + // one of 'county', 'tract', 'block' + size: 'county', + // Bounds for USA, including Alaska and Hawaii + bounds: [ + [14, -180], + [72, -56], + ], + }, + variants: { + income: 'income', + americanIndian: 'indian', + asian: 'asian', + black: 'black', + hispanic: 'hispanic', + multi: 'multi', + nonWhite: 'nonwhite', + white: 'white', + plurality: 'plural', + }, + }, + GeoportailFrance: { + url: 'https://wxs.ign.fr/{apikey}/geoportail/wmts?REQUEST=GetTile&SERVICE=WMTS&VERSION=1.0.0&STYLE={style}&TILEMATRIXSET=PM&FORMAT={format}&LAYER={variant}&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}', + options: { + attribution: + 'Geoportail France', + bounds: [ + [-75, -180], + [81, 180], + ], + minZoom: 2, + maxZoom: 18, + // Get your own geoportail apikey here : http://professionnels.ign.fr/ign/contrats/ + // NB : 'choisirgeoportail' is a demonstration key that comes with no guarantee + apikey: 'choisirgeoportail', + format: 'image/png', + style: 'normal', + variant: 'GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2', + }, + variants: { + plan: 'GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2', + parcels: { + options: { + variant: 'CADASTRALPARCELS.PARCELLAIRE_EXPRESS', + style: 'PCI vecteur', + maxZoom: 20, + }, + }, + orthos: { + options: { + maxZoom: 19, + format: 'image/jpeg', + variant: 'ORTHOIMAGERY.ORTHOPHOTOS', + }, + }, + }, + }, + OneMapSG: { + url: 'https://maps-{s}.onemap.sg/v3/{variant}/{z}/{x}/{y}.png', + options: { + variant: 'Default', + minZoom: 11, + maxZoom: 18, + bounds: [ + [1.56073, 104.11475], + [1.16, 103.502], + ], + attribution: + ' New OneMap | Map data © contributors, Singapore Land Authority', + }, + variants: { + Default: 'Default', + Night: 'Night', + Original: 'Original', + Grey: 'Grey', + LandLot: 'LandLot', + }, + }, + USGS: { + url: 'https://basemap.nationalmap.gov/arcgis/rest/services/USGSTopo/MapServer/tile/{z}/{y}/{x}', + options: { + maxZoom: 20, + attribution: + 'Tiles courtesy of the U.S. Geological Survey', + }, + variants: { + USTopo: {}, + USImagery: { + url: 'https://basemap.nationalmap.gov/arcgis/rest/services/USGSImageryOnly/MapServer/tile/{z}/{y}/{x}', + }, + USImageryTopo: { + url: 'https://basemap.nationalmap.gov/arcgis/rest/services/USGSImageryTopo/MapServer/tile/{z}/{y}/{x}', + }, + }, + }, + WaymarkedTrails: { + url: 'https://tile.waymarkedtrails.org/{variant}/{z}/{x}/{y}.png', + options: { + maxZoom: 18, + attribution: + 'Map data: {attribution.OpenStreetMap} | Map style: © waymarkedtrails.org (CC-BY-SA)', + }, + variants: { + hiking: 'hiking', + cycling: 'cycling', + mtb: 'mtb', + slopes: 'slopes', + riding: 'riding', + skating: 'skating', + }, + }, + OpenAIP: { + url: 'https://{s}.tile.maps.openaip.net/geowebcache/service/tms/1.0.0/openaip_basemap@EPSG%3A900913@png/{z}/{x}/{y}.{ext}', + options: { + attribution: + 'openAIP Data (CC-BY-NC-SA)', + ext: 'png', + minZoom: 4, + maxZoom: 14, + tms: true, + detectRetina: true, + subdomains: '12', + }, + }, + OpenSnowMap: { + url: 'https://tiles.opensnowmap.org/{variant}/{z}/{x}/{y}.png', + options: { + minZoom: 9, + maxZoom: 18, + attribution: + 'Map data: {attribution.OpenStreetMap} & ODbL, © www.opensnowmap.org CC-BY-SA', + }, + variants: { + pistes: 'pistes', + }, + }, + AzureMaps: { + url: + 'https://atlas.microsoft.com/map/tile?api-version={apiVersion}' + + '&tilesetId={variant}&x={x}&y={y}&zoom={z}&language={language}' + + '&subscription-key={subscriptionKey}', + options: { + attribution: + 'See https://docs.microsoft.com/en-us/rest/api/maps/render-v2/get-map-tile for details.', + apiVersion: '2.0', + variant: 'microsoft.imagery', + subscriptionKey: '', + language: 'en-US', + }, + variants: { + MicrosoftImagery: 'microsoft.imagery', + MicrosoftBaseDarkGrey: 'microsoft.base.darkgrey', + MicrosoftBaseRoad: 'microsoft.base.road', + MicrosoftBaseHybridRoad: 'microsoft.base.hybrid.road', + MicrosoftTerraMain: 'microsoft.terra.main', + MicrosoftWeatherInfraredMain: { + url: + 'https://atlas.microsoft.com/map/tile?api-version={apiVersion}' + + '&tilesetId={variant}&x={x}&y={y}&zoom={z}' + + '&timeStamp={timeStamp}&language={language}' + + '&subscription-key={subscriptionKey}', + options: { + timeStamp: '2021-05-08T09:03:00Z', + attribution: + 'See https://docs.microsoft.com/en-us/rest/api/maps/render-v2/get-map-tile#uri-parameters for details.', + variant: 'microsoft.weather.infrared.main', + }, + }, + MicrosoftWeatherRadarMain: { + url: + 'https://atlas.microsoft.com/map/tile?api-version={apiVersion}' + + '&tilesetId={variant}&x={x}&y={y}&zoom={z}' + + '&timeStamp={timeStamp}&language={language}' + + '&subscription-key={subscriptionKey}', + options: { + timeStamp: '2021-05-08T09:03:00Z', + attribution: + 'See https://docs.microsoft.com/en-us/rest/api/maps/render-v2/get-map-tile#uri-parameters for details.', + variant: 'microsoft.weather.radar.main', + }, + }, + }, + }, + SwissFederalGeoportal: { + url: 'https://wmts.geo.admin.ch/1.0.0/{variant}/default/current/3857/{z}/{x}/{y}.jpeg', + options: { + attribution: + '© swisstopo', + minZoom: 2, + maxZoom: 18, + bounds: [ + [45.398181, 5.140242], + [48.230651, 11.47757], + ], + }, + variants: { + NationalMapColor: 'ch.swisstopo.pixelkarte-farbe', + NationalMapGrey: 'ch.swisstopo.pixelkarte-grau', + SWISSIMAGE: { + options: { + variant: 'ch.swisstopo.swissimage', + maxZoom: 19, + }, + }, + }, + }, + TopPlusOpen: { + url: 'http://sgx.geodatenzentrum.de/wmts_topplus_open/tile/1.0.0/{variant}/default/WEBMERCATOR/{z}/{y}/{x}.png', + options: { + maxZoom: 18, + attribution: + 'Map data: © dl-de/by-2-0', + variant: 'web', + }, + variants: { + Color: 'web', + Grey: 'web_grau', + }, + }, +}; + +export default TileLayerPresets; diff --git a/packages/components/stories/Map.stories.ts b/packages/components/stories/Map.stories.ts index 0da60f03c..e479bb776 100644 --- a/packages/components/stories/Map.stories.ts +++ b/packages/components/stories/Map.stories.ts @@ -43,11 +43,9 @@ type Story = StoryObj; export const GeoJSONPolygons: Story = { name: 'GeoJSON polygons map', args: { - tile : { - url : 'https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', - attribution:'© OpenStreetMap contributors © Mapbox', + tileLayerName:'OpenStreetMap', + tileLayerOptions:{ accessToken : 'pk.eyJ1Ijoid2lsbHktcGFsbWFyZWpvIiwiYSI6ImNqNzk5NmRpNDFzb2cyeG9sc2luMHNjajUifQ.lkoVRFSI8hOLH4uJeOzwXw', - id: 'mapbox/streets-v10' }, layers: [ { From 32f29024f87af8b46496c4da81d5d332d6cdecbc Mon Sep 17 00:00:00 2001 From: William Lima Date: Tue, 18 Jun 2024 22:05:41 -0100 Subject: [PATCH 5/8] attr replace fix --- packages/components/src/components/Map.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/components/src/components/Map.tsx b/packages/components/src/components/Map.tsx index 9bbc099d4..0cd62133e 100644 --- a/packages/components/src/components/Map.tsx +++ b/packages/components/src/components/Map.tsx @@ -159,7 +159,8 @@ export function Map({ } return attr.replace( /\{attribution.(\w*)\}/g, - function (match, attributionName) { + function (match: any, attributionName: string) { + match; return attributionReplacer( providers[attributionName].options.attribution ); From 97e43fdcba25fb757bc0a860d6c7522541a0a6c2 Mon Sep 17 00:00:00 2001 From: William Lima Date: Tue, 18 Jun 2024 22:37:20 -0100 Subject: [PATCH 6/8] add mapbox as default basemap --- packages/components/.storybook/preview.ts | 5 +---- packages/components/stories/Map.stories.ts | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/components/.storybook/preview.ts b/packages/components/.storybook/preview.ts index 93bbee20e..b31490560 100644 --- a/packages/components/.storybook/preview.ts +++ b/packages/components/.storybook/preview.ts @@ -6,10 +6,7 @@ window.process = { ...window.process, env:{ ...window.process?.env, - - NEXT_PUBLIC_MAP_TILE_LAYER_NAME:'MapBox', - NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_accessToken: 'pk.eyJ1Ijoid2lsbHktcGFsbWFyZWpvIiwiYSI6ImNqNzk5NmRpNDFzb2cyeG9sc2luMHNjajUifQ.lkoVRFSI8hOLH4uJeOzwXw', - + } }; diff --git a/packages/components/stories/Map.stories.ts b/packages/components/stories/Map.stories.ts index e479bb776..f4500f82d 100644 --- a/packages/components/stories/Map.stories.ts +++ b/packages/components/stories/Map.stories.ts @@ -43,7 +43,7 @@ type Story = StoryObj; export const GeoJSONPolygons: Story = { name: 'GeoJSON polygons map', args: { - tileLayerName:'OpenStreetMap', + tileLayerName:'MapBox', tileLayerOptions:{ accessToken : 'pk.eyJ1Ijoid2lsbHktcGFsbWFyZWpvIiwiYSI6ImNqNzk5NmRpNDFzb2cyeG9sc2luMHNjajUifQ.lkoVRFSI8hOLH4uJeOzwXw', }, From 93ae498ec2a62763fd4c4469975a96c22f3237b7 Mon Sep 17 00:00:00 2001 From: William Lima Date: Wed, 19 Jun 2024 10:10:56 -0100 Subject: [PATCH 7/8] Code cleanup --- packages/components/src/components/Map.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/components/src/components/Map.tsx b/packages/components/src/components/Map.tsx index 0cd62133e..2f0cd92b3 100644 --- a/packages/components/src/components/Map.tsx +++ b/packages/components/src/components/Map.tsx @@ -122,8 +122,6 @@ export function Map({ if (providers[providerName].url?.includes('{variant}') && !variantName) variantName = Object.keys(providers[providerName].variants)[0]; - console.log(variantName); - if (!providers[providerName]) { throw 'No such provider (' + providerName + ')'; } From 8e3496782c022b0653e07f217c6b315ba84e0e61 Mon Sep 17 00:00:00 2001 From: Demenech Date: Mon, 24 Jun 2024 17:42:49 -0300 Subject: [PATCH 8/8] version: add changeset --- .changeset/long-kiwis-vanish.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/long-kiwis-vanish.md diff --git a/.changeset/long-kiwis-vanish.md b/.changeset/long-kiwis-vanish.md new file mode 100644 index 000000000..b7a98e8c7 --- /dev/null +++ b/.changeset/long-kiwis-vanish.md @@ -0,0 +1,5 @@ +--- +'@portaljs/components': minor +--- + +Map: allow users to choose a base layer setting