geothermie-atlas/app/ews/grundlagenkarte/grundlagenkarte.tsx

259 lines
8.1 KiB
TypeScript

'use client';
import { useEffect, useRef, useState } from 'react';
import { useMediaQuery } from 'react-responsive';
import ArcGISMap from '@arcgis/core/Map';
import Extent from '@arcgis/core/geometry/Extent';
import MapView from '@arcgis/core/views/MapView';
import Basemap from '@arcgis/core/Basemap';
import MapImageLayer from '@arcgis/core/layers/MapImageLayer';
import WMTSLayer from '@arcgis/core/layers/WMTSLayer';
import SpatialReference from '@arcgis/core/geometry/SpatialReference';
import Search from '@arcgis/core/widgets/Search';
import ScaleBar from '@arcgis/core/widgets/ScaleBar';
import GraphicsLayer from '@arcgis/core/layers/GraphicsLayer';
import Graphic from '@arcgis/core/Graphic';
import LayerList from '@arcgis/core/widgets/LayerList';
import Zoom from '@arcgis/core/widgets/Zoom';
import Legend from '@arcgis/core/widgets/Legend';
import FeatureLayer from '@arcgis/core/layers/FeatureLayer';
import Polygon from '@arcgis/core/geometry/Polygon';
import esriConfig from '@arcgis/core/config';
import { watch } from '@arcgis/core/core/reactiveUtils';
import type SimpleFillSymbol from '@arcgis/core/symbols/SimpleFillSymbol';
import './esri-ui-grundlagenkarte.css';
import { Vienna, Austria } from '@/public/borders-vienna-austria';
import { BASEMAP_AT_URL, AMPEL_EWS_URL, RESOURCES_EWS_URL, SRS } from '@/app/config/config';
import getAddress from '@/app/utils/getAddress';
import identifyAllLayers from '@/app/utils/identify';
import takeScreenshot from '@/app/utils/screenshot';
import { updateAmpelkarteEWS } from '@/redux/ampelkarteEWSSlice';
import { updateResourcesEWS } from '@/redux/resourcesEWSSlice';
import { updateScreenshot } from '@/redux/screenshotSlice';
import { useAppDispatch } from '@/redux/hooks';
import PanelGrundlagenkarte from './panel-grundlagenkarte';
// set path for local assets
esriConfig.assetsPath = '/assets';
export default function MapComponent() {
const dispatch = useAppDispatch();
const mapDiv = useRef<HTMLDivElement | null>(null);
const [address, setAddress] = useState<string[] | null>([]);
const isMobile = useMediaQuery({ maxWidth: 480 });
useEffect(() => {
let handle: IHandle;
let view: MapView;
if (mapDiv.current) {
dispatch(updateAmpelkarteEWS([]));
dispatch(updateResourcesEWS([]));
dispatch(updateScreenshot(''));
view = new MapView({
container: mapDiv.current,
extent: new Extent({
xmin: -19000,
ymin: 325000,
xmax: 29000,
ymax: 360000,
spatialReference: new SpatialReference({ wkid: SRS }),
}),
popupEnabled: false,
});
let viennaGraphic = new Graphic({
geometry: new Polygon({ rings: [Austria, Vienna], spatialReference: { wkid: SRS } }),
symbol: {
type: 'simple-fill',
color: [209, 213, 219, 0.65],
style: 'solid',
outline: {
color: 'white',
width: 0,
},
} as unknown as SimpleFillSymbol,
});
// graphic layers
let viennaGraphicsLayer = new GraphicsLayer({ title: 'Wien', listMode: 'hide' });
viennaGraphicsLayer.add(viennaGraphic);
const ampelkarte_ews = new FeatureLayer({
url: AMPEL_EWS_URL + '/0',
title: 'Mögliche Einschränkungen',
visible: false,
listMode: 'show',
opacity: 0.5,
});
const resources_ews = new MapImageLayer({
title: 'Ressourcen',
url: RESOURCES_EWS_URL,
visible: false,
listMode: 'show',
opacity: 0.5,
});
// basemap in Viennese coordinate system due to tranformation inaccuracies from MGI to WGS84
// default transformation in ArcGIS API from MGI to WGS84 is 1306
// transformation 1618 is recommended
const basemap_at = new WMTSLayer({
url: BASEMAP_AT_URL,
listMode: 'hide',
});
let basemap = new Basemap({
baseLayers: [basemap_at],
title: 'basemap.at',
id: 'basemap.at',
spatialReference: { wkid: SRS },
});
let arcgisMap = new ArcGISMap({
basemap: basemap,
layers: [resources_ews, ampelkarte_ews, viennaGraphicsLayer],
});
const layerList = new LayerList({
view,
listItemCreatedFunction: addPanelInfo,
});
const search = new Search({
view,
popupEnabled: true,
});
const scaleBar = new ScaleBar({
view: view,
unit: 'metric',
});
const zoom = new Zoom({
view,
layout: 'horizontal',
});
const legend = new Legend({
view,
});
// register event handler for mouse clicks
view.on('immediate-click', (event) => {
if (setAddress && dispatch) {
takeScreenshot(view, event.mapPoint, dispatch, true);
getAddress(event.mapPoint, setAddress);
identifyAllLayers(view, event.mapPoint, dispatch, 'EWS');
}
});
// add map to view
view.map = arcgisMap;
// add UI components
view.ui.components = [];
if (!isMobile) {
view.ui.add([zoom, search, layerList], 'top-left');
view.ui.add(scaleBar, 'bottom-left');
}
view.when(() => {
handle = watch(
() => view.map?.layers?.map((layer) => layer.visible),
() => {
if (view.map?.layers?.some((layer) => layer.title !== 'Wien' && layer.visible === true)) {
view.ui?.add(legend, 'top-left');
} else {
view.ui?.remove(legend);
}
}
);
});
}
return () => {
handle?.remove();
view?.destroy();
};
}, [dispatch, isMobile, mapDiv]);
return (
<div ref={mapDiv} className="absolute top-16 bottom-0 w-full">
<PanelGrundlagenkarte address={address}></PanelGrundlagenkarte>
</div>
);
}
const addPanelInfo = (event: any) => {
let item = event.item;
switch (item.layer.id) {
case 0:
item.panel = {
content: 'mittlere jährliche Bodentemperatur laut Satellitendaten (MODIS)',
className: 'esri-icon-description',
};
break;
case 1:
item.panel = {
content: 'mittlere Temperatur des Untergrunds für eine Tiefe von 0 bis 100 m',
className: 'esri-icon-description',
};
break;
case 2:
item.panel = {
content: 'mittlere konduktive Wärmeleitfähigkeit des Untergrunds für eine Tiefe von 0 bis 100 m',
className: 'esri-icon-description',
};
break;
case 3:
item.panel = {
content:
'Entzugsleistung einer 100 m tiefen Einzelsonde im standortbezogenen Normbetrieb (Heizen und Kühlen mit Normbetriebsstunden eines typischen Wohngebäudes am Standort)',
className: 'esri-icon-description',
};
break;
case 4:
item.panel = {
content:
'Entzugsleistung einer 100 m tiefen Einzelsonde im saisonalem Speicherbetrieb (die im Winter zur Heizung entzogene Wärme wird im Sommer vollständig wieder zurückgegeben)',
className: 'esri-icon-description',
};
break;
case 5:
item.panel = {
content:
'flächenspezifische Jahresenergie eines 1156 m² großen und 100 m tiefen Sondenfeldes im standortbezogenen Normbetrieb (4 x 4 Sonden mit je 10 m Abstand - Heizen und Kühlen mit Normbetriebsstunden eines typischen Wohngebäudes am Standort)',
className: 'esri-icon-description',
};
break;
case 6:
item.panel = {
content:
'flächenspezifische Jahresenergie eines 1156 m² großen und 100 m tiefen Sondenfeldes im saisonalem Speicherbetrieb (7 x 7 Sonden mit je 5 m Abstand - die im Winter zur Heizung entzogene Wärme wird im Sommer vollständig wieder zurückgegeben)',
className: 'esri-icon-description',
};
break;
case 7:
item.panel = {
content: 'mittlere Jahresbetriebsstunden für Heizen',
className: 'esri-icon-description',
};
break;
case 8:
item.panel = {
content: 'mittlere Jahresbetriebsstunden für Kühlen',
className: 'esri-icon-description',
};
break;
default:
break;
}
};