diff --git a/README.md b/README.md
index 70358eb..be77ae4 100644
Binary files a/README.md and b/README.md differ
diff --git a/src/assets/images/화면구성도_다이어그램.png b/src/assets/images/화면구성도_다이어그램.png
deleted file mode 100644
index 9783ca0..0000000
Binary files a/src/assets/images/화면구성도_다이어그램.png and /dev/null differ
diff --git a/src/assets/images/화면구성도다이어그램.png b/src/assets/images/화면구성도다이어그램.png
new file mode 100644
index 0000000..45db312
Binary files /dev/null and b/src/assets/images/화면구성도다이어그램.png differ
diff --git a/src/components/analysis/simulation/AnalysisSimuationInfo.js b/src/components/analysis/simulation/AnalysisSimuationInfo.js
index f7a3d72..9d73cf3 100644
--- a/src/components/analysis/simulation/AnalysisSimuationInfo.js
+++ b/src/components/analysis/simulation/AnalysisSimuationInfo.js
@@ -6,8 +6,10 @@ import { Spinner } from 'reactstrap';
export const AnalysisSimulationInfo = props => {
const [target, setTarget] = useState(null);
+ // 로딩 상태
const { loading } = useSelector(state => state.loadingReducer);
+ // 스크롤 끝 감지 데이터 추가
const onIntersect = useCallback(
([entry], observer) => {
if (entry.isIntersecting) {
@@ -19,6 +21,7 @@ export const AnalysisSimulationInfo = props => {
[props.handlerPageList]
);
+ // 무한 스크롤
useEffect(() => {
let observer;
if (target) {
diff --git a/src/components/analysis/simulation/AnalysisSimulationDetail.js b/src/components/analysis/simulation/AnalysisSimulationDetail.js
index 35aa6e8..97f46a3 100644
--- a/src/components/analysis/simulation/AnalysisSimulationDetail.js
+++ b/src/components/analysis/simulation/AnalysisSimulationDetail.js
@@ -11,6 +11,7 @@ import { ReactComponent as Simulation_icon } from '../../../assets/images/simula
import { IMG_PATH } from '../../../configs/constants';
import AnalysisSimulatorSlider from './AnalysisSimulatorSlider';
export const AnalysisSimulationDetail = props => {
+ // 슬라이드 진행 방향
const [isRtl, setIsRtl] = useRTL();
return (
diff --git a/src/components/analysis/simulation/AnalysisSimulationMap.js b/src/components/analysis/simulation/AnalysisSimulationMap.js
index c3db44f..d6fbd52 100644
--- a/src/components/analysis/simulation/AnalysisSimulationMap.js
+++ b/src/components/analysis/simulation/AnalysisSimulationMap.js
@@ -9,12 +9,15 @@ import { Threebox } from 'threebox-plugin';
import gimPo from '../../map/geojson/gimpoAirportAirArea.json';
export const AnalysisSimulationMap = props => {
+ // 지도
const mapContainer = useRef(null);
+ // mabboxgl 지도 초기화
useEffect(() => {
mapBoxMapInit();
}, []);
+ // mabboxgl 지도 초기화 함수
const mapBoxMapInit = () => {
mapboxgl.accessToken = MAPBOX_TOKEN;
diff --git a/src/components/analysis/simulation/AnalysisSimulationMarker.js b/src/components/analysis/simulation/AnalysisSimulationMarker.js
index 0a0e201..715e7ab 100644
--- a/src/components/analysis/simulation/AnalysisSimulationMarker.js
+++ b/src/components/analysis/simulation/AnalysisSimulationMarker.js
@@ -3,6 +3,7 @@ import DronIcon from '../../../assets/images/drone-marker-icon.png';
import mapboxgl from 'mapbox-gl';
export const AnalysisSimulationMarker = props => {
+ // 마커 css
const el = document.createElement('div');
el.className = 'marker';
el.style.width = '30px';
@@ -10,6 +11,7 @@ export const AnalysisSimulationMarker = props => {
el.style.textAlign = 'center';
el.style.backgroundImage = `url(${DronIcon})`;
+ // 마커 경로 담기
useEffect(() => {
if (props.selMarker && props.selMarker.setMap) {
props.selMarker.setMap(null);
@@ -30,6 +32,7 @@ export const AnalysisSimulationMarker = props => {
}
}, [props.data]);
+ // 매 초마다 경로 이동
useEffect(() => {
if (props.isPlay) {
if (props.marker) {
@@ -47,6 +50,7 @@ export const AnalysisSimulationMarker = props => {
}
}, [props.info]);
+ // 지도 드론 표출
const addMarkers = (position, id) => {
// 이미 지정된 마커 제거
if (props.marker) {
diff --git a/src/components/analysis/simulation/AnalysisSimulationPolyline.js b/src/components/analysis/simulation/AnalysisSimulationPolyline.js
index 305b4c1..7030c74 100644
--- a/src/components/analysis/simulation/AnalysisSimulationPolyline.js
+++ b/src/components/analysis/simulation/AnalysisSimulationPolyline.js
@@ -1,8 +1,10 @@
import { useEffect } from 'react';
export const AnalysisSimulationPolyline = props => {
+ // 폴리라인 경로 담는 변수
const polylinePath = [];
+ // 기존 저장된 경로 삭제
useEffect(() => {
// 기존 폴리라인 삭제 처리
if (props.selPolyline && props.selPolyline.setMap) {
@@ -19,6 +21,7 @@ export const AnalysisSimulationPolyline = props => {
}
}, [props.data]);
+ // 경로 그리기
const addPolyline = () => {
if (props.data && props.map) {
props.data.forEach(item => {
diff --git a/src/components/analysis/simulation/AnalysisSimulationReport.js b/src/components/analysis/simulation/AnalysisSimulationReport.js
index 4be4be6..6d118eb 100644
--- a/src/components/analysis/simulation/AnalysisSimulationReport.js
+++ b/src/components/analysis/simulation/AnalysisSimulationReport.js
@@ -5,6 +5,7 @@ import Flatpickr from 'react-flatpickr';
import { Button, Input, InputGroup } from 'reactstrap';
export const AnalysisSimulationReport = props => {
+ // 식별번호
const [filterId, setFilterId] = useState('');
return (
diff --git a/src/components/analysis/simulation/AnalysisSimulatorSlider.js b/src/components/analysis/simulation/AnalysisSimulatorSlider.js
index 87b643a..b26f796 100644
--- a/src/components/analysis/simulation/AnalysisSimulatorSlider.js
+++ b/src/components/analysis/simulation/AnalysisSimulatorSlider.js
@@ -24,6 +24,7 @@ const AnalysisSimulatorSlider = ({
return timeString;
}
+ // 슬라이더 값이 바뀔 때마다 실행되는 함수
const colorOptions = {
start: [playCount ? playCount : 0],
// connect: true,
@@ -64,7 +65,6 @@ const AnalysisSimulatorSlider = ({
direction
};
- useEffect(() => {}, [playCount]);
return (
{/*
Default / Primary Color Slider
*/}
diff --git a/src/components/laanc/list/LaancDetail.js b/src/components/laanc/list/LaancDetail.js
index 904de47..3837a1f 100644
--- a/src/components/laanc/list/LaancDetail.js
+++ b/src/components/laanc/list/LaancDetail.js
@@ -30,7 +30,9 @@ export default function LaancDetail({ data, handlerLaancClose }) {
11: '25kg초과'
}
};
+ // 로그인 정보
const { user } = useSelector(state => state.authState);
+ // 약관 정보
const { termsList } = useSelector(state => state.accountState);
// Laanc 약관 동의
diff --git a/src/components/laanc/list/LaancGrid.js b/src/components/laanc/list/LaancGrid.js
index 65f4698..ca3b796 100644
--- a/src/components/laanc/list/LaancGrid.js
+++ b/src/components/laanc/list/LaancGrid.js
@@ -18,11 +18,13 @@ pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/$
export default function LaancGrid() {
const dispatch = useDispatch();
+ // 상세보기 모달
const [isAnimation, setIsAnimation] = useState(false);
-
+ // Laanc 승인 신청 목록
const { laancSearchData, laancDetail } = useSelector(
state => state.laancState
);
+ // 로딩 상태
const { loading } = useSelector(state => state.loadingReducer);
// Laanc 승인 신청 목록 조회
@@ -169,6 +171,7 @@ export default function LaancGrid() {
}
];
+ // PDF 다운로드
const handlerPdfDownload = pdf => {
if (pdf) {
let alink = document.createElement('a');
diff --git a/src/components/laanc/list/LaancSearch.js b/src/components/laanc/list/LaancSearch.js
index 649281e..2e93a14 100644
--- a/src/components/laanc/list/LaancSearch.js
+++ b/src/components/laanc/list/LaancSearch.js
@@ -8,7 +8,7 @@ import * as LaancAction from '../../../modules/laanc/actions/laancActions';
function LaancSearch({ isSearch }) {
const dispatch = useDispatch();
-
+ // 날짜 데이터
const [date, setDate] = useState({
createStDate: moment().subtract(0, 'day').format('YYYY-MM-DD'),
createEndDate: moment().subtract(-7, 'day').format('YYYY-MM-DD')
diff --git a/src/components/laanc/map/FlightArea.js b/src/components/laanc/map/FlightArea.js
index 401dde8..c7bdfbf 100644
--- a/src/components/laanc/map/FlightArea.js
+++ b/src/components/laanc/map/FlightArea.js
@@ -1,6 +1,9 @@
+import { useEffect, useRef, useState } from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
+// mapbox
import 'mapbox-gl/dist/mapbox-gl.css';
import mapboxgl from 'mapbox-gl';
-import threebox from 'threebox-plugin';
import MapboxLanguage from '@mapbox/mapbox-gl-language';
import MapboxDraw from '@mapbox/mapbox-gl-draw';
import {
@@ -10,18 +13,6 @@ import {
SimpleSelectMode
} from 'mapbox-gl-draw-circle';
import { MAPBOX_TOKEN } from '../../../configs/constants';
-import { useEffect, useRef, useState } from 'react';
-import { useDispatch, useSelector } from 'react-redux';
-import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
-import {
- AREA_COORDINATE_LIST_SAVE,
- AREA_DETAIL_LIST_SAVE
-} from '../../../modules/basis/flight/actions/basisFlightAction';
-import {
- drawTypeChangeAction,
- mapInitAction
-} from '../../../modules/control/map/actions/controlMapActions';
-import LaancAreaMap from './LaancAreaMap';
import {
InitFeature,
handlerCreatePoint,
@@ -32,20 +23,26 @@ import {
layerPolyline,
layerWayPoint
} from '../../../utility/DrawUtil';
-import flatGimpo from '../../map/geojson/flatGimpoAirportAirArea.json';
+// actions
+import {
+ AREA_COORDINATE_LIST_SAVE,
+ AREA_DETAIL_LIST_SAVE
+} from '../../../modules/basis/flight/actions/basisFlightAction';
+import {
+ drawTypeChangeAction,
+ mapInitAction
+} from '../../../modules/control/map/actions/controlMapActions';
+import * as LaancAction from '../../../modules/laanc/actions/laancActions';
+// geojson
import gimpo from '../../map/geojson/gimpoAirportAirArea.json';
-import geoJson from '../../map/geojson/airArea.json';
+
+import threebox from 'threebox-plugin';
import { FeatureAirZone } from '../../map/mapbox/feature/FeatureAirZone';
import { WeatherContainer } from '../../../containers/basis/flight/plan/WeatherContainer';
import { initFlightBas } from '../../../modules/laanc/models/laancModels';
-import * as LaancAction from '../../../modules/laanc/actions/laancActions';
+import LaancAreaMap from './LaancAreaMap';
import LaancDrawModal from './LaancDrawModal';
-
-const initialAddData = {
- isAddable: false,
- isViewAdd: false,
- overAdd: false
-};
+import { handlerCreateAirSpace } from './LaancComn';
export default function FlightArea({
centeredModal,
@@ -61,40 +58,65 @@ export default function FlightArea({
>;
const dispatch = useDispatch();
- const { areaCoordList } = useSelector(state => state.flightState);
+ // 비행구역 타입 및 공역 타입
const mapControl = useSelector(state => state.controlMapReducer);
- const mapContainer = useRef(null);
+ // 비행구역 정보 저장
+ const { areaCoordList } = useSelector(state => state.flightState);
+
+ // 지도
const [mapObject, setMapObject] = useState();
- const [drawObj, setDrawObj] = useState();
+ const mapContainer = useRef(null);
+ // 지도 로드 여부
const [isMapLoad, setIsMapLoad] = useState(false);
+
+ // 비행구역 그리기
+ const [drawObj, setDrawObj] = useState();
+
+ // 미니맵 레이어
const [previewLayer, setPreviewLayer] = useState();
+
+ // 날씨 모달
const [formModal, setFormModal] = useState(false);
+ // 비행구역 설정 관련 모달
const [modal, setModal] = useState({
title: '',
desc: '',
isOpen: false
});
+ // 비행구역 저장 가능 여부
const [isSaveable, setIsSaveable] = useState(false);
- const [addData, setAddData] = useState(initialAddData);
+ // 비행구역 추가 가능 여부 판단
+ const [addData, setAddData] = useState({
+ isAddable: false,
+ isViewAdd: false,
+ overAdd: false
+ });
+
+ // 저장된 비행구역 데이터
const [saveData, setSaveData] = useState();
+
+ // 비행구역 고도
const [saveElev, setSaveElev] = useState();
- //날씨 임시 데이터
+ //날씨 위치 데이터
const [wheather, setWheather] = useState([]);
+ // 미니맵에 표출되는 비행구역 정보
const previewGeo = {
type: 'FeatureCollection',
features: []
};
+ // 지도 초기 셋팅
useEffect(() => {
handlerMapInit();
}, []);
+ // 미니맵에 비행구역 표출 및 날씨 정보 저장
useEffect(() => {
if (areaCoordList) {
const area = areaCoordList[0];
@@ -105,78 +127,12 @@ export default function FlightArea({
}
}, [areaCoordList, centeredModal, previewLayer]);
- const handlerCreateAirSpace = (
- map,
- useGeoJson = {
- ...geoJson,
- ...flatGimpo,
- features: [...geoJson.features, ...flatGimpo.features]
- }
- ) => {
- if (map.getLayer('maine')) {
- map.removeLayer('maine');
- map.removeSource('maine');
- }
- let arrGeoJson = [];
- useGeoJson.features.map(item => {
- if (item.properties.type === '0001' && mapControl.area0001) {
- arrGeoJson.push({
- ...item,
- properties: { ...item.properties, color: '#FF3648' }
- });
- } else if (item.properties.type === '0002' && mapControl.area0002) {
- arrGeoJson.push({
- ...item,
- properties: { ...item.properties, color: '#FFA1AA' }
- });
- } else if (item.properties.type === '0003' && mapControl.area0003) {
- arrGeoJson.push({
- ...item,
- properties: { ...item.properties, color: '#FFA800' }
- });
- } else if (item.properties.type === '0004' && mapControl.area0004) {
- arrGeoJson.push({
- ...item,
- properties: { ...item.properties, color: '#A16B00' }
- });
- } else if (item.properties.type === '0005' && mapControl.area0005) {
- arrGeoJson.push({
- ...item,
- properties: { ...item.properties, color: '#AB40FF' }
- });
- } else if (item.properties.type === '0006' && mapControl.area0006) {
- arrGeoJson.push({
- ...item,
- properties: { ...item.properties, color: '#009cad' }
- });
- }
- });
- useGeoJson.features = arrGeoJson.filter(i => i.geometry.type === 'Polygon');
-
- // 공역 생성 start
- map.addSource('maine', {
- type: 'geojson',
- data: {
- ...useGeoJson
- }
- });
- map.addLayer({
- id: 'maine',
- type: 'fill',
- source: 'maine',
- layout: {},
- paint: {
- 'fill-color': ['get', 'color'],
- // 'fill-extrusion-height': 3000,
- 'fill-opacity': 0.5
- }
- });
- };
-
+ // 비행구역 설정 관련 모달 표출
const handlerModal = () => {
setModal(!modal);
};
+ // 비행구역 타입 변경 시 그리기 모드 상태일 때 에러 표출
const handlerDrawType = val => {
if (drawObj.getMode().includes('draw')) {
setModal({
@@ -195,6 +151,7 @@ export default function FlightArea({
}
};
+ // laanc계획서 비행구역 저장버튼 클릭 시 비행구역 정보 저장
const handlerSave = async () => {
if (areaCoordList) {
console.log('save');
@@ -208,29 +165,28 @@ export default function FlightArea({
setCenteredModal(false);
dispatch(AREA_DETAIL_LIST_SAVE(resultAreaDetail));
- } else {
- alert('아무것도 작성 안함');
}
};
- // 날씨 handler
+ // 날씨 모달 표출
const handlerWeather = () => {
setFormModal(!formModal);
};
+ // 지도 초기 셋팅
const handlerMapInit = () => {
mapboxgl.accessToken = MAPBOX_TOKEN;
const map = new mapboxgl.Map({
- container: 'preview', // container ID
- style: 'mapbox://styles/mapbox/streets-v12', // style URL
- center: [126.612647, 37.519893], // starting position [lng, lat]
- // zoom: !areaCoordList ? 14 : bufferZoom.bufferzoom, // starting zoom
+ container: 'preview',
+ style: 'mapbox://styles/mapbox/streets-v12',
+ center: [126.612647, 37.519893],
zoom: 15,
antialias: true,
attributionControl: false
});
+ // 비행구역 상세맵 draw 정보 셋팅
const draw = new MapboxDraw({
displayControlsDefault: false,
userProperties: true,
@@ -243,16 +199,14 @@ export default function FlightArea({
simple_select: SimpleSelectMode
},
styles: [
- // line stroke
{
+ // polyline
id: 'gl-draw-line',
type: 'line',
filter: [
'all',
['==', '$type', 'LineString'],
['!=', 'mode', 'static']
- // ['==', 'meta', 'feature'],
- // ['==', 'active', 'false']
],
layout: {
'line-cap': 'round',
@@ -264,28 +218,8 @@ export default function FlightArea({
'line-width': 2
}
},
- // direct line stroke
- // {
- // id: 'gl-draw-line-active',
- // type: 'line',
- // filter: [
- // 'all',
- // ['==', '$type', 'LineString'],
- // ['==', 'meta', 'feature'],
- // ['==', 'active', 'true']
- // ],
- // layout: {
- // 'line-cap': 'round',
- // 'line-join': 'round'
- // },
- // paint: {
- // 'line-color': '#000000',
- // 'line-dasharray': [0.2, 2],
- // 'line-width': 2
- // }
- // },
- // polygon fill
{
+ // polygon fill
id: 'gl-draw-polygon-fill',
type: 'fill',
filter: ['all', ['==', '$type', 'Polygon'], ['!=', 'mode', 'static']],
@@ -295,18 +229,7 @@ export default function FlightArea({
'fill-opacity': 0.1
}
},
- // polygon mid points
- {
- id: 'gl-draw-polygon-midpoint',
- type: 'circle',
- filter: ['all', ['==', '$type', 'Point'], ['==', 'meta', 'midpoint']],
- paint: {
- 'circle-radius': 4,
- 'circle-color': '#8a1c05'
- }
- },
- // polygon outline stroke
- // This doesn't style the first edge of the polygon, which uses the line stroke styling instead
+ // polygon outline
{
id: 'gl-draw-polygon-stroke-active',
type: 'line',
@@ -321,8 +244,8 @@ export default function FlightArea({
'line-width': 2
}
},
- // vertex point halos
{
+ // vertex point halos
id: 'gl-draw-polygon-and-line-vertex-halo-active',
type: 'circle',
filter: [
@@ -333,11 +256,11 @@ export default function FlightArea({
],
paint: {
'circle-radius': 8,
- 'circle-color': '#fff'
+ 'circle-color': '#ffffff'
}
},
- // vertex points
{
+ // vertex points
id: 'gl-draw-polygon-and-line-vertex-active',
type: 'circle',
filter: [
@@ -359,7 +282,6 @@ export default function FlightArea({
const language = new MapboxLanguage();
map.addControl(language);
- // map.addControl(draw);
const tb = (window.tb = new threebox.Threebox(
map,
@@ -396,7 +318,7 @@ export default function FlightArea({
}
});
- handlerCreateAirSpace(map);
+ handlerCreateAirSpace(map, mapControl);
// 미니맵 표출
map.addSource('preview', {
@@ -417,6 +339,7 @@ export default function FlightArea({
dispatch(mapInitAction(map));
};
+ // 저장된 비행구역 미니맵에 표출
const handlerPreviewDraw = () => {
if (areaCoordList) {
const areas = areaCoordList[0];
@@ -427,7 +350,6 @@ export default function FlightArea({
let fitZoomPaths = [];
- // 기존
if (areas.areaType) {
if (areas.areaType === 'CIRCLE') {
const radius = areas.bufferZone;
@@ -478,12 +400,8 @@ export default function FlightArea({
//지도 줌 좌표 설정
fitZoomPaths = paths.concat();
-
- // 마커 삭제
- // const ele = document.getElementById('mapboxgl-popup');
- // const eleArr = Array.from(ele);
- // eleArr?.forEach(marker => marker.remove());
}
+
handlerFitBounds(mapObject, fitZoomPaths, 50, areas.areaType);
mapObject.setPaintProperty('waypoint', 'circle-radius', 10);
@@ -491,12 +409,13 @@ export default function FlightArea({
}
const coordValue = [];
- const coord = paths?.map(coords => {
+ paths?.map(coords => {
coordValue.push({
lat: coords[1],
lon: coords[0]
});
});
+
if (page === 1) {
naver.maps.Service.reverseGeocode(
{
@@ -527,7 +446,6 @@ export default function FlightArea({
name: 'latlon',
value: coordValue
});
- //스텝1에 반경도 글씨가 바뀌어야 함...!!
handleChange({
type: 'area',
name: 'bufferZone',
@@ -537,38 +455,33 @@ export default function FlightArea({
}
};
+ // 비행구역 추가 버튼 클릭 시
const handlerAddClick = () => {
if (!addData.isAddable || !addData.overAdd) {
handlerAddChange('isAddable', true);
- const obj = drawObj
- .getAll()
- .features.filter(obj => obj.properties.id !== 'BUFFER');
- // handlerDrawType(obj[0].properties.id);
}
};
+ // 비행구역 추가 관련 상태 변경
const handlerAddChange = (key, val) => {
- // const [addData, setAddData] = useState({
- // isAddalbe: false,
- // isViewAdd: false,
- // overAdd: false
- // })
-
setAddData(prev => ({
...prev,
[key]: val
}));
};
+ // 비행구역 저장 가능 유무 체크
const handlerSaveCheck = save => {
setIsSaveable(save);
};
+ // 비행구역 데이터 초기화
const handlerInitCoordinates = () => {
const init = initFlightBas.initDetail.areaList.concat();
dispatch(AREA_COORDINATE_LIST_SAVE(init));
};
+ // 비행구역 고도 저장
const handlerSaveElev = elev => {
setSaveElev(elev);
};
@@ -604,7 +517,6 @@ export default function FlightArea({
- {/* 닫기 */}
저장
diff --git a/src/components/laanc/map/LaancAreaMap.js b/src/components/laanc/map/LaancAreaMap.js
index 039f91e..0901ba2 100644
--- a/src/components/laanc/map/LaancAreaMap.js
+++ b/src/components/laanc/map/LaancAreaMap.js
@@ -3,7 +3,7 @@ import mapboxgl from 'mapbox-gl';
import threebox from 'threebox-plugin';
import MapboxLanguage from '@mapbox/mapbox-gl-language';
import { MAPBOX_TOKEN } from '../../../configs/constants';
-import { useEffect, useMemo, useRef, useState } from 'react';
+import { useEffect, useRef, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Card, CardBody } from 'reactstrap';
import { initFlightBas } from '../../../modules/basis/flight/models/basisFlightModel';
@@ -16,22 +16,15 @@ import { mapInitAction } from '../../../modules/control/map/actions/controlMapAc
import {
FormattingCoord,
handlerFitBounds,
- handlerGetCircleCoord,
- layerBuffer,
- layerGuideLine,
- layerPolygon,
- layerPolyline,
- layerWayPoint
+ handlerGetCircleCoord
} from '../../../utility/DrawUtil';
-import flatGimpo from '../../map/geojson/flatGimpoAirportAirArea.json';
import gimpo from '../../map/geojson/gimpoAirportAirArea.json';
-import geoJson from '../../map/geojson/airArea.json';
import { FeatureAirZone } from '../../map/mapbox/feature/FeatureAirZone';
import LaancMapSearch from './LaancMapSearch';
import { LaancDrawControl } from './LaancDrawControl';
+import { handlerCreateAirSpace } from './LaancComn';
export default function LaancAreaMap({
- centeredModal,
mapContainer,
drawObj,
handlerSaveCheck,
@@ -43,42 +36,38 @@ export default function LaancAreaMap({
setModal
}) {
const dispatch = useDispatch();
+ // 비행구역 타입 및 공역 타입
const mapControl = useSelector(state => state.controlMapReducer);
- const { areaCoordList } = useSelector(state => state.flightState);
- const [mapObject, setMapObject] = useState();
- const [isMapLoad, setIsMapLoad] = useState(false);
- const [mode, setMode] = useState();
+ // 비행구역 정보 저장
+ const { areaCoordList } = useSelector(state => state.flightState);
+ // 비행구역 초기값 포함 정보 저장
const [mapAreaCoordList, setMapAreaCoordList] = useState(
initFlightBas.initDetail.areaList
);
- const [number, setNumber] = useState(0);
+ // 지도
+ const [mapObject, setMapObject] = useState();
+ // 지도 로드 여부
+ const [isMapLoad, setIsMapLoad] = useState(false);
- // const [detailLayer, setDetailLayer] = useState();
+ // 지도 렌더 횟수
+ const [number, setNumber] = useState(0);
+ // 비행구역 좌표 카드에 표출될 좌표 정보
const [viewCoordObj, setViewCoordObj] = useState([]);
- const detailGeo = useMemo(() => {
- return {
- type: 'FeatureCollection',
- features: []
- };
- }, []);
-
// 좌표 정보 마우스 드래그
const scrollRef = useRef(null);
const [isDrag, setIsDrag] = useState(false);
const [startX, setStartX] = useState();
+ // 지도 초기 셋팅
useEffect(() => {
handlerMapInit();
}, []);
- useEffect(() => {
- setMode(mapControl.drawType);
- }, [mapControl.drawType]);
-
+ // 첫 비행구역 생성 or 저장했던 비행구역 다시 열기 시 비행구역에 화면 맞추어서 zoom
useEffect(() => {
if (areaCoordList && mapObject) {
if (
@@ -111,75 +100,7 @@ export default function LaancAreaMap({
}
}, [areaCoordList, mapObject, number]);
- // 공역 생성
- const handlerCreateAirSpace = (
- map,
- useGeoJson = {
- ...geoJson,
- ...flatGimpo,
- features: [...geoJson.features, ...flatGimpo.features]
- }
- ) => {
- if (map.getLayer('maine')) {
- map.removeLayer('maine');
- map.removeSource('maine');
- }
- let arrGeoJson = [];
- useGeoJson.features.map(item => {
- if (item.properties.type === '0001' && mapControl.area0001) {
- arrGeoJson.push({
- ...item,
- properties: { ...item.properties, color: '#FF3648' }
- });
- } else if (item.properties.type === '0002' && mapControl.area0002) {
- arrGeoJson.push({
- ...item,
- properties: { ...item.properties, color: '#FFA1AA' }
- });
- } else if (item.properties.type === '0003' && mapControl.area0003) {
- arrGeoJson.push({
- ...item,
- properties: { ...item.properties, color: '#FFA800' }
- });
- } else if (item.properties.type === '0004' && mapControl.area0004) {
- arrGeoJson.push({
- ...item,
- properties: { ...item.properties, color: '#A16B00' }
- });
- } else if (item.properties.type === '0005' && mapControl.area0005) {
- arrGeoJson.push({
- ...item,
- properties: { ...item.properties, color: '#AB40FF' }
- });
- } else if (item.properties.type === '0006' && mapControl.area0006) {
- arrGeoJson.push({
- ...item,
- properties: { ...item.properties, color: '#009cad' }
- });
- }
- });
- useGeoJson.features = arrGeoJson.filter(i => i.geometry.type === 'Polygon');
-
- // 공역 생성 start
- map.addSource('maine', {
- type: 'geojson',
- data: {
- ...useGeoJson
- }
- });
- map.addLayer({
- id: 'maine',
- type: 'fill',
- source: 'maine',
- layout: {},
- paint: {
- 'fill-color': ['get', 'color'],
- // 'fill-extrusion-height': 3000,
- 'fill-opacity': 0.5
- }
- });
- };
-
+ // 맵박스 지도 초기 셋팅
const handlerMapInit = () => {
mapboxgl.accessToken = MAPBOX_TOKEN;
@@ -187,7 +108,6 @@ export default function LaancAreaMap({
container: 'detail', // container ID
style: 'mapbox://styles/mapbox/streets-v12', // style URL
center: [126.612647, 37.519893], // starting position [lng, lat]
- // zoom: !areaCoordList ? 14 : bufferZoom.bufferzoom, // starting zoom
zoom: 15,
antialias: true,
attributionControl: false
@@ -238,31 +158,15 @@ export default function LaancAreaMap({
}
});
- map.addSource('detail', {
- type: 'geojson',
- data: detailGeo
- });
- map.addLayer(layerWayPoint('detail'));
- map.addLayer(layerGuideLine('detail'));
- map.addLayer(layerPolyline('detail'));
- map.addLayer(layerPolygon('detail'));
- map.addLayer(layerBuffer('detail'));
-
- handlerCreateAirSpace(map);
+ handlerCreateAirSpace(map, mapControl);
setIsMapLoad(true);
-
- // const detail = map.getSource('detail');
- // if (detail) setDetailLayer(detail);
});
+
setMapObject(map);
dispatch(mapInitAction(map));
};
- // const handlerInitCoordinates = () => {
- // const init = initFlightBas.initDetail.areaList.concat();
- // dispatch(AREA_COORDINATE_LIST_SAVE(init));
- // };
-
+ // areaInfo를 areaList 형식으로 반환
const handlerAreaInfoToAreaList = areaInfo => {
const initAreaList = initFlightBas.initDetail.areaList.concat();
const coordList = [];
@@ -287,10 +191,10 @@ export default function LaancAreaMap({
return areaList;
};
+ // 비행관제구역 체크 및 버퍼 생성
const handlerCoordinates = areaInfo => {
const areaList = handlerAreaInfoToAreaList(areaInfo);
- // dispatch(LaancAction.LAANC_ALTITUDE.request(areaList));
dispatch(LaancAction.LAANC_VALID_AREA.request(areaList));
if (areaInfo.areaType === 'LINE' || areaInfo.areaType === 'POLYGON') {
dispatch(FLIGHT_PLAN_AREA_BUFFER_LIST.request(areaList));
@@ -299,6 +203,7 @@ export default function LaancAreaMap({
}
};
+ // 비행구역 설정 후 저장
const handlerConfirm = areaList => {
if (areaList === undefined) {
alert('영역을 설정해 주세요.');
@@ -308,17 +213,14 @@ export default function LaancAreaMap({
dispatch(AREA_COORDINATE_LIST_SAVE(areaList));
};
- // const handlerModal = () => {
- // setModal(!modal);
- // };
-
- // 좌표 정보 마우스 드래그
+ // [좌표 정보] 마우스 다운 시 스크롤 준비
const onMouseDown = e => {
e.preventDefault();
setIsDrag(true);
setStartX(e.pageX + scrollRef.current.scrollLeft);
};
+ // [좌표 정보] 마우스 드래그로 스크롤 이동
const onMouseMove = e => {
if (isDrag) {
const { scrollWidth, clientWidth, scrollLeft } = scrollRef.current;
@@ -333,6 +235,7 @@ export default function LaancAreaMap({
}
};
+ // [좌표 정보] onMouseMove 이벤트 빈도 조절
const throttle = (func, ms) => {
let throttled = false;
return (...args) => {
@@ -346,11 +249,13 @@ export default function LaancAreaMap({
};
};
+ // [좌표 정보] 마우스 업 시 스크롤 멈춤
const onMouseUp = e => {
e.preventDefault();
setIsDrag(false);
};
+ // [좌표 정보] 마우스 벗어날 시 스크롤 멈춤
const onMouseLeave = () => {
setIsDrag(false);
};
@@ -455,21 +360,20 @@ export default function LaancAreaMap({
{isMapLoad && mapObject ? (
<>
>
diff --git a/src/components/laanc/map/LaancComn.js b/src/components/laanc/map/LaancComn.js
new file mode 100644
index 0000000..d8e30a8
--- /dev/null
+++ b/src/components/laanc/map/LaancComn.js
@@ -0,0 +1,73 @@
+import { useSelector } from 'react-redux';
+import geoJson from '../../map/geojson/airArea.json';
+import flatGimpo from '../../map/geojson/flatGimpoAirportAirArea.json';
+
+// 공역 생성
+export const handlerCreateAirSpace = (
+ map,
+ mapControl,
+ useGeoJson = {
+ ...geoJson,
+ ...flatGimpo,
+ features: [...geoJson.features, ...flatGimpo.features]
+ }
+) => {
+ if (map.getLayer('maine')) {
+ map.removeLayer('maine');
+ map.removeSource('maine');
+ }
+ let arrGeoJson = [];
+ useGeoJson.features.map(item => {
+ if (item.properties.type === '0001' && mapControl.area0001) {
+ arrGeoJson.push({
+ ...item,
+ properties: { ...item.properties, color: '#FF3648' }
+ });
+ } else if (item.properties.type === '0002' && mapControl.area0002) {
+ arrGeoJson.push({
+ ...item,
+ properties: { ...item.properties, color: '#FFA1AA' }
+ });
+ } else if (item.properties.type === '0003' && mapControl.area0003) {
+ arrGeoJson.push({
+ ...item,
+ properties: { ...item.properties, color: '#FFA800' }
+ });
+ } else if (item.properties.type === '0004' && mapControl.area0004) {
+ arrGeoJson.push({
+ ...item,
+ properties: { ...item.properties, color: '#A16B00' }
+ });
+ } else if (item.properties.type === '0005' && mapControl.area0005) {
+ arrGeoJson.push({
+ ...item,
+ properties: { ...item.properties, color: '#AB40FF' }
+ });
+ } else if (item.properties.type === '0006' && mapControl.area0006) {
+ arrGeoJson.push({
+ ...item,
+ properties: { ...item.properties, color: '#009cad' }
+ });
+ }
+ });
+ useGeoJson.features = arrGeoJson.filter(i => i.geometry.type === 'Polygon');
+
+ // 공역 생성 start
+ map.addSource('maine', {
+ type: 'geojson',
+ data: {
+ ...useGeoJson
+ }
+ });
+ map.addLayer({
+ id: 'maine',
+ type: 'fill',
+ source: 'maine',
+ layout: {},
+ paint: {
+ 'fill-color': ['get', 'color'],
+ // 'fill-extrusion-height': 3000,
+ 'fill-opacity': 0.5
+ }
+ });
+};
diff --git a/src/components/laanc/map/LaancDrawControl.js b/src/components/laanc/map/LaancDrawControl.js
index 0dd2ef9..58990f2 100644
--- a/src/components/laanc/map/LaancDrawControl.js
+++ b/src/components/laanc/map/LaancDrawControl.js
@@ -1,5 +1,4 @@
import { useEffect, useRef, useState } from 'react';
-import { InfoModal } from '../../modal/InfoModal';
import { ErrorModal } from '../../modal/ErrorModal';
import { useDispatch, useSelector } from 'react-redux';
import {
@@ -25,36 +24,42 @@ import Constants from 'mapbox-gl-draw-circle/node_modules/@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;
+ // 비행구역 타입
+ const { drawType } = useSelector(state => state.controlMapReducer);
+
+ // mapbox 기본 onClick 함수 저장
+ const originClickRef = useRef(null);
+
+ // 비행구역이 WayPoint일 때 bufferId
const [bufferId, setBufferId] = useState();
+ // 그리기모드 상태인지 유무 확인
const [isDrawDone, setIsDrawDone] = useState(false);
- const [alertModal, setAlertModal] = useState({
- isOpen: false,
- title: '',
- desc: ''
- });
+ // 지도 렌더 횟수
+ const [number, setNumber] = useState(0);
+
+ // 에러 모달창 정보
const [isErrorModal, setIsErrorModal] = useState({
isOpen: false,
title: '',
desc: ''
});
- const [number, setNumber] = useState(0);
-
+ // 비행구역 타입 변경에 따른 그리기모드 셋팅
useEffect(() => {
- if (mapControl.drawType === 'DONE') {
- // 구역 생성 후 바로 directMode
+ if (drawType === 'DONE') {
if (number !== 0) {
const obj = drawObj
.getAll()
.features.filter(o => o.properties.id !== 'BUFFER');
+
+ // 구역 생성 후 바로 directMode
if (obj.length > 0) {
drawObj.changeMode('direct_select', {
featureId: obj[obj.length - 1]?.id
@@ -64,10 +69,9 @@ export const LaancDrawControl = props => {
} else {
drawInit();
}
- }, [mapControl.drawType]);
-
- const originClickRef = useRef(null);
+ }, [drawType]);
+ // mapbox 기본 함수 오버라이드 및 함수 중복 등록 방지
useEffect(() => {
if (mapObject) {
const DrawLineStringMode = MapboxDraw.modes.draw_line_string;
@@ -75,6 +79,7 @@ export const LaancDrawControl = props => {
const DrawCircleMode = CircleMode;
const modeArr = [DrawLineStringMode, DrawPolygonMode, DrawCircleMode];
+ // 등록 함수 제거
const cleanUp = () => {
modeArr.forEach(m => {
m.onStop = null;
@@ -154,6 +159,7 @@ export const LaancDrawControl = props => {
setNumber(number + 1);
}
+ // 컴포넌트 언마운트 시
return () => {
dispatch(drawTypeChangeAction('DONE'));
mapObject.off('draw.update', handlerUpdateSetting);
@@ -162,10 +168,12 @@ export const LaancDrawControl = props => {
}
}, [mapObject]);
+ // 비행구역 데이터 지도에 다시 그려주기
useEffect(() => {
handlerPastDraw();
}, [props.areaCoordList]);
+ // 비행구역 설정을 올바르게 마쳤을 때 좌표 저장
useEffect(() => {
if (isDrawDone) {
props.handlerConfirm(props.areaCoordList);
@@ -173,7 +181,7 @@ export const LaancDrawControl = props => {
}
}, [isDrawDone]);
- // 클릭할 때마다 마커 찍어줌
+ // 클릭할 때마다 마커 표출
const handlerCustomOnClick = (state, e) => {
const mode = handlerReturnMode(drawObj.getMode());
const obj = state[mode?.toLowerCase()];
@@ -181,7 +189,7 @@ export const LaancDrawControl = props => {
if (mode && obj) {
const feature = drawObj.get(obj.id);
if (!feature) {
- console.log('2222222222');
+ // console.log('simple_select');
drawObj.changeMode('simple_select');
return;
}
@@ -220,7 +228,7 @@ export const LaancDrawControl = props => {
}
};
- // 도형 그리기 완료 시
+ // 비행구역 그리기 완료 시
const handlerFinishDraw = state => {
if (drawObj.getAll().features.length === 0) return;
@@ -293,8 +301,7 @@ export const LaancDrawControl = props => {
});
}
} else {
- console.log('333333333');
- // 좌표가 찍히기도 전에 틀만 생성된 도형들 삭제
+ // console.log('좌표가 찍히기도 전에 틀만 생성된 도형들 삭제');
// if (mode === 'CIRCLE') {
// const obj = state.polygon;
// drawObj.delete(obj.id);
@@ -307,7 +314,7 @@ export const LaancDrawControl = props => {
// 모든 비정상상황 체크
const handlerAbnormalityCheck = async data => {
- // radius도 있음
+ // radius 존재함
const { coords, mode, id } = data;
const areaInfo = handlerSettingAreaInfo(coords, mode);
@@ -411,7 +418,7 @@ export const LaancDrawControl = props => {
}
};
- // 도형 수정 시
+ // 비행구역 수정 시
const handlerUpdateSetting = e => {
if (e.features[0]) {
const { geometry, properties, id } = e.features[0];
@@ -482,7 +489,7 @@ export const LaancDrawControl = props => {
);
props.setViewCoordObj(viewCoordObj);
- // 계속 20개 미만이라 overAdd false처리(임시)
+ // 계속 20개 미만이라 overAdd false처리
props.handlerAddChange('overAdd', false);
};
@@ -565,12 +572,12 @@ export const LaancDrawControl = props => {
return true;
};
+ // 저장된 비행구역 데이터를 기반으로 지도에 다시 그려주기
const handlerPastDraw = () => {
if (props.areaCoordList) {
const objs = drawObj?.getAll().features;
const areas = props.areaCoordList;
if (areas.length > 0 && objs.length > 0) {
- // areas -> 현재는 1개이지만 추후에 데이터가 바뀌면 여러개의 도형도 처리 가능!
areas.map((area, idx) => {
const paths = [];
area.coordList.forEach(coord => paths.push([coord.lon, coord.lat]));
@@ -639,7 +646,7 @@ export const LaancDrawControl = props => {
}
objId = polygonId;
}
- // 마커를 삭제하고 다시 그려주기
+ // 마커를 삭제하고 다시 그려줌
const data = {
coord: area.areaType === 'LINE' ? paths : [paths],
id: objId
@@ -754,8 +761,9 @@ export const LaancDrawControl = props => {
return newObjId[0];
};
+ // 비행구역 기본셋팅
const drawInit = () => {
- const mode = mapControl.drawType;
+ const mode = drawType;
if (mode !== 'DONE') {
if (!mode || mode === 'RESET') {
handlerResetMode();
@@ -790,6 +798,7 @@ export const LaancDrawControl = props => {
drawObj.changeMode('simple_select');
};
+ // 그리기모드 셋팅
const handlerStartMode = mode => {
if (mode === 'LINE') {
drawObj.changeMode('draw_line_string');
@@ -802,7 +811,6 @@ export const LaancDrawControl = props => {
return (
<>
-
>
);
diff --git a/src/components/laanc/map/LaancDrawModal.js b/src/components/laanc/map/LaancDrawModal.js
index c97c27d..c340ab3 100644
--- a/src/components/laanc/map/LaancDrawModal.js
+++ b/src/components/laanc/map/LaancDrawModal.js
@@ -1,6 +1,7 @@
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
export default function LaancDrawModal({ modal, handler }) {
+ // 드론원스탑으로 새창 바로가기
const handlerDroneOneStop = () => {
window.open('https://drone.onestop.go.kr/', '드론원스탑');
handler();
diff --git a/src/components/laanc/map/LaancMapSearch.js b/src/components/laanc/map/LaancMapSearch.js
index 8ec4b9d..46f0276 100644
--- a/src/components/laanc/map/LaancMapSearch.js
+++ b/src/components/laanc/map/LaancMapSearch.js
@@ -4,8 +4,13 @@ import { useState } from 'react';
import { flightPlanAPI } from '../../../modules/basis/flight/apis/basisFlightApi';
export default function LaancMapSearch({ mapObject }) {
+ // 검색어
const [query, setQuery] = useState('');
+
+ // 검색 결과
const [searchRes, setSearchRes] = useState([]);
+
+ // 검색 여부
const [isSearch, setIsSearch] = useState(false);
// 지역 검색
@@ -15,6 +20,7 @@ export default function LaancMapSearch({ mapObject }) {
setSearchRes(res.data.items);
};
+ // 검색어 저장
const handlerSearchChange = e => {
const { name, value } = e.target;
@@ -23,12 +29,14 @@ export default function LaancMapSearch({ mapObject }) {
}
};
+ // 지역 검색 후 엔터 키
const handlerSearchEnter = e => {
if (e.key == 'Enter') {
handlerSearchRes();
}
};
+ // 해당 좌표로 지도 이동
const handlerSearchCoord = (mapx, mapy) => {
const numberString = [mapx, mapy];
const latlng = [];
diff --git a/src/components/laanc/step/LaacnStep3.js b/src/components/laanc/step/LaacnStep3.js
index 96c0ca8..3121f2f 100644
--- a/src/components/laanc/step/LaacnStep3.js
+++ b/src/components/laanc/step/LaacnStep3.js
@@ -41,10 +41,15 @@ export default function LaacnStep3({
}
};
- const [centeredModal2, setCenteredModal2] = useState(false);
+ // 성공 모달
+ const [confirmModal, setConfirmModal] = useState(false);
+ // 공문 모달
const [formModal, setFormModal] = useState(false);
- const [numPages, setNumPages] = useState(null); // total
+ // total
+ const [numPages, setNumPages] = useState(null);
+ // 로그인 정보
const { user } = useSelector(state => state.authState);
+ // pdf 데이터
const { laancPdf } = useSelector(state => state.laancState);
// PDF 다운로드
@@ -241,16 +246,16 @@ export default function LaacnStep3({
-