181 lines
5.4 KiB
TypeScript
181 lines
5.4 KiB
TypeScript
|
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 SimpleFillSymbol from '@arcgis/core/symbols/SimpleFillSymbol';
|
||
|
|
||
|
import './esri-ui-grundlagenkarte.css';
|
||
|
import { Vienna, Austria } from '@/public/borders-vienna-austria';
|
||
|
import { BASEMAP_AT_URL, AMPEL_GWWP_URL, RESOURCES_GWWP_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 { useAppDispatch } from '@/redux/hooks';
|
||
|
|
||
|
import PanelGrundlagenkarte from './panel-grundlagenkarte-gwwp';
|
||
|
|
||
|
// set path for local assets
|
||
|
esriConfig.assetsPath = '/assets';
|
||
|
|
||
|
export default function MapComponent() {
|
||
|
const dispatch = useAppDispatch();
|
||
|
const isMobile = useMediaQuery({ maxWidth: 480 });
|
||
|
|
||
|
const mapDiv = useRef<HTMLDivElement | null>(null);
|
||
|
const [address, setAddress] = useState<string[]>([]);
|
||
|
|
||
|
useEffect(() => {
|
||
|
let view: MapView;
|
||
|
let handle: IHandle;
|
||
|
if (mapDiv.current) {
|
||
|
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_gwwp = new FeatureLayer({
|
||
|
url: AMPEL_GWWP_URL + '/0',
|
||
|
title: 'Mögliche Einschränkungen',
|
||
|
visible: false,
|
||
|
listMode: 'show',
|
||
|
opacity: 0.5,
|
||
|
});
|
||
|
|
||
|
const resources_gwwp = new MapImageLayer({
|
||
|
title: 'Ressourcen',
|
||
|
url: RESOURCES_GWWP_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_gwwp, ampelkarte_gwwp, viennaGraphicsLayer],
|
||
|
});
|
||
|
|
||
|
const layerList = new LayerList({
|
||
|
view,
|
||
|
});
|
||
|
|
||
|
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) {
|
||
|
takeScreenshot(view, event.mapPoint, dispatch, true);
|
||
|
getAddress(event.mapPoint, setAddress);
|
||
|
identifyAllLayers(view, event.mapPoint, dispatch, 'GWWP');
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// 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]);
|
||
|
|
||
|
return (
|
||
|
<div ref={mapDiv} className="absolute top-16 bottom-0 w-full">
|
||
|
<PanelGrundlagenkarte address={address}></PanelGrundlagenkarte>
|
||
|
</div>
|
||
|
);
|
||
|
}
|