map interaction fixes; MapPrint cleanup; MapToolbar - add zoom, enable ruler for all modes;
This commit is contained in:
@ -4,11 +4,10 @@ import { clearPrintArea, PrintScale, setPreviousView, setPrintScale, setPrintSca
|
|||||||
import { PrintFormat, PrintOrientation, printResolutions, setPrintOrientation, setPrintResolution, usePrintStore } from '../../../store/print'
|
import { PrintFormat, PrintOrientation, printResolutions, setPrintOrientation, setPrintResolution, usePrintStore } from '../../../store/print'
|
||||||
import { printDimensions, scaleOptions } from '../../../constants/map'
|
import { printDimensions, scaleOptions } from '../../../constants/map'
|
||||||
import { useObjectsStore } from '../../../store/objects'
|
import { useObjectsStore } from '../../../store/objects'
|
||||||
// import { getPointResolution } from 'ol/proj'
|
|
||||||
import jsPDF from 'jspdf'
|
import jsPDF from 'jspdf'
|
||||||
import { getCenter } from 'ol/extent'
|
import { getCenter } from 'ol/extent'
|
||||||
import ScaleLine from 'ol/control/ScaleLine'
|
import ScaleLine from 'ol/control/ScaleLine'
|
||||||
import { Button, Checkbox, Dialog, DialogActions, DialogBody, DialogContent, DialogSurface, DialogTitle, Dropdown, Field, Option, Radio, RadioGroup, Text } from '@fluentui/react-components'
|
import { Button, Checkbox, Dialog, DialogActions, DialogBody, DialogContent, DialogSurface, DialogTitle, Dropdown, Field, Option, Radio, RadioGroup } from '@fluentui/react-components'
|
||||||
import { Dismiss24Regular } from '@fluentui/react-icons'
|
import { Dismiss24Regular } from '@fluentui/react-icons'
|
||||||
|
|
||||||
const MapPrint = ({
|
const MapPrint = ({
|
||||||
@ -46,16 +45,6 @@ const MapPrint = ({
|
|||||||
const scaleFactor = width / originalSize[0]
|
const scaleFactor = width / originalSize[0]
|
||||||
const newResolution = originalResolution / scaleFactor
|
const newResolution = originalResolution / scaleFactor
|
||||||
|
|
||||||
// console.log(`New resolution: ${newResolution}`)
|
|
||||||
|
|
||||||
// const center = map.getView().getCenter()
|
|
||||||
// let scaleResolution = 1
|
|
||||||
// if (center) {
|
|
||||||
// scaleResolution = Number(printScale) / getPointResolution(map.getView().getProjection(), Number(resolution) / 25.4, center)
|
|
||||||
// // console.log(`Scaled resolution: ${scaleResolution}`)
|
|
||||||
// }
|
|
||||||
|
|
||||||
console.log(width, height)
|
|
||||||
// Set new high-resolution rendering
|
// Set new high-resolution rendering
|
||||||
map.setSize([width, height])
|
map.setSize([width, height])
|
||||||
map.getView().setResolution(newResolution)
|
map.getView().setResolution(newResolution)
|
||||||
@ -120,7 +109,6 @@ const MapPrint = ({
|
|||||||
|
|
||||||
const [opened, setOpened] = useState(false)
|
const [opened, setOpened] = useState(false)
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (printArea && opened) {
|
if (printArea && opened) {
|
||||||
// backup view before entering print mode
|
// backup view before entering print mode
|
||||||
@ -160,7 +148,7 @@ const MapPrint = ({
|
|||||||
}, [opened])
|
}, [opened])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={opened} defaultOpen={true}>
|
<Dialog open={opened}>
|
||||||
<DialogSurface style={{ maxWidth: fullscreen ? '100%' : 'fit-content', maxHeight: fullscreen ? '100%' : 'fit-content' }}>
|
<DialogSurface style={{ maxWidth: fullscreen ? '100%' : 'fit-content', maxHeight: fullscreen ? '100%' : 'fit-content' }}>
|
||||||
<DialogBody>
|
<DialogBody>
|
||||||
<DialogTitle action={
|
<DialogTitle action={
|
||||||
@ -193,7 +181,6 @@ const MapPrint = ({
|
|||||||
|
|
||||||
<Field label="Разрешение">
|
<Field label="Разрешение">
|
||||||
<Dropdown
|
<Dropdown
|
||||||
defaultValue={printResolution.toString()}
|
|
||||||
value={printResolution.toString()}
|
value={printResolution.toString()}
|
||||||
selectedOptions={[printResolution.toString()]}
|
selectedOptions={[printResolution.toString()]}
|
||||||
onOptionSelect={(_, data) => setPrintResolution(Number(data.optionValue))}
|
onOptionSelect={(_, data) => setPrintResolution(Number(data.optionValue))}
|
||||||
@ -242,112 +229,6 @@ const MapPrint = ({
|
|||||||
</DialogSurface>
|
</DialogSurface>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
)
|
)
|
||||||
|
|
||||||
// return (
|
|
||||||
// <div
|
|
||||||
// style={{
|
|
||||||
// display: opened ? 'flex' : 'none',
|
|
||||||
// position: fullscreen ? 'fixed' : 'fixed',
|
|
||||||
// zIndex: '9999',
|
|
||||||
// width: '100%',
|
|
||||||
// height: '100%',
|
|
||||||
// inset: 0,
|
|
||||||
// justifyContent: 'center',
|
|
||||||
// alignItems: 'center',
|
|
||||||
// }}
|
|
||||||
// >
|
|
||||||
// <div style={{
|
|
||||||
// display: 'flex',
|
|
||||||
// flexDirection: 'column',
|
|
||||||
// transition: 'all .3s ease',
|
|
||||||
// width: fullscreen ? '100%' : 'auto',
|
|
||||||
// height: fullscreen ? '100%' : 'fit-content',
|
|
||||||
// background: 'var(--colorNeutralBackground1)',
|
|
||||||
// border: '1px solid var(--colorNeutralShadowKey)',
|
|
||||||
// }}>
|
|
||||||
// <div style={{ display: 'flex', padding: '1rem', alignItems: 'center' }}>
|
|
||||||
// <Text>
|
|
||||||
// Предпросмотр области печати
|
|
||||||
// </Text>
|
|
||||||
|
|
||||||
// <div style={{ display: 'flex', marginLeft: 'auto', gap: '1.5rem' }}>
|
|
||||||
// <Button appearance='subtle' title='Помощь' style={{ marginLeft: 'auto' }} icon={<IconHelp color='gray' />} />
|
|
||||||
|
|
||||||
// <Button appearance='subtle' title={fullscreen ? 'Свернуть' : 'Развернуть'} style={{ marginLeft: 'auto' }} icon={fullscreen ? <IconWindowMinimize color='gray' /> : <IconWindowMaximize color='gray' />} onClick={() => setFullscreen(!fullscreen)} />
|
|
||||||
|
|
||||||
// <Button appearance='subtle' title='Закрыть' icon={<IconX />} onClick={() => setOpened(false)} />
|
|
||||||
// </div>
|
|
||||||
// </div>
|
|
||||||
|
|
||||||
// <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', height: 'fit-content', overflow: 'auto' }}>
|
|
||||||
// <Text>Область печати можно передвигать.</Text>
|
|
||||||
|
|
||||||
// <div id='print-portal' style={{
|
|
||||||
// width: printOrientation === 'horizontal' ? '594px' : '420px',
|
|
||||||
// height: printOrientation === 'horizontal' ? '420px' : '594px',
|
|
||||||
// flexShrink: '0'
|
|
||||||
// }}>
|
|
||||||
|
|
||||||
// </div>
|
|
||||||
|
|
||||||
// <div style={{ display: 'flex', width: '100%', flexWrap: 'wrap', gap: '1rem', padding: '1rem', justifyContent: 'space-between', alignItems: 'flex-start' }}>
|
|
||||||
// <Field label={'Ориентация'}>
|
|
||||||
// <RadioGroup value={printOrientation} onChange={(_, data) => setPrintOrientation(data.value as PrintOrientation)}>
|
|
||||||
// <Radio value='horizontal' label='Горизонтальная' />
|
|
||||||
// <Radio value='vertical' label='Вертикальная' />
|
|
||||||
// </RadioGroup>
|
|
||||||
// </Field>
|
|
||||||
|
|
||||||
// <Field label="Разрешение">
|
|
||||||
// <Dropdown
|
|
||||||
// defaultValue={printResolution.toString()}
|
|
||||||
// value={printResolution.toString()}
|
|
||||||
// selectedOptions={[printResolution.toString()]}
|
|
||||||
// onOptionSelect={(_, data) => setPrintResolution(Number(data.optionValue))}
|
|
||||||
// >
|
|
||||||
// {printResolutions.map((res) => (
|
|
||||||
// <Option key={res} text={res} value={res}>
|
|
||||||
// {res}
|
|
||||||
// </Option>
|
|
||||||
// ))}
|
|
||||||
// </Dropdown>
|
|
||||||
// </Field>
|
|
||||||
|
|
||||||
|
|
||||||
// <Field label="Масштаб">
|
|
||||||
// <Dropdown
|
|
||||||
// value={printScale.toString()}
|
|
||||||
// selectedOptions={[printScale]}
|
|
||||||
// onOptionSelect={(_, data) => setPrintScale(id, data.optionValue as PrintScale)}
|
|
||||||
// >
|
|
||||||
// {scaleOptions.map((opt) => (
|
|
||||||
// <Option key={opt.value} text={opt.label} value={opt.value}>
|
|
||||||
// {opt.label}
|
|
||||||
// </Option>
|
|
||||||
// ))}
|
|
||||||
// </Dropdown>
|
|
||||||
// </Field>
|
|
||||||
|
|
||||||
// <Checkbox
|
|
||||||
// checked={printScaleLine}
|
|
||||||
// label="Масштабная линия"
|
|
||||||
// onChange={(event) => setPrintScaleLine(id, event.currentTarget.checked)}
|
|
||||||
// />
|
|
||||||
// </div>
|
|
||||||
|
|
||||||
// <div style={{ display: 'flex', width: '100%', gap: '1rem', padding: '1rem', alignItems: 'center' }}>
|
|
||||||
// <Button style={{ marginLeft: 'auto' }} onClick={() => {
|
|
||||||
// if (previousView) {
|
|
||||||
// exportToPDF(printFormat, printResolution, printOrientation)
|
|
||||||
// }
|
|
||||||
// }}>
|
|
||||||
// Печать
|
|
||||||
// </Button>
|
|
||||||
// </div>
|
|
||||||
// </div>
|
|
||||||
// </div>
|
|
||||||
// </div>
|
|
||||||
// )
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MapPrint
|
export default MapPrint
|
@ -1,63 +1,101 @@
|
|||||||
import { IconArrowBackUp, IconArrowsMove, IconCircle, IconExclamationCircle, IconLine, IconPoint, IconPolygon, IconRuler, IconTransformPoint } from '@tabler/icons-react'
|
import { IconArrowBackUp, IconArrowsMove, IconCircle, IconExclamationCircle, IconLine, IconPoint, IconPolygon, IconTransformPoint } from '@tabler/icons-react'
|
||||||
import { getDraw, setCurrentTool, useMapStore } from '../../../store/map';
|
import { getDraw, setCurrentTool, useMapStore } from '../../../store/map';
|
||||||
import { saveFeatures } from '../mapUtils';
|
import { saveFeatures } from '../mapUtils';
|
||||||
import { Button, Tooltip } from '@fluentui/react-components';
|
import { Button, Tooltip } from '@fluentui/react-components';
|
||||||
import { useAppStore } from '../../../store/app';
|
import { useAppStore } from '../../../store/app';
|
||||||
|
import { useObjectsStore } from '../../../store/objects';
|
||||||
|
import { AddFilled, RulerRegular, SubtractFilled } from '@fluentui/react-icons';
|
||||||
|
|
||||||
const MapToolbar = ({
|
const MapToolbar = ({
|
||||||
map_id
|
map_id
|
||||||
}: { map_id: string }) => {
|
}: { map_id: string }) => {
|
||||||
const { currentTool } = useMapStore().id[map_id]
|
const { currentTool, mode, map } = useMapStore().id[map_id]
|
||||||
|
const { selectedRegion, selectedDistrict, selectedYear } = useObjectsStore().id[map_id]
|
||||||
const { colorScheme } = useAppStore();
|
const { colorScheme } = useAppStore();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ display: 'flex' }}>
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', zIndex: 1, backdropFilter: 'blur(8px)', backgroundColor: colorScheme === 'light' ? '#FFFFFFAA' : '#000000AA', borderRadius: '4px' }}>
|
<div style={{ display: 'flex', flexDirection: 'column', zIndex: 1, backdropFilter: 'blur(8px)', backgroundColor: colorScheme === 'light' ? '#FFFFFFAA' : '#000000AA', borderRadius: '4px' }}>
|
||||||
<Button icon={<IconExclamationCircle />} appearance='transparent' onClick={() => saveFeatures(map_id)} />
|
{selectedRegion && selectedDistrict && selectedYear && mode === 'edit' &&
|
||||||
|
<>
|
||||||
|
<Button icon={<IconExclamationCircle />} appearance='transparent' onClick={() => saveFeatures(map_id)} />
|
||||||
|
|
||||||
<Tooltip content={"Отмена"} relationship='label' hideDelay={0} showDelay={0} withArrow>
|
<Tooltip content={"Отмена"} relationship='label' hideDelay={0} showDelay={0} withArrow>
|
||||||
<Button icon={<IconArrowBackUp />} appearance='transparent' onClick={() => getDraw(map_id)?.removeLastPoint()} />
|
<Button icon={<IconArrowBackUp />} appearance='transparent' onClick={() => getDraw(map_id)?.removeLastPoint()} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<Tooltip content={"Редактировать"} relationship='label' hideDelay={0} showDelay={0} withArrow>
|
<Tooltip content={"Редактировать"} relationship='label' hideDelay={0} showDelay={0} withArrow>
|
||||||
<Button icon={<IconTransformPoint />} appearance={currentTool === 'Edit' ? 'primary' : 'transparent'} onClick={() => {
|
<Button icon={<IconTransformPoint />} appearance={currentTool === 'Edit' ? 'primary' : 'transparent'} onClick={() => {
|
||||||
setCurrentTool(map_id, 'Edit')
|
setCurrentTool(map_id, 'Edit')
|
||||||
}} />
|
}} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<Tooltip content={"Точка"} relationship='label' hideDelay={0} showDelay={0} withArrow>
|
<Tooltip content={"Точка"} relationship='label' hideDelay={0} showDelay={0} withArrow>
|
||||||
<Button icon={<IconPoint />} appearance={currentTool === 'Point' ? 'primary' : 'transparent'} onClick={() => {
|
<Button icon={<IconPoint />} appearance={currentTool === 'Point' ? 'primary' : 'transparent'} onClick={() => {
|
||||||
setCurrentTool(map_id, 'Point')
|
setCurrentTool(map_id, 'Point')
|
||||||
|
}} />
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
<Tooltip content={"Линия"} relationship='label' hideDelay={0} showDelay={0} withArrow>
|
||||||
|
<Button icon={<IconLine />} appearance={currentTool === 'LineString' ? 'primary' : 'transparent'} onClick={() => {
|
||||||
|
setCurrentTool(map_id, 'LineString')
|
||||||
|
}} />
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
<Tooltip content={"Многоугольник"} relationship='label' hideDelay={0} showDelay={0} withArrow>
|
||||||
|
<Button icon={<IconPolygon />} appearance={currentTool === 'Polygon' ? 'primary' : 'transparent'} onClick={() => {
|
||||||
|
setCurrentTool(map_id, 'Polygon')
|
||||||
|
}} />
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
<Tooltip content={"Окружность"} relationship='label' hideDelay={0} showDelay={0} withArrow>
|
||||||
|
<Button icon={<IconCircle />} appearance={currentTool === 'Circle' ? 'primary' : 'transparent'} onClick={() => {
|
||||||
|
setCurrentTool(map_id, 'Circle')
|
||||||
|
}} />
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
<Tooltip content={"Перемещение"} relationship='label' hideDelay={0} showDelay={0} withArrow>
|
||||||
|
<Button icon={<IconArrowsMove />} appearance={currentTool === 'Mover' ? 'primary' : 'transparent'} onClick={() => {
|
||||||
|
setCurrentTool(map_id, 'Mover')
|
||||||
|
}} />
|
||||||
|
</Tooltip>
|
||||||
|
</>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column', zIndex: 1, backdropFilter: 'blur(8px)', backgroundColor: colorScheme === 'light' ? '#FFFFFFAA' : '#000000AA', borderRadius: '4px' }}>
|
||||||
|
<Tooltip content={"Приблизить"} relationship='label' hideDelay={0} showDelay={0} withArrow>
|
||||||
|
<Button icon={<AddFilled />} appearance={'transparent'} onClick={() => {
|
||||||
|
const currentZoom = map?.getView().getZoom()
|
||||||
|
if (currentZoom) {
|
||||||
|
// map?.getView().setZoom(currentZoom + 1)
|
||||||
|
map?.getView().animate({
|
||||||
|
zoom: currentZoom + 1,
|
||||||
|
duration: 100
|
||||||
|
})
|
||||||
|
}
|
||||||
}} />
|
}} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
|
|
||||||
<Tooltip content={"Линия"} relationship='label' hideDelay={0} showDelay={0} withArrow>
|
<Tooltip content={"Отдалить"} relationship='label' hideDelay={0} showDelay={0} withArrow>
|
||||||
<Button icon={<IconLine />} appearance={currentTool === 'LineString' ? 'primary' : 'transparent'} onClick={() => {
|
<Button icon={<SubtractFilled />} appearance={'transparent'} onClick={() => {
|
||||||
setCurrentTool(map_id, 'LineString')
|
const currentZoom = map?.getView().getZoom()
|
||||||
|
if (currentZoom) {
|
||||||
|
// map?.getView().setZoom(currentZoom - 1)
|
||||||
|
map?.getView().animate({
|
||||||
|
zoom: currentZoom - 1,
|
||||||
|
duration: 100
|
||||||
|
})
|
||||||
|
}
|
||||||
}} />
|
}} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<Tooltip content={"Многоугольник"} relationship='label' hideDelay={0} showDelay={0} withArrow>
|
|
||||||
<Button icon={<IconPolygon />} appearance={currentTool === 'Polygon' ? 'primary' : 'transparent'} onClick={() => {
|
|
||||||
setCurrentTool(map_id, 'Polygon')
|
|
||||||
}} />
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<Tooltip content={"Окружность"} relationship='label' hideDelay={0} showDelay={0} withArrow>
|
</div>
|
||||||
<Button icon={<IconCircle />} appearance={currentTool === 'Circle' ? 'primary' : 'transparent'} onClick={() => {
|
|
||||||
setCurrentTool(map_id, 'Circle')
|
|
||||||
}} />
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<Tooltip content={"Перемещение"} relationship='label' hideDelay={0} showDelay={0} withArrow>
|
|
||||||
<Button icon={<IconArrowsMove />} appearance={currentTool === 'Mover' ? 'primary' : 'transparent'} onClick={() => {
|
|
||||||
setCurrentTool(map_id, 'Mover')
|
|
||||||
}} />
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column', zIndex: 1, backdropFilter: 'blur(8px)', backgroundColor: colorScheme === 'light' ? '#FFFFFFAA' : '#000000AA', borderRadius: '4px' }}>
|
||||||
<Tooltip content={"Линейка"} relationship='label' hideDelay={0} showDelay={0} withArrow>
|
<Tooltip content={"Линейка"} relationship='label' hideDelay={0} showDelay={0} withArrow>
|
||||||
<Button icon={<IconRuler />} appearance={currentTool === 'Measure' ? 'primary' : 'transparent'} onClick={() => {
|
<Button icon={<RulerRegular />} appearance={currentTool === 'Measure' ? 'primary' : 'transparent'} onClick={() => {
|
||||||
setCurrentTool(map_id, 'Measure')
|
setCurrentTool(map_id, 'Measure')
|
||||||
}} />
|
}} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
@ -125,6 +125,7 @@ export const initializeMapState = (
|
|||||||
lineSelect.on('select', (e) => {
|
lineSelect.on('select', (e) => {
|
||||||
if (e.selected[0]) {
|
if (e.selected[0]) {
|
||||||
setCurrentObjectId(id, e.selected[0].get('object_id'))
|
setCurrentObjectId(id, e.selected[0].get('object_id'))
|
||||||
|
zoomToFeature(id, e.selected[0])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -135,6 +136,7 @@ export const initializeMapState = (
|
|||||||
figureSelect.on('select', (e) => {
|
figureSelect.on('select', (e) => {
|
||||||
if (e.selected[0]) {
|
if (e.selected[0]) {
|
||||||
setCurrentObjectId(id, e.selected[0].get('object_id'))
|
setCurrentObjectId(id, e.selected[0].get('object_id'))
|
||||||
|
zoomToFeature(id, e.selected[0])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const figureHover = new Select({ condition: pointerMove, style: highlightStyleYellow, hitTolerance: hitTolerance, layers: (layer) => layer.get('type') === 'figure', })
|
const figureHover = new Select({ condition: pointerMove, style: highlightStyleYellow, hitTolerance: hitTolerance, layers: (layer) => layer.get('type') === 'figure', })
|
||||||
@ -323,7 +325,7 @@ export const initializeMapState = (
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
setStatusText(id, "");
|
setStatusText(id, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -362,7 +364,8 @@ export const initializeMapState = (
|
|||||||
setSelectedRegion(id, feature.get('entity_id'))
|
setSelectedRegion(id, feature.get('entity_id'))
|
||||||
|
|
||||||
//regionsLayer.setVisible(false)
|
//regionsLayer.setVisible(false)
|
||||||
regionsLayer.setOpacity(0)
|
//regionsLayer.setOpacity(0)
|
||||||
|
map.removeInteraction(regionSelect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,6 +374,8 @@ export const initializeMapState = (
|
|||||||
|
|
||||||
if (feature.get('entity_id')) {
|
if (feature.get('entity_id')) {
|
||||||
setSelectedDistrict(id, feature.get('entity_id'))
|
setSelectedDistrict(id, feature.get('entity_id'))
|
||||||
|
|
||||||
|
map.removeInteraction(districtSelect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user