Browse Source

laanc 비행구역 다수 설정 및 비가시권 모달 표출

pull/2/head
junh_eee(이준희) 11 months ago
parent
commit
4980b06a3b
  1. 32
      src/components/map/mapbox/draw/LaancModal.js
  2. 214
      src/components/map/mapbox/draw/LaancDrawControl.js
  3. 3
      src/utility/DrawUtil.js
  4. 5
      src/views/laanc/FlightArea.js
  5. 26
      src/views/laanc/LaancAreaMap.js

32
src/components/map/mapbox/draw/LaancModal.js

@ -0,0 +1,32 @@
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
export default function LaancModal({ modal, handler }) {
const handlerDroneOneStop = () => {
window.open('https://drone.onestop.go.kr/', '드론원스탑');
handler();
};
return (
<div className='vertically-centered-modal'>
<Modal
isOpen={modal}
toggle={handler}
modalClassName={'modal-primary'}
className='modal-dialog-centered'
>
<ModalHeader toggle={handler}>특별 비행 신청</ModalHeader>
<ModalBody>
육안으로 기체를 확인할 없는 가시권 범위는 특별비행 신청을
진행하셔야 합니다. 드론원스톱을 통해서 신청해 주시기 바랍니다.
</ModalBody>
<ModalFooter>
<Button color='secondary' onClick={handler}>
취소
</Button>
<Button color='primary' onClick={handlerDroneOneStop}>
드론원스톱 바로가기
</Button>
</ModalFooter>
</Modal>
</div>
);
}

214
src/components/map/mapbox/draw/LaancDrawControl.js

