geosphere-maps/app/[locale]/basemap-list.tsx

143 lines
4.9 KiB
TypeScript
Raw Normal View History

2023-09-29 11:18:55 +00:00
import { useRef, useEffect } from 'react';
2023-09-28 11:27:46 +00:00
import { useTranslation } from 'react-i18next';
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';
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>;
}