151 lines
5.1 KiB
TypeScript
151 lines
5.1 KiB
TypeScript
|
import { useRef, useEffect, RefObject } from 'react';
|
||
|
|
||
|
import { useTranslation } from 'react-i18next';
|
||
|
import initI18n from './i18n';
|
||
|
|
||
|
import MapView from '@arcgis/core/views/MapView';
|
||
|
import Basemap from '@arcgis/core/Basemap';
|
||
|
import esriRequest from '@arcgis/core/request';
|
||
|
import BaseTileLayer from '@arcgis/core/layers/BaseTileLayer';
|
||
|
import BasemapGallery from '@arcgis/core/widgets/BasemapGallery';
|
||
|
import VectorTileLayer from '@arcgis/core/layers/VectorTileLayer';
|
||
|
import TileLayer from '@arcgis/core/layers/TileLayer';
|
||
|
|
||
|
const BEVURL = 'https://maps.bev.gv.at/tiles/{z}/{x}/{y}.png';
|
||
|
|
||
|
// load localized strings
|
||
|
const match = location.pathname.match(/\/(\w+)/);
|
||
|
if (match && match.length > 1) {
|
||
|
const locale = match[1];
|
||
|
initI18n(locale);
|
||
|
}
|
||
|
|
||
|
export default function Basemaps({ view }: { view: MapView }) {
|
||
|
const basemapGalleryContainer = useRef<HTMLDivElement | null>(null);
|
||
|
const rendered = useRef<boolean>(false);
|
||
|
|
||
|
const { t } = useTranslation();
|
||
|
|
||
|
const BEVTileLayer = (BaseTileLayer as any).createSubclass({
|
||
|
// define instance properties
|
||
|
properties: {
|
||
|
urlTemplate: null,
|
||
|
},
|
||
|
|
||
|
// generate the tile url for a given level, row and column
|
||
|
getTileUrl: function (level: number, row: number, col: number) {
|
||
|
const z = level.toString().padStart(2, '0');
|
||
|
let x = row.toString().padStart(9, '0');
|
||
|
let y = col.toString().padStart(9, '0');
|
||
|
|
||
|
// this is the BEV tiling scheme
|
||
|
x = x.substring(0, 3) + '/' + x.substring(3, 3) + '/' + x.substring(6, 3);
|
||
|
y = y.substring(0, 3) + '/' + y.substring(3, 3) + '/' + y.substring(6, 3);
|
||
|
|
||
|
return this.urlTemplate.replace(/\{z\}/g, z).replace(/\{x\}/g, y).replace(/\{y\}/g, x);
|
||
|
},
|
||
|
|
||
|
// This method fetches tiles for the specified level and size.
|
||
|
fetchTile: function (level: number, row: number, col: number, options: any) {
|
||
|
// get the url for this tile
|
||
|
const url = this.getTileUrl(level, row, col);
|
||
|
|
||
|
// request for tiles based on the generated url
|
||
|
// the signal option ensures that obsolete requests are aborted
|
||
|
return esriRequest(url, {
|
||
|
responseType: 'image',
|
||
|
}).then(
|
||
|
function (this: any, response: any) {
|
||
|
// when esri request resolves successfully
|
||
|
// get the image from the response
|
||
|
const image = response.data;
|
||
|
const width = this.tileInfo.size[0];
|
||
|
const height = this.tileInfo.size[0];
|
||
|
|
||
|
// create a canvas with 2D rendering context
|
||
|
const canvas = document.createElement('canvas');
|
||
|
const context = canvas.getContext('2d');
|
||
|
canvas.width = width;
|
||
|
canvas.height = height;
|
||
|
|
||
|
// Draw the blended image onto the canvas.
|
||
|
context?.drawImage(image, 0, 0, width, height);
|
||
|
const imageData = context?.getImageData(0, 0, canvas.width, canvas.height);
|
||
|
if (imageData) context?.putImageData(imageData, 0, 0);
|
||
|
|
||
|
return canvas;
|
||
|
}.bind(this)
|
||
|
);
|
||
|
},
|
||
|
|
||
|
copyright: t('basemaps.copyright-bev'),
|
||
|
});
|
||
|
|
||
|
useEffect(() => {
|
||
|
if (rendered.current) return;
|
||
|
rendered.current = true;
|
||
|
|
||
|
if (view) {
|
||
|
const topoLayer = new BEVTileLayer({
|
||
|
urlTemplate: BEVURL,
|
||
|
title: 'BEV-Topografie',
|
||
|
});
|
||
|
|
||
|
const basemapBEV = new Basemap({
|
||
|
baseLayers: [topoLayer],
|
||
|
title: t('basemaps.basemap-bev-title'),
|
||
|
id: 'basemap',
|
||
|
thumbnailUrl:
|
||
|
'https://gis.geosphere.at/portal/sharing/rest/content/items/1a94736328a1458abe435d23508f1822/data',
|
||
|
});
|
||
|
|
||
|
const basemapAT = new Basemap({
|
||
|
portalItem: {
|
||
|
id: 'df7d6cc9be754db8970614d2ee661f57',
|
||
|
portal: {
|
||
|
url: 'https://gis.geosphere.at/portal',
|
||
|
},
|
||
|
},
|
||
|
});
|
||
|
|
||
|
const basemapOSM = new Basemap({
|
||
|
portalItem: {
|
||
|
id: '5f6efd84434842fb9dcdcf6b9116dcd9',
|
||
|
portal: { url: 'https://gis.geosphere.at/portal' },
|
||
|
},
|
||
|
});
|
||
|
|
||
|
const lightgrayBase = new VectorTileLayer({
|
||
|
url: 'https://gis.geosphere.at/portal/sharing/rest/content/items/291da5eab3a0412593b66d384379f89f/resources/styles/root.json',
|
||
|
opacity: 0.5,
|
||
|
});
|
||
|
const lightGrayReference = new VectorTileLayer({
|
||
|
url: 'https://gis.geosphere.at/portal/sharing/rest/content/items/1768e8369a214dfab4e2167d5c5f2454/resources/styles/root.json',
|
||
|
opacity: 1,
|
||
|
});
|
||
|
const worldHillshade = new TileLayer({
|
||
|
url: 'https://services.arcgisonline.com/arcgis/rest/services/Elevation/World_Hillshade/MapServer',
|
||
|
});
|
||
|
const basemapEsri = new Basemap({
|
||
|
baseLayers: [worldHillshade, lightgrayBase, lightGrayReference],
|
||
|
title: t('basemaps.basemap-esri-title'),
|
||
|
thumbnailUrl:
|
||
|
'https://gis.geosphere.at/portal/sharing/rest/content/items/3eb1510943be4f29ae01c01ce229d8ba/data',
|
||
|
});
|
||
|
|
||
|
const basemapGalleryDiv = document.createElement('div');
|
||
|
basemapGalleryContainer.current?.append(basemapGalleryDiv);
|
||
|
|
||
|
new BasemapGallery({
|
||
|
container: basemapGalleryDiv,
|
||
|
view: view,
|
||
|
source: [basemapAT, basemapBEV, basemapOSM, basemapEsri],
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return () => {};
|
||
|
});
|
||
|
|
||
|
return <div ref={basemapGalleryContainer}></div>;
|
||
|
}
|