Browse Source

관제과 페이지 거리측정 기능 추가

master
김장현 2 months ago
parent
commit
7f07a82a2f
  1. 232
      src/containers/flight/ControlApprovalsContainer.js

232
src/containers/flight/ControlApprovalsContainer.js

@ -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>
</>
);
}

Loading…
Cancel
Save