forked from VinokurovVE/tests
Map update
This commit is contained in:
@ -1,21 +1,30 @@
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { useCallback, 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, Select, Snap, Translate } from 'ol/interaction'
|
||||
import { OSM, Vector as VectorSource, XYZ } from 'ol/source'
|
||||
import { ImageStatic, OSM, Vector as VectorSource, XYZ } from 'ol/source'
|
||||
import { Tile as TileLayer, Vector as VectorLayer } from 'ol/layer'
|
||||
import { Divider, IconButton, Slider, Stack, Select as MUISelect, MenuItem, Box } from '@mui/material'
|
||||
import { Adjust, Api, CircleOutlined, OpenWith, RectangleOutlined, Rule, Straighten, Timeline, Undo, Warning } from '@mui/icons-material'
|
||||
import { Add, Adjust, Api, CircleOutlined, OpenWith, RectangleOutlined, Straighten, Timeline, Undo, Warning } from '@mui/icons-material'
|
||||
import { Type } from 'ol/geom/Geometry'
|
||||
import { click, noModifierKeys, shiftKeyOnly } from 'ol/events/condition'
|
||||
import { click, never, noModifierKeys, platformModifierKeyOnly, primaryAction, shiftKeyOnly } from 'ol/events/condition'
|
||||
import Feature from 'ol/Feature'
|
||||
import { SatelliteMapsProvider } from '../../interfaces/map'
|
||||
import { containsExtent } from 'ol/extent'
|
||||
import { boundingExtent, containsExtent, Extent, getBottomLeft, getBottomRight, getCenter, getHeight, getTopLeft, getTopRight, getWidth } from 'ol/extent'
|
||||
import { drawingLayerStyle, regionsLayerStyle, selectStyle } from './MapStyles'
|
||||
import { googleMapsSatelliteSource, regionsLayerSource, yandexMapsSatelliteSource } from './MapSources'
|
||||
import { mapCenter, mapExtent } from './MapConstants'
|
||||
import { mapCenter } from './MapConstants'
|
||||
import ImageLayer from 'ol/layer/Image'
|
||||
import VectorImageLayer from 'ol/layer/VectorImage'
|
||||
import { LineString, MultiPoint, Point, Polygon, SimpleGeometry } from 'ol/geom'
|
||||
import { fromExtent } from 'ol/geom/Polygon'
|
||||
import Collection from 'ol/Collection'
|
||||
import { Coordinate, distance, rotate } from 'ol/coordinate'
|
||||
import { Stroke, Fill, Circle as CircleStyle, Style } from 'ol/style'
|
||||
import { addCoordinateTransforms, addProjection, get, getTransform, Projection, transform } from 'ol/proj'
|
||||
import proj4 from 'proj4'
|
||||
|
||||
const MapComponent = () => {
|
||||
const mapElement = useRef<HTMLDivElement | null>(null)
|
||||
@ -42,10 +51,13 @@ const MapComponent = () => {
|
||||
},
|
||||
}))
|
||||
|
||||
const overlayLayer = useRef<VectorLayer | null>(null)
|
||||
const overlayLayerSource = useRef<VectorSource>(new VectorSource())
|
||||
|
||||
const drawingLayer = useRef<VectorLayer | null>(null)
|
||||
const drawingLayerSource = useRef<VectorSource>(new VectorSource())
|
||||
|
||||
const regionsLayer = useRef<VectorLayer>(new VectorLayer({
|
||||
const regionsLayer = useRef<VectorImageLayer>(new VectorImageLayer({
|
||||
source: regionsLayerSource,
|
||||
style: regionsLayerStyle
|
||||
}))
|
||||
@ -56,6 +68,8 @@ const MapComponent = () => {
|
||||
source: new OSM(),
|
||||
}))
|
||||
|
||||
const imageLayer = useRef<ImageLayer<ImageStatic>>(new ImageLayer())
|
||||
|
||||
const addInteractions = () => {
|
||||
if (currentTool) {
|
||||
draw.current = new Draw({
|
||||
@ -114,20 +128,474 @@ const MapComponent = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const style = new Style({
|
||||
geometry: function (feature) {
|
||||
const modifyGeometry = feature.get('modifyGeometry');
|
||||
return modifyGeometry ? modifyGeometry.geometry : feature.getGeometry();
|
||||
},
|
||||
fill: new Fill({
|
||||
color: 'rgba(255, 255, 255, 0.2)',
|
||||
}),
|
||||
stroke: new Stroke({
|
||||
color: '#ffcc33',
|
||||
width: 2,
|
||||
}),
|
||||
image: new CircleStyle({
|
||||
radius: 7,
|
||||
fill: new Fill({
|
||||
color: '#ffcc33',
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
function calculateCenter(geometry: SimpleGeometry) {
|
||||
let center, coordinates, minRadius;
|
||||
const type = geometry.getType();
|
||||
if (type === 'Polygon') {
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
let i = 0;
|
||||
coordinates = (geometry as Polygon).getCoordinates()[0].slice(1);
|
||||
coordinates.forEach(function (coordinate) {
|
||||
x += coordinate[0];
|
||||
y += coordinate[1];
|
||||
i++;
|
||||
});
|
||||
center = [x / i, y / i];
|
||||
} else if (type === 'LineString') {
|
||||
center = (geometry as LineString).getCoordinateAt(0.5);
|
||||
coordinates = geometry.getCoordinates();
|
||||
} else {
|
||||
center = getCenter(geometry.getExtent());
|
||||
}
|
||||
let sqDistances;
|
||||
if (coordinates) {
|
||||
sqDistances = coordinates.map(function (coordinate: Coordinate) {
|
||||
const dx = coordinate[0] - center[0];
|
||||
const dy = coordinate[1] - center[1];
|
||||
return dx * dx + dy * dy;
|
||||
});
|
||||
minRadius = Math.sqrt(Math.max.apply(Math, sqDistances)) / 3;
|
||||
} else {
|
||||
minRadius =
|
||||
Math.max(
|
||||
getWidth(geometry.getExtent()),
|
||||
getHeight(geometry.getExtent()),
|
||||
) / 3;
|
||||
}
|
||||
return {
|
||||
center: center,
|
||||
coordinates: coordinates,
|
||||
minRadius: minRadius,
|
||||
sqDistances: sqDistances,
|
||||
};
|
||||
}
|
||||
|
||||
function rotateProjection(projection, angle, extent) {
|
||||
function rotateCoordinate(coordinate, angle, anchor) {
|
||||
var coord = rotate(
|
||||
[coordinate[0] - anchor[0], coordinate[1] - anchor[1]],
|
||||
angle
|
||||
);
|
||||
return [coord[0] + anchor[0], coord[1] + anchor[1]];
|
||||
}
|
||||
|
||||
function rotateTransform(coordinate: Coordinate) {
|
||||
return rotateCoordinate(coordinate, angle, getCenter(extent));
|
||||
}
|
||||
|
||||
function normalTransform(coordinate: Coordinate) {
|
||||
return rotateCoordinate(coordinate, -angle, getCenter(extent));
|
||||
}
|
||||
|
||||
var normalProjection = get(projection);
|
||||
|
||||
var rotatedProjection = new Projection({
|
||||
code:
|
||||
normalProjection.getCode() +
|
||||
":" +
|
||||
angle.toString() +
|
||||
":" +
|
||||
extent.toString(),
|
||||
units: normalProjection.getUnits(),
|
||||
extent: extent
|
||||
});
|
||||
addProjection(rotatedProjection);
|
||||
|
||||
addCoordinateTransforms(
|
||||
"EPSG:4326",
|
||||
rotatedProjection,
|
||||
function (coordinate) {
|
||||
return rotateTransform(transform(coordinate, "EPSG:4326", projection));
|
||||
},
|
||||
function (coordinate) {
|
||||
return transform(normalTransform(coordinate), projection, "EPSG:4326");
|
||||
}
|
||||
);
|
||||
|
||||
addCoordinateTransforms(
|
||||
"EPSG:3857",
|
||||
rotatedProjection,
|
||||
function (coordinate) {
|
||||
return rotateTransform(transform(coordinate, "EPSG:3857", projection));
|
||||
},
|
||||
function (coordinate) {
|
||||
return transform(normalTransform(coordinate), projection, "EPSG:3857");
|
||||
}
|
||||
);
|
||||
|
||||
// also set up transforms with any projections defined using proj4
|
||||
if (typeof proj4 !== "undefined") {
|
||||
var projCodes = Object.keys(proj4.defs);
|
||||
projCodes.forEach(function (code) {
|
||||
var proj4Projection = get(code);
|
||||
if (!getTransform(proj4Projection, rotatedProjection)) {
|
||||
addCoordinateTransforms(
|
||||
proj4Projection,
|
||||
rotatedProjection,
|
||||
function (coordinate) {
|
||||
return rotateTransform(
|
||||
transform(coordinate, proj4Projection, projection)
|
||||
);
|
||||
},
|
||||
function (coordinate) {
|
||||
return transform(
|
||||
normalTransform(coordinate),
|
||||
projection,
|
||||
proj4Projection
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return rotatedProjection;
|
||||
}
|
||||
|
||||
const handleImageDrop = useCallback((event: any) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
const files = event.dataTransfer.files;
|
||||
if (files.length > 0) {
|
||||
const file = files[0];
|
||||
|
||||
if (file.type.startsWith('image/')) {
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = () => {
|
||||
const imageUrl = reader.result as string;
|
||||
const img = new Image();
|
||||
img.src = imageUrl;
|
||||
img.onload = () => {
|
||||
if (map.current) {
|
||||
const view = map.current.getView();
|
||||
const center = view.getCenter() || [0, 0];
|
||||
|
||||
const width = img.naturalWidth;
|
||||
const height = img.naturalHeight;
|
||||
const resolution = view.getResolution() || 0;
|
||||
|
||||
const extent = [
|
||||
center[0] - (width * resolution) / 20,
|
||||
center[1] - (height * resolution) / 20,
|
||||
center[0] + (width * resolution) / 20,
|
||||
center[1] + (height * resolution) / 20,
|
||||
];
|
||||
|
||||
// Create a polygon feature with the same extent as the image
|
||||
const polygonFeature = new Feature({
|
||||
geometry: fromExtent(extent),
|
||||
});
|
||||
|
||||
// Add the polygon feature to the drawing layer source
|
||||
overlayLayerSource.current?.addFeature(polygonFeature);
|
||||
|
||||
// Set up the initial image layer with the extent
|
||||
const imageSource = new ImageStatic({
|
||||
url: imageUrl,
|
||||
imageExtent: extent,
|
||||
});
|
||||
imageLayer.current.setSource(imageSource);
|
||||
|
||||
//map.current.addLayer(imageLayer.current);
|
||||
|
||||
// Add interactions for translation and scaling
|
||||
const translate = new Translate({
|
||||
layers: [imageLayer.current],
|
||||
features: new Collection([polygonFeature]),
|
||||
});
|
||||
|
||||
const defaultStyle = new Modify({ source: overlayLayerSource.current })
|
||||
.getOverlay()
|
||||
.getStyleFunction();
|
||||
|
||||
const modify = new Modify({
|
||||
insertVertexCondition: never,
|
||||
source: overlayLayerSource.current,
|
||||
condition: function (event) {
|
||||
return primaryAction(event) && !platformModifierKeyOnly(event);
|
||||
},
|
||||
deleteCondition: never,
|
||||
features: new Collection([polygonFeature]),
|
||||
style: function (feature) {
|
||||
feature.get('features').forEach(function (modifyFeature: Feature) {
|
||||
const modifyGeometry = modifyFeature.get('modifyGeometry')
|
||||
if (modifyGeometry) {
|
||||
const point = (feature.getGeometry() as Point).getCoordinates()
|
||||
let modifyPoint = modifyGeometry.point
|
||||
if (!modifyPoint) {
|
||||
// save the initial geometry and vertex position
|
||||
modifyPoint = point;
|
||||
modifyGeometry.point = modifyPoint;
|
||||
modifyGeometry.geometry0 = modifyGeometry.geometry;
|
||||
// get anchor and minimum radius of vertices to be used
|
||||
const result = calculateCenter(modifyGeometry.geometry0);
|
||||
modifyGeometry.center = result.center;
|
||||
modifyGeometry.minRadius = result.minRadius;
|
||||
}
|
||||
const center = modifyGeometry.center;
|
||||
const minRadius = modifyGeometry.minRadius;
|
||||
let dx, dy;
|
||||
dx = modifyPoint[0] - center[0];
|
||||
dy = modifyPoint[1] - center[1];
|
||||
const initialRadius = Math.sqrt(dx * dx + dy * dy);
|
||||
if (initialRadius > minRadius) {
|
||||
const initialAngle = Math.atan2(dy, dx);
|
||||
dx = point[0] - center[0];
|
||||
dy = point[1] - center[1];
|
||||
const currentRadius = Math.sqrt(dx * dx + dy * dy);
|
||||
if (currentRadius > 0) {
|
||||
const currentAngle = Math.atan2(dy, dx);
|
||||
const geometry = modifyGeometry.geometry0.clone();
|
||||
geometry.scale(currentRadius / initialRadius, undefined, center);
|
||||
geometry.rotate(currentAngle - initialAngle, center);
|
||||
modifyGeometry.geometry = geometry;
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
const res = map?.current?.getView()?.getResolution()
|
||||
if (typeof res === 'number' && feature && defaultStyle) {
|
||||
return defaultStyle(feature, res)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const calculateCentroid = (bottomLeft: Coordinate, topLeft: Coordinate, topRight: Coordinate, bottomRight: Coordinate) => {
|
||||
const x = (bottomLeft[0] + topLeft[0] + topRight[0] + bottomRight[0]) / 4;
|
||||
const y = (bottomLeft[1] + topLeft[1] + topRight[1] + bottomRight[1]) / 4;
|
||||
return [x, y];
|
||||
}
|
||||
|
||||
const calculateRotationAngle = (bottomLeft: Coordinate, bottomRight: Coordinate) => {
|
||||
// Calculate the difference in x and y coordinates between bottom right and bottom left
|
||||
const deltaX = bottomRight[0] - bottomLeft[0];
|
||||
const deltaY = bottomRight[1] - bottomLeft[1];
|
||||
|
||||
// Calculate the angle using atan2
|
||||
const angle = Math.atan2(deltaY, deltaX);
|
||||
|
||||
return angle;
|
||||
}
|
||||
|
||||
const calculateExtent = (bottomLeft: Coordinate, topLeft: Coordinate, topRight: Coordinate, bottomRight: Coordinate) => {
|
||||
const width = distance(bottomLeft, bottomRight);
|
||||
const height = distance(bottomLeft, topLeft);
|
||||
|
||||
// Calculate the centroid of the polygon
|
||||
const [centerX, centerY] = calculateCentroid(bottomLeft, topLeft, topRight, bottomRight);
|
||||
|
||||
// Define the extent based on the center and dimensions
|
||||
const extent = [
|
||||
centerX - width / 2, // minX
|
||||
centerY - height / 2, // minY
|
||||
centerX + width / 2, // maxX
|
||||
centerY + height / 2 // maxY
|
||||
];
|
||||
|
||||
return extent;
|
||||
}
|
||||
|
||||
// Function to update the image layer with a new source when extent changes
|
||||
const updateImageSource = () => {
|
||||
const newExtent = polygonFeature.getGeometry()?.getExtent();
|
||||
|
||||
const bottomLeft = polygonFeature.getGeometry()?.getCoordinates()[0][0]
|
||||
const topLeft = polygonFeature.getGeometry()?.getCoordinates()[0][1]
|
||||
const topRight = polygonFeature.getGeometry()?.getCoordinates()[0][2]
|
||||
const bottomRight = polygonFeature.getGeometry()?.getCoordinates()[0][3]
|
||||
|
||||
if (newExtent && bottomLeft && bottomRight && topRight && topLeft) {
|
||||
const originalExtent = calculateExtent(bottomLeft, topLeft, topRight, bottomRight)
|
||||
|
||||
const newImageSource = new ImageStatic({
|
||||
url: imageUrl,
|
||||
imageExtent: originalExtent,
|
||||
projection: rotateProjection('EPSG:3857', -calculateRotationAngle(bottomLeft, bottomRight), originalExtent)
|
||||
});
|
||||
imageLayer.current.setSource(newImageSource);
|
||||
}
|
||||
};
|
||||
|
||||
translate.on('translateend', updateImageSource);
|
||||
//modify.on('modifyend', updateImageSource);
|
||||
|
||||
modify.on('modifystart', function (event) {
|
||||
event.features.forEach(function (feature) {
|
||||
feature.set(
|
||||
'modifyGeometry',
|
||||
{ geometry: feature.getGeometry()?.clone() },
|
||||
true,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
modify.on('modifyend', function (event) {
|
||||
event.features.forEach(function (feature) {
|
||||
const modifyGeometry = feature.get('modifyGeometry');
|
||||
if (modifyGeometry) {
|
||||
feature.setGeometry(modifyGeometry.geometry);
|
||||
feature.unset('modifyGeometry', true);
|
||||
}
|
||||
})
|
||||
updateImageSource()
|
||||
})
|
||||
|
||||
map.current.addInteraction(translate);
|
||||
map.current.addInteraction(modify);
|
||||
}
|
||||
};
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
|
||||
function regionsInit() {
|
||||
map.current?.on('click', function (e) {
|
||||
if (selectedRegion.current !== null) {
|
||||
selectedRegion.current = null
|
||||
}
|
||||
|
||||
if (map.current) {
|
||||
map.current.forEachFeatureAtPixel(e.pixel, function (feature, layer) {
|
||||
if (layer === regionsLayer.current) {
|
||||
selectedRegion.current = feature as Feature
|
||||
// Zoom to the selected feature
|
||||
zoomToFeature(selectedRegion.current)
|
||||
|
||||
return true
|
||||
} else return false
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
// Show current selected region
|
||||
map.current?.on('pointermove', function (e) {
|
||||
if (selectedRegion.current !== null) {
|
||||
selectedRegion.current.setStyle(undefined)
|
||||
selectedRegion.current = null
|
||||
}
|
||||
|
||||
if (map.current) {
|
||||
map.current.forEachFeatureAtPixel(e.pixel, function (feature, layer) {
|
||||
if (layer === regionsLayer.current) {
|
||||
selectedRegion.current = feature as Feature
|
||||
selectedRegion.current.setStyle(selectStyle)
|
||||
|
||||
if (feature.get('district')) {
|
||||
setStatusText(feature.get('district'))
|
||||
}
|
||||
|
||||
return true
|
||||
} else return false
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// Hide regions layer when fully visible
|
||||
map.current?.on('moveend', function () {
|
||||
const viewExtent = map.current?.getView().calculateExtent(map.current.getSize())
|
||||
const features = regionsLayer.current.getSource()?.getFeatures()
|
||||
|
||||
let isViewCovered = false
|
||||
|
||||
features?.forEach((feature: Feature) => {
|
||||
const featureExtent = feature?.getGeometry()?.getExtent()
|
||||
if (viewExtent && featureExtent) {
|
||||
if (containsExtent(featureExtent, viewExtent)) {
|
||||
isViewCovered = true
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
regionsLayer.current.setVisible(!isViewCovered)
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
drawingLayer.current = new VectorLayer({
|
||||
source: drawingLayerSource.current,
|
||||
style: drawingLayerStyle,
|
||||
style: drawingLayerStyle
|
||||
})
|
||||
|
||||
overlayLayer.current = new VectorLayer({
|
||||
source: overlayLayerSource.current,
|
||||
style: function (feature) {
|
||||
const styles = [style]
|
||||
const modifyGeometry = feature.get('modifyGeometry')
|
||||
const geometry = modifyGeometry ? modifyGeometry.geometry : feature.getGeometry()
|
||||
const result = calculateCenter(geometry)
|
||||
const center = result.center
|
||||
if (center) {
|
||||
styles.push(
|
||||
new Style({
|
||||
geometry: new Point(center),
|
||||
image: new CircleStyle({
|
||||
radius: 4,
|
||||
fill: new Fill({
|
||||
color: '#ff3333'
|
||||
})
|
||||
})
|
||||
})
|
||||
)
|
||||
const coordinates = result.coordinates
|
||||
if (coordinates) {
|
||||
const minRadius = result.minRadius
|
||||
const sqDistances = result.sqDistances
|
||||
const rsq = minRadius * minRadius
|
||||
if (Array.isArray(sqDistances)) {
|
||||
const points = coordinates.filter(function (coordinate, index) {
|
||||
return sqDistances[index] > rsq
|
||||
})
|
||||
styles.push(
|
||||
new Style({
|
||||
geometry: new MultiPoint(points),
|
||||
image: new CircleStyle({
|
||||
radius: 4,
|
||||
fill: new Fill({
|
||||
color: '#33cc33'
|
||||
})
|
||||
})
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
return styles
|
||||
},
|
||||
})
|
||||
|
||||
map.current = new Map({
|
||||
layers: [baseLayer.current, satLayer.current, regionsLayer.current, drawingLayer.current],
|
||||
layers: [baseLayer.current, satLayer.current, regionsLayer.current, drawingLayer.current, imageLayer.current, overlayLayer.current],
|
||||
target: mapElement.current as HTMLDivElement,
|
||||
view: new View({
|
||||
center: mapCenter,
|
||||
zoom: 2,
|
||||
maxZoom: 21,
|
||||
extent: mapExtent,
|
||||
//extent: mapExtent,
|
||||
}),
|
||||
})
|
||||
|
||||
@ -148,65 +616,22 @@ const MapComponent = () => {
|
||||
|
||||
loadFeatures()
|
||||
|
||||
// Show current selected region
|
||||
map.current.on('pointermove', function (e) {
|
||||
if (selectedRegion.current !== null) {
|
||||
selectedRegion.current.setStyle(undefined)
|
||||
selectedRegion.current = null
|
||||
}
|
||||
regionsInit()
|
||||
|
||||
if (map.current) {
|
||||
map.current.forEachFeatureAtPixel(e.pixel, function (f) {
|
||||
selectedRegion.current = f as Feature
|
||||
selectedRegion.current.setStyle(selectStyle)
|
||||
|
||||
if (f.get('district')) {
|
||||
setStatusText(f.get('district'))
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
map.current.on('click', function (e) {
|
||||
if (selectedRegion.current !== null) {
|
||||
selectedRegion.current = null
|
||||
}
|
||||
|
||||
if (map.current) {
|
||||
map.current.forEachFeatureAtPixel(e.pixel, function (f) {
|
||||
selectedRegion.current = f as Feature
|
||||
// Zoom to the selected feature
|
||||
zoomToFeature(selectedRegion.current)
|
||||
|
||||
return true
|
||||
});
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
// Hide regions layer when fully visible
|
||||
map.current.on('moveend', function () {
|
||||
const viewExtent = map.current?.getView().calculateExtent(map.current.getSize())
|
||||
const features = regionsLayer.current.getSource()?.getFeatures()
|
||||
|
||||
let isViewCovered = false
|
||||
|
||||
features?.forEach((feature: Feature) => {
|
||||
const featureExtent = feature?.getGeometry()?.getExtent()
|
||||
if (viewExtent && featureExtent) {
|
||||
if (containsExtent(featureExtent, viewExtent)) {
|
||||
isViewCovered = true
|
||||
}
|
||||
}
|
||||
if (mapElement.current) {
|
||||
mapElement.current.addEventListener('dragover', (e) => {
|
||||
e.preventDefault()
|
||||
})
|
||||
|
||||
regionsLayer.current.setVisible(!isViewCovered)
|
||||
})
|
||||
mapElement.current.addEventListener('drop', handleImageDrop)
|
||||
}
|
||||
|
||||
return () => {
|
||||
map?.current?.setTarget(undefined)
|
||||
|
||||
if (mapElement.current) {
|
||||
mapElement.current.removeEventListener('drop', handleImageDrop)
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
|
||||
@ -249,6 +674,11 @@ const MapComponent = () => {
|
||||
|
||||
return (
|
||||
<Stack flex={1} flexDirection='column'>
|
||||
<Stack my={1} spacing={1} direction='row' divider={<Divider orientation='vertical' flexItem />}>
|
||||
<IconButton title='Добавить подложку'>
|
||||
<Add />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
<Stack my={1} spacing={1} direction='row' divider={<Divider orientation='vertical' flexItem />}>
|
||||
|
||||
<Stack flex={1} alignItems='center' justifyContent='center'>
|
||||
|
Reference in New Issue
Block a user