|
|
|
@ -8,11 +8,17 @@ import {
|
|
|
|
|
flightlayerWayPoint, |
|
|
|
|
flightlayerPolyline, |
|
|
|
|
flightlayerPolygon, |
|
|
|
|
flightlayerBuffer |
|
|
|
|
flightlayerBuffer, |
|
|
|
|
handlerStartMode, |
|
|
|
|
handlerDrawEvents, |
|
|
|
|
getDintancePointPopupList |
|
|
|
|
} from '../../utility/MapUtils'; |
|
|
|
|
import { useHistory } from 'react-router-dom'; |
|
|
|
|
import useMapType from '@hooks/useMapType'; |
|
|
|
|
import { clientSaveAreaCoordinateList } from '@src/redux/features/laanc/laancSlice'; |
|
|
|
|
import { |
|
|
|
|
clientSaveAreaCoordinateList, |
|
|
|
|
clientChangeDrawType |
|
|
|
|
} from '@src/redux/features/laanc/laancSlice'; |
|
|
|
|
import { MapControl } from '../../components/map/MapControl'; |
|
|
|
|
import { clientSetIsMapLoading } from '@src/redux/features/laanc/laancSlice'; |
|
|
|
|
import { clientMapInit } from '@src/redux/features/control/map/mapSlice'; |
|
|
|
@ -28,6 +34,8 @@ import { FiRotateCw, FiCornerUpLeft } from 'react-icons/fi';
|
|
|
|
|
import { X } from 'react-feather'; |
|
|
|
|
import mapboxgl from 'mapbox-gl'; |
|
|
|
|
|
|
|
|
|
let distanceMarkers = []; |
|
|
|
|
|
|
|
|
|
export default function ControlApprovalsContainer({ mode }) { |
|
|
|
|
const dispatch = useDispatch(); |
|
|
|
|
const history = useHistory(); |
|
|
|
@ -41,7 +49,7 @@ export default function ControlApprovalsContainer({ mode }) {
|
|
|
|
|
// 지도
|
|
|
|
|
const [mapObject, setMapObject] = useState(); |
|
|
|
|
const [setMapType] = useMapType(); |
|
|
|
|
const { areaCoordList, isOpenModal } = useSelector(state => state.laancState); |
|
|
|
|
const { areaCoordList, drawType } = useSelector(state => state.laancState); |
|
|
|
|
|
|
|
|
|
const [startDate, setStartDate] = useState(dayjs().format('YYYY-MM-DD')); |
|
|
|
|
const [endDate, setEndDate] = useState(dayjs().format('YYYY-MM-DD')); |
|
|
|
@ -68,6 +76,14 @@ export default function ControlApprovalsContainer({ mode }) {
|
|
|
|
|
// 비행구역 데이터블록
|
|
|
|
|
const [dataBlocks, setDataBlocks] = useState([]); |
|
|
|
|
|
|
|
|
|
// 거리측정
|
|
|
|
|
const [isDistanceRevert, setIsDistanceRevert] = useState(true); |
|
|
|
|
const [isResetDisabled, setIsResetDisabled] = useState(true); |
|
|
|
|
const totalDistanceRef = useRef(null); |
|
|
|
|
const totalAreaRef = useRef(null); |
|
|
|
|
const mouseCursorRef = useRef(null); |
|
|
|
|
const distanceBoxRef = useRef(null); |
|
|
|
|
|
|
|
|
|
// 비행구역 (관제과) 레이어
|
|
|
|
|
const controlLayer = { |
|
|
|
|
type: 'FeatureCollection', |
|
|
|
@ -375,6 +391,155 @@ export default function ControlApprovalsContainer({ mode }) {
|
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const handlerDrawTypeChange = (e, val) => { |
|
|
|
|
drawObj.deleteAll(); |
|
|
|
|
distanceMarkers.map(i => i.remove()); |
|
|
|
|
setIsResetDisabled(true); |
|
|
|
|
distanceBoxRef.current.style.display = 'block'; |
|
|
|
|
totalDistanceRef.current.innerText = ''; |
|
|
|
|
totalAreaRef.current.innerText = ''; |
|
|
|
|
dispatch(clientChangeDrawType(val)); |
|
|
|
|
handlerStartMode(val, drawObj); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const handlerDrawObjInit = (obj, mapInstance) => { |
|
|
|
|
setDrawObj(obj); |
|
|
|
|
|
|
|
|
|
handlerDrawEvents( |
|
|
|
|
mapInstance, |
|
|
|
|
handlerDrawPopup, |
|
|
|
|
handlerDrawEnd, |
|
|
|
|
{ |
|
|
|
|
totalDistanceRef, |
|
|
|
|
mouseCursorRef, |
|
|
|
|
totalAreaRef |
|
|
|
|
}, |
|
|
|
|
obj |
|
|
|
|
); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const handlerMapTypeChange = val => { |
|
|
|
|
handlerDistanceClose(); |
|
|
|
|
setMapType(val); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const handlerDistanceClose = () => { |
|
|
|
|
drawObj.deleteAll(); |
|
|
|
|
distanceMarkers.map(i => i.remove()); |
|
|
|
|
dispatch(clientChangeDrawType('simple_select')); |
|
|
|
|
drawObj.changeMode('simple_select'); |
|
|
|
|
totalDistanceRef.current.innerText = ''; |
|
|
|
|
mouseCursorRef.current.style.display = 'none'; |
|
|
|
|
distanceBoxRef.current.style.display = 'none'; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const handlerDrawReset = () => { |
|
|
|
|
drawObj.deleteAll(); |
|
|
|
|
distanceMarkers.map(i => i.remove()); |
|
|
|
|
if (drawType === 'LINE') { |
|
|
|
|
drawObj.changeMode('draw_line_string'); |
|
|
|
|
} else { |
|
|
|
|
drawObj.changeMode('draw_polygon'); |
|
|
|
|
totalAreaRef.current.style.display = 'none'; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
totalDistanceRef.current.style.display = 'none'; |
|
|
|
|
setIsResetDisabled(true); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const handlerDrawEnd = featuresLength => { |
|
|
|
|
if (!featuresLength) { |
|
|
|
|
dispatch(clientChangeDrawType('simple_select')); |
|
|
|
|
totalDistanceRef.current.innerText = ''; |
|
|
|
|
mouseCursorRef.current.style.display = 'none'; |
|
|
|
|
distanceBoxRef.current.style.display = 'none'; |
|
|
|
|
} else { |
|
|
|
|
setIsResetDisabled(false); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const handlerDistanceRevert = () => { |
|
|
|
|
if (drawObj.getMode() === 'draw_line_string') { |
|
|
|
|
const allFeatures = drawObj.getAll(); |
|
|
|
|
if (allFeatures.features.length > 0) { |
|
|
|
|
drawObj.deleteAll(); |
|
|
|
|
const coords = allFeatures.features[0].geometry.coordinates; |
|
|
|
|
|
|
|
|
|
// 새로운 배열로 마지막 두 개의 값을 제거
|
|
|
|
|
if (coords.length > 1) { |
|
|
|
|
// 최소한 두 개의 좌표가 있어야 함
|
|
|
|
|
const newCoords = coords.slice(0, -2); // 마지막 두 개의 값을 제거
|
|
|
|
|
|
|
|
|
|
newCoords.push(newCoords[newCoords.length - 1]); // 마지막 값을 다시 추가
|
|
|
|
|
|
|
|
|
|
// 중복 배열 제거
|
|
|
|
|
const uniqueArray = Array.from( |
|
|
|
|
new Set(newCoords.map(JSON.stringify)) |
|
|
|
|
).map(JSON.parse); |
|
|
|
|
|
|
|
|
|
if (uniqueArray.length === 1) { |
|
|
|
|
uniqueArray.push(uniqueArray[uniqueArray.length - 1]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
drawObj.set({ |
|
|
|
|
type: 'FeatureCollection', |
|
|
|
|
features: [ |
|
|
|
|
{ |
|
|
|
|
type: 'Feature', |
|
|
|
|
properties: {}, |
|
|
|
|
id: 'pal_line_string', |
|
|
|
|
geometry: { type: 'LineString', coordinates: [...uniqueArray] } |
|
|
|
|
} |
|
|
|
|
] |
|
|
|
|
}); |
|
|
|
|
const markerList = getDintancePointPopupList(drawObj); |
|
|
|
|
handlerDrawPopup(mapObject, markerList, drawObj); |
|
|
|
|
// 다시 이어그리기
|
|
|
|
|
let feature = drawObj.getAll().features[0]; |
|
|
|
|
drawObj.changeMode('draw_line_string', { |
|
|
|
|
featureId: 'pal_line_string', |
|
|
|
|
from: feature.geometry.coordinates[ |
|
|
|
|
feature.geometry.coordinates.length - 1 |
|
|
|
|
] |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const handlerDrawPopup = (mapInstance, popupList, draw = undefined) => { |
|
|
|
|
if (distanceMarkers.length > 0) { |
|
|
|
|
distanceMarkers.map(i => i.remove()); |
|
|
|
|
} |
|
|
|
|
if (popupList.length > 0) { |
|
|
|
|
popupList.map(i => { |
|
|
|
|
let distanceMarker = new mapboxgl.Popup({ |
|
|
|
|
closeButton: false, |
|
|
|
|
closeOnClick: false, |
|
|
|
|
offset: { |
|
|
|
|
bottom: [0, -10] |
|
|
|
|
}, |
|
|
|
|
focusAfterOpen: false |
|
|
|
|
}) |
|
|
|
|
.setLngLat([i.coord[0][0].toFixed(6), i.coord[0][1].toFixed(6)]) |
|
|
|
|
.setHTML( |
|
|
|
|
`<div style="color:#000000;font-weight:400;padding:2.5px;user-select:none">${i.text}</div>` |
|
|
|
|
) |
|
|
|
|
.addTo(mapInstance); |
|
|
|
|
|
|
|
|
|
distanceMarkers.push(distanceMarker); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (draw.getMode() === 'simple_select') { |
|
|
|
|
setIsDistanceRevert(true); |
|
|
|
|
} else { |
|
|
|
|
if (draw.getMode() === 'draw_line_string') { |
|
|
|
|
setIsDistanceRevert(false); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const handlerLogout = async () => { |
|
|
|
|
const { payload } = await dispatch(setLogout()); |
|
|
|
|
|
|
|
|
@ -383,10 +548,6 @@ export default function ControlApprovalsContainer({ mode }) {
|
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const handlerDrawObjInit = obj => { |
|
|
|
|
setDrawObj(obj); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<> |
|
|
|
|
<div className='map' style={{ width: '100%' }}> |
|
|
|
@ -422,12 +583,30 @@ export default function ControlApprovalsContainer({ mode }) {
|
|
|
|
|
<h4>거리측정</h4> |
|
|
|
|
<div className='map-btn'> |
|
|
|
|
<ButtonGroup> |
|
|
|
|
<Button primary>직선</Button> |
|
|
|
|
<Button primary>다각형</Button> |
|
|
|
|
<Button |
|
|
|
|
color={drawType === 'LINE' ? 'primary' : ''} |
|
|
|
|
onClick={e => { |
|
|
|
|
handlerDrawTypeChange(e, 'LINE'); |
|
|
|
|
}} |
|
|
|
|
> |
|
|
|
|
직선 |
|
|
|
|
</Button> |
|
|
|
|
<Button |
|
|
|
|
color={drawType === 'POLYGON' ? 'primary' : ''} |
|
|
|
|
onClick={e => { |
|
|
|
|
handlerDrawTypeChange(e, 'POLYGON'); |
|
|
|
|
}} |
|
|
|
|
> |
|
|
|
|
다각형 |
|
|
|
|
</Button> |
|
|
|
|
</ButtonGroup> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
<div className='data-box-btn-list'> |
|
|
|
|
<div |
|
|
|
|
ref={distanceBoxRef} |
|
|
|
|
className='data-box-btn-list' |
|
|
|
|
style={{ display: 'none' }} |
|
|
|
|
> |
|
|
|
|
<h4>측정</h4> |
|
|
|
|
<div className='distance-check'> |
|
|
|
|
<div className='btn-box'> |
|
|
|
@ -435,13 +614,18 @@ export default function ControlApprovalsContainer({ mode }) {
|
|
|
|
|
className='btn-icon rounded-circle' |
|
|
|
|
color='primary' |
|
|
|
|
size='sm' |
|
|
|
|
disabled={isResetDisabled} |
|
|
|
|
onClick={handlerDrawReset} |
|
|
|
|
> |
|
|
|
|
<FiRotateCw size={16} /> |
|
|
|
|
</Button> |
|
|
|
|
<Button |
|
|
|
|
id='draw_revert' |
|
|
|
|
onClick={handlerDistanceRevert} |
|
|
|
|
className='btn-icon rounded-circle' |
|
|
|
|
color='primary' |
|
|
|
|
size='sm' |
|
|
|
|
disabled={isDistanceRevert} |
|
|
|
|
> |
|
|
|
|
<FiCornerUpLeft size={16} /> |
|
|
|
|
</Button> |
|
|
|
@ -449,6 +633,7 @@ export default function ControlApprovalsContainer({ mode }) {
|
|
|
|
|
className='btn-icon rounded-circle' |
|
|
|
|
color='dark' |
|
|
|
|
size='sm' |
|
|
|
|
onClick={handlerDistanceClose} |
|
|
|
|
> |
|
|
|
|
<X size={16} /> |
|
|
|
|
</Button> |
|
|
|
@ -456,7 +641,20 @@ export default function ControlApprovalsContainer({ mode }) {
|
|
|
|
|
<div className='text'> |
|
|
|
|
<p> |
|
|
|
|
지도에서 지점을 클릭하여 거리를 측정하세요. |
|
|
|
|
<span className='finish'>총 거리 : 1050.24m</span> |
|
|
|
|
<span |
|
|
|
|
ref={totalDistanceRef} |
|
|
|
|
className='finish' |
|
|
|
|
style={{ display: 'none' }} |
|
|
|
|
> |
|
|
|
|
총 거리 : 1050.24m |
|
|
|
|
</span> |
|
|
|
|
<span |
|
|
|
|
ref={totalAreaRef} |
|
|
|
|
className='finish' |
|
|
|
|
style={{ display: 'none' }} |
|
|
|
|
> |
|
|
|
|
총 거리 : 1050.24m |
|
|
|
|
</span> |
|
|
|
|
</p> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
@ -512,6 +710,18 @@ export default function ControlApprovalsContainer({ mode }) {
|
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
)} |
|
|
|
|
<div |
|
|
|
|
ref={mouseCursorRef} |
|
|
|
|
style={{ |
|
|
|
|
position: 'absolute', |
|
|
|
|
display: 'none', |
|
|
|
|
background: '#8a1c05', |
|
|
|
|
color: '#fff', |
|
|
|
|
padding: '5px', |
|
|
|
|
borderRadius: '5px', |
|
|
|
|
fontWeight: 500 |
|
|
|
|
}} |
|
|
|
|
></div> |
|
|
|
|
</> |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|