@ -1,14 +1,18 @@
import { useEffect, useState } from 'react';
import { InfoModal } from '../../../modal/InfoModal';
import { useSelector } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import {
CalculateDistance,
handlerGetCircleCoord,
handlerGetHtmlContent,
handlerGetMidPoint
} from '../../../../utility/DrawUtil';
import { drawTypeChangeAction } from '../../../../modules/control/map/actions/controlMapActions';
import MapboxDraw from '@mapbox/mapbox-gl-draw';
export const LaancDrawControl = props => {
const dispatch = useDispatch();
const mapControl = useSelector(state => state.controlMapReducer);
const drawObj = props.drawObj;
const mapObject = props.mapObject;
@ -34,10 +38,22 @@ export const LaancDrawControl = props => {
useEffect(() => {
if (mapObject) {
mapObject.on('draw.create', handlerSetId);
mapObject.on('draw.update', handlerFormatAreaInfo);
mapObject.on('draw.update', handlerUpdateSetting);
const DrawLineStringMode = MapboxDraw.modes.draw_line_string;
const DrawPolygonMode = MapboxDraw.modes.draw_polygon;
const modeArr = [DrawLineStringMode, DrawPolygonMode];
mapObject.on('click', handlerOnClick);
modeArr.forEach(m => {
m.onStop = state => handlerDblClickFinish(state);
// onClick 이벤트 오버라이드
const origin = m.onClick;
m.onClick = function (state, e) {
origin.call(this, state, e);
handlerCustomOnClick(state, e);
};
});
}
}, [mapObject]);
@ -53,17 +69,15 @@ export const LaancDrawControl = props => {
}, [isDrawDone]);
// 클릭할 때마다 마커 찍어줌
const handlerOnClick = e => {
const handlerCustomOnClick = (state, e) => {
console.log('click');
const featureIds = drawObj.getFeatureIdsAt(e.point);
const feature = drawObj.get(featureIds[0]);
const type = handlerReturnMode(drawObj.getMode());
const obj = state[type?.toLowerCase()];
if (type) {
if (type && obj) {
if (type !== 'CIRCLE') {
if (feature) {
// 뒷 부분
if (state.currentVertexPosition > 1) {
const feature = drawObj.get(obj.id);
const coordinates = feature.geometry.coordinates;
const coords = [
...new Set(
@ -77,48 +91,110 @@ export const LaancDrawControl = props => {
const lngLat = handlerGetMidPoint(coords[len - 2], coords[len - 1]);
const text = CalculateDistance(coords[len - 2], coords[len - 1]);
handlerCreateOneMarker([0, 0], lngLat, text);
handlerCreateOneMarker([0, 0], lngLat, text, obj.id);
} else {
// Start
if (type !== 'CIRCLE')
handlerCreateOneMarker(
[0, -10],
[e.lngLat.lng, e.lngLat.lat],
'Start'
);
handlerCreateOneMarker(
[0, -10],
[e.lngLat.lng, e.lngLat.lat],
'Start',
obj.id
);
}
}
}
};
// 도형 첫 생성하면 properties.id에 현재 drawType 넣어줌
const handlerSetId = e => {
console.log('create');
const id = e.features[0].id;
const handlerDblClickFinish = state => {
console.log('dblclick');
const mode = handlerReturnMode(drawObj.getMode());
if (mode) {
drawObj.setFeatureProperty(id, 'id', mode);
setDrawObjId(id);
handlerFormatAreaInfo(e);
const obj = state[mode.toLowerCase()];
console.log(obj, '>>>>>>obj');
const length = state.currentVertexPosition;
drawObj.setFeatureProperty(obj.id, 'id', mode);
// dbl클릭이 click 두번으로 인식돼서, 마지막 값을 없애버리기로 함
if (mode === 'LINE') {
obj.coordinates.splice(-1);
if (length < 1) {
setAlertModal({
isOpen: true,
title: '좌표 최소 개수',
desc: '좌표를 두 개 점으로 이어주세요.'
});
handlerRemoveError(obj.id);
}
} else if (mode === 'POLYGON') {
obj.coordinates[0].splice(-1);
if (length < 2) {
setAlertModal({
isOpen: true,
title: '좌표 최소 개수',
desc: '좌표를 세 개 점으로 이어주세요.'
});
handlerRemoveError(obj.id);
}
}
handlerAbnormalityCheck(obj.coordinates, obj.id, mode);
};
const handlerFormatAreaInfo = e => {
const coord = e.features[0].geometry.coordinates;
const mode = drawObj.get(e.features[0].id).properties.id;
// 변수들 이름 겹쳐서 헷갈리니까 정리하기
const handlerAbnormalityCheck = (coord, id, mode) => {
console.log('check', coord, id, mode);
const isBreak = handlerIsSpecialFlight(coord, id, mode);
if (isBreak) return;
const data =
mode === 'LINE'
? coord
: mode === 'POLYGON'
? coord[0]
: mode === 'CIRCLE'
? e.features[0].properties.center
: null;
const initCoord = coord;
const coords =
mode === 'LINE' ? initCoord : mode === 'POLYGON' ? initCoord[0] : null;
handlerSaveAreaInfo(coords, mode);
};
handlerSaveAreaInfo(data, mode);
// 현재 그려진 모든 도형에 대한 비가시권 검사
const handlerIsSpecialFlight = (coord, id, mode) => {
// console.log(obj, 'specialFlight');
console.log('specialFlight');
let isBreak = false;
const coords = mode === 'LINE' ? coord : coord[0];
for (let point = 0; point < coords.length - 1; point++) {
const distance = CalculateDistance(coords[point], coords[point + 1]);
if (distance > 1000) {
isBreak = true;
break;
}
}
if (isBreak) {
props.setModal(true);
handlerRemoveError(id);
return true;
} else {
props.handlerSaveCheck(true);
return false;
}
};
// 비정상 감지 시 해당 도형, 마커 삭제
const handlerRemoveError = id => {
drawObj.delete(id);
handlerRemoveGroupMarker(id);
props.handlerSaveCheck(false);
};
// 도형 수정 시
const handlerUpdateSetting = e => {
console.log('update');
if (e.features[0]) {
const obj = e.features[0];
const mode = obj.properties.id;
const initCoord = obj.geometry.coordinates;
const coords = mode === 'LINE' ? initCoord : initCoord[0];
handlerAbnormalityCheck(coords, obj.id, mode);
}
};
// areaInfo 셋팅
const handlerSaveAreaInfo = (coord, mode) => {
if (!coord || !mode) {
alert('에러 발생. 다시 시도해 주세요.');
@ -163,6 +239,10 @@ export const LaancDrawControl = props => {
setIsDrawDone(true);
};
// 버퍼 및 기존 도형 재생성
// 해당되는 도형 및 마커만 다시 그려지게 해야함(버퍼 포함)
// 해당 Id 마커 지우고 path만 받아서 다시 그려지도록...
// 근데 areaCoordList[0]이.. 도형을 하나만 받아오는걸로 알고 있어서 그거 확인해야함
const handlerPastDraw = () => {
if (props.areaCoordList) {
const areas = props.areaCoordList[0];
@ -187,13 +267,13 @@ export const LaancDrawControl = props => {
);
} else {
if (areas.areaType === 'LINE') {
handlerCreateDrawObj(
drawObjId,
setDrawObjId,
'LineString',
{ path: paths },
'LINE'
);
// handlerCreateDrawObj(
// drawObjId,
// setDrawObjId,
// 'LineString',
// { path: paths },
// 'LINE'
// );
// 버퍼 생성
if (areas.bufferCoordList) {
@ -212,21 +292,21 @@ export const LaancDrawControl = props => {
);
}
} else if (areas.areaType === 'POLYGON') {
handlerCreateDrawObj(
drawObjId,
setDrawObjId,
'Polygon',
{ path: [paths] },
'POLYGON'
);
// handlerCreateDrawObj(
// drawObjId,
// setDrawObjId,
// 'Polygon',
// { path: [paths] },
// 'POLYGON'
// );
}
}
// 현재 그려진 도형 저장
setGeoJson(drawGeoJson);
// 마커 재 생성
handlerRemoveMarker();
handlerCreateAllMarker(paths);
// handlerRemoveMarker();
// handlerCreateAllMarker(paths);
}
}
};
@ -257,23 +337,35 @@ export const LaancDrawControl = props => {
}
};
// 지도에 있는 모든 마커 삭제
const handlerRemoveMarker = () => {
const ele = document.getElementsByClassName('mapboxgl-popup');
const eleArr = Array.from(ele);
eleArr?.forEach(marker => marker.remove());
};
const handlerCreateOneMarker = (anchor, lngLat, text) => {
// 해당되는 id의 마커 삭제
const handlerRemoveGroupMarker = id => {
const ele = document.getElementsByClassName('mapboxgl-popup');
const eleArr = Array.from(ele);
eleArr?.forEach(marker => {
if (marker.innerHTML.includes(id)) marker.remove();
});
};
// 개별 마커 생성
const handlerCreateOneMarker = (anchor, lngLat, text, id) => {
const popup = new props.mapboxgl.Popup({
offset: anchor,
closeButton: false,
closeOnClick: false
})
.setLngLat(lngLat)
.setHTML(handlerGetHtmlContent(text))
.setHTML(handlerGetHtmlContent(text, id))
.addTo(mapObject);
};
// 모든 마커 생성
const handlerCreateAllMarker = coords => {
const areas = props.areaCoordList[0];
@ -293,15 +385,17 @@ export const LaancDrawControl = props => {
};
const drawInit = () => {
// console.log('drawInit');
drawObj.deleteAll();
handlerRemoveMarker();
// drawObj.deleteAll();
// handlerRemoveMarker();
props.handlerSaveCheck(false);
setDrawObjId();
props.handlerInitCoordinates();
const mode = mapControl.drawType;
if (!mode || mode === 'RESET') {
drawObj.deleteAll();
handlerRemoveMarker();
return;
}
handlerStartMode(mode);

3
src/utility/DrawUtil.js

@ -49,7 +49,7 @@ export const handlerGetMidPoint = (dis1, dis2) => {
};
// html Content 반환
export const handlerGetHtmlContent = distance => {
export const handlerGetHtmlContent = (distance, id) => {
const text =
typeof distance === 'number'
? '거리 ' + fromMetersToText(distance)
@ -57,6 +57,7 @@ export const handlerGetHtmlContent = distance => {
return (
'<div style="display:inline-block;padding:5px;text-align:center;background-color:#fff;border:1px solid #000;font-size:13px;color:#ff0000;"><span>' +
`<div style="display:hidden;" className=${id}></div>` +
text +
'</span></div>'
);

5
src/views/laanc/FlightArea.js

@ -67,7 +67,8 @@ export default function FlightArea({
desc: ''
});
// console.log('>>>');
const [isSaveable, setIsSaveable] = useState(false);
//날씨 임시 데이터
const [wheather, setWheather] = useState([]);
@ -507,6 +508,7 @@ export default function FlightArea({
centeredModal={centeredModal}
mapContainer={mapContainer}
drawObj={drawObj}
setIsSaveable={setIsSaveable}
/>
</ModalBody>
<ModalFooter>
@ -577,6 +579,7 @@ export default function FlightArea({
<div>
<Button
color='primary'
disabled={!isSaveable}
onClick={() => {
handlerSave();
}}

26
src/views/laanc/LaancAreaMap.js

@ -11,8 +11,6 @@ import {
AREA_COORDINATE_LIST_SAVE,
FLIGHT_PLAN_AREA_BUFFER_LIST
} from '../../modules/basis/flight/actions/basisFlightAction';
import { LaancDraw } from '../../components/map/mapbox/draw/LaancDraw';
import { LaancDrawRe } from '../../components/map/mapbox/draw/LaancDrawRe';
import {
drawTypeChangeAction,
mapInitAction
@ -33,8 +31,14 @@ import geoJson from '../../components/map/geojson/airArea.json';
import { FeatureAirZone } from '../../components/map/mapbox/feature/FeatureAirZone';
import LaancMapSearch from '../../components/map/mapbox/draw/LaancMapSearch';
import { LaancDrawControl } from '../../components/map/mapbox/draw/LaancDrawControl';
export default function LaancAreaMap({ centeredModal, mapContainer, drawObj }) {
import LaancModal from '../../components/map/mapbox/draw/\bLaancModal';
export default function LaancAreaMap({
centeredModal,
mapContainer,
drawObj,
setIsSaveable
}) {
const dispatch = useDispatch();
const mapControl = useSelector(state => state.controlMapReducer);
const { areaCoordList } = useSelector(state => state.flightState);
@ -47,6 +51,7 @@ export default function LaancAreaMap({ centeredModal, mapContainer, drawObj }) {
);
const [number, setNumber] = useState(0);
const [modal, setModal] = useState(false);
const [detailLayer, setDetailLayer] = useState();
@ -294,6 +299,14 @@ export default function LaancAreaMap({ centeredModal, mapContainer, drawObj }) {
dispatch(AREA_COORDINATE_LIST_SAVE(areaList));
};
const handlerModal = () => {
setModal(!modal);
};
const handlerSaveCheck = save => {
setIsSaveable(save);
};
return (
<Card className='mb-0'>
<CardBody>
@ -331,14 +344,19 @@ export default function LaancAreaMap({ centeredModal, mapContainer, drawObj }) {
/> */}
<LaancDrawControl
drawObj={drawObj}
setModal={setModal}
mapboxgl={mapboxgl}
mapObject={mapObject}
areaCoordList={mapAreaCoordList}
handlerConfirm={handlerConfirm}
handlerSaveCheck={handlerSaveCheck}
handlerCoordinates={handlerCoordinates}
handlerInitCoordinates={handlerInitCoordinates}
/>
<FeatureAirZone map={mapObject} mapboxgl={mapboxgl} />
{modal ? (
<LaancModal modal={modal} handler={handlerModal} />
) : null}
</>
) : null}
</div>

Loading…
Cancel
Save