forked from VinokurovVE/tests
Rename; Added EMS server; redis compose
This commit is contained in:
175
client/src/components/map/MapComponent.tsx
Normal file
175
client/src/components/map/MapComponent.tsx
Normal file
@ -0,0 +1,175 @@
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import GeoJSON from 'ol/format/GeoJSON'
|
||||
import 'ol/ol.css'
|
||||
import Map from 'ol/Map'
|
||||
import View from 'ol/View'
|
||||
import { Draw, Modify, Snap } from 'ol/interaction'
|
||||
import { OSM, Vector as VectorSource } from 'ol/source'
|
||||
import { Tile as TileLayer, Vector as VectorLayer } from 'ol/layer'
|
||||
import { transform, transformExtent } from 'ol/proj'
|
||||
import { Divider, IconButton, Stack } from '@mui/material'
|
||||
import { Adjust, Api, CircleOutlined, RectangleOutlined, Timeline, Undo, Warning } from '@mui/icons-material'
|
||||
import { Type } from 'ol/geom/Geometry'
|
||||
|
||||
const MapComponent = () => {
|
||||
const mapElement = useRef<HTMLDivElement | null>(null)
|
||||
const [currentTool, setCurrentTool] = useState<Type>('Point')
|
||||
|
||||
const map = useRef<Map | null>(null)
|
||||
const source = useRef<VectorSource>(new VectorSource())
|
||||
|
||||
const draw = useRef<Draw | null>(null)
|
||||
const snap = useRef<Snap | null>(null)
|
||||
|
||||
const drawingLayer = useRef<VectorLayer | null>(null)
|
||||
|
||||
const addInteractions = () => {
|
||||
draw.current = new Draw({
|
||||
source: source.current,
|
||||
type: currentTool,
|
||||
})
|
||||
map?.current?.addInteraction(draw.current)
|
||||
snap.current = new Snap({ source: source.current })
|
||||
map?.current?.addInteraction(snap.current)
|
||||
}
|
||||
|
||||
// Function to save features to localStorage
|
||||
const saveFeatures = () => {
|
||||
const features = drawingLayer.current?.getSource()?.getFeatures()
|
||||
if (features && features.length > 0) {
|
||||
const geoJSON = new GeoJSON()
|
||||
const featuresJSON = geoJSON.writeFeatures(features)
|
||||
localStorage.setItem('savedFeatures', featuresJSON)
|
||||
}
|
||||
}
|
||||
|
||||
// Function to load features from localStorage
|
||||
const loadFeatures = () => {
|
||||
const savedFeatures = localStorage.getItem('savedFeatures')
|
||||
if (savedFeatures) {
|
||||
const geoJSON = new GeoJSON()
|
||||
const features = geoJSON.readFeatures(savedFeatures, {
|
||||
featureProjection: 'EPSG:4326', // Ensure the projection is correct
|
||||
})
|
||||
source.current?.addFeatures(features) // Add features to the vector source
|
||||
//drawingLayer.current?.getSource()?.changed()
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const geoLayer = new VectorLayer({
|
||||
background: '#1a2b39',
|
||||
source: new VectorSource({
|
||||
url: 'https://openlayers.org/data/vector/ecoregions.json',
|
||||
format: new GeoJSON(),
|
||||
}),
|
||||
style: {
|
||||
'fill-color': ['string', ['get', 'COLOR'], '#eee'],
|
||||
},
|
||||
})
|
||||
|
||||
const raster = new TileLayer({
|
||||
source: new OSM(),
|
||||
})
|
||||
|
||||
drawingLayer.current = new VectorLayer({
|
||||
source: source.current,
|
||||
style: {
|
||||
'fill-color': 'rgba(255, 255, 255, 0.2)',
|
||||
'stroke-color': '#ffcc33',
|
||||
'stroke-width': 2,
|
||||
'circle-radius': 7,
|
||||
'circle-fill-color': '#ffcc33',
|
||||
},
|
||||
})
|
||||
|
||||
// Center coordinates of Yakutia in EPSG:3857
|
||||
const center = transform([129.7694, 66.9419], 'EPSG:4326', 'EPSG:3857')
|
||||
|
||||
// Extent for Yakutia in EPSG:4326
|
||||
const extent4326 = [105.0, 55.0, 170.0, 75.0] // Approximate bounding box
|
||||
// Transform extent to EPSG:3857
|
||||
const extent = transformExtent(extent4326, 'EPSG:4326', 'EPSG:3857')
|
||||
|
||||
map.current = new Map({
|
||||
layers: [geoLayer, raster, drawingLayer.current],
|
||||
target: mapElement.current as HTMLDivElement,
|
||||
view: new View({
|
||||
center,
|
||||
zoom: 4,
|
||||
extent,
|
||||
}),
|
||||
})
|
||||
|
||||
const modify = new Modify({ source: source.current })
|
||||
map.current.addInteraction(modify)
|
||||
|
||||
addInteractions()
|
||||
|
||||
loadFeatures()
|
||||
|
||||
return () => {
|
||||
map?.current?.setTarget(undefined)
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (currentTool) {
|
||||
if (draw.current) map?.current?.removeInteraction(draw.current)
|
||||
if (snap.current) map?.current?.removeInteraction(snap.current)
|
||||
addInteractions()
|
||||
}
|
||||
}, [currentTool])
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Stack my={1} spacing={1} direction='row' divider={<Divider orientation='vertical' flexItem />}>
|
||||
<IconButton onClick={() => {
|
||||
fetch(`${import.meta.env.VITE_API_EMS_URL}/hello`, { method: 'GET' }).then(res => console.log(res))
|
||||
}}>
|
||||
<Api />
|
||||
</IconButton>
|
||||
|
||||
<IconButton onClick={() => {
|
||||
saveFeatures()
|
||||
}}>
|
||||
<Warning />
|
||||
</IconButton>
|
||||
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
draw.current?.removeLastPoint()
|
||||
}}>
|
||||
<Undo />
|
||||
</IconButton>
|
||||
|
||||
<IconButton
|
||||
sx={{ backgroundColor: currentTool === 'Point' ? 'Highlight' : 'transparent' }}
|
||||
onClick={() => setCurrentTool('Point')}>
|
||||
<Adjust />
|
||||
</IconButton>
|
||||
|
||||
<IconButton
|
||||
sx={{ backgroundColor: currentTool === 'LineString' ? 'Highlight' : 'transparent' }}
|
||||
onClick={() => setCurrentTool('LineString')}>
|
||||
<Timeline />
|
||||
</IconButton>
|
||||
|
||||
<IconButton
|
||||
sx={{ backgroundColor: currentTool === 'Polygon' ? 'Highlight' : 'transparent' }}
|
||||
onClick={() => setCurrentTool('Polygon')}>
|
||||
<RectangleOutlined />
|
||||
</IconButton>
|
||||
|
||||
<IconButton
|
||||
sx={{ backgroundColor: currentTool === 'Circle' ? 'Highlight' : 'transparent' }}
|
||||
onClick={() => setCurrentTool('Circle')}>
|
||||
<CircleOutlined />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
<div ref={mapElement} style={{ width: '100%', height: '400px' }}></div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MapComponent
|
Reference in New Issue
Block a user