Browse Source

비행계획서 draw기능 작업중(2d, 3d switch 기능 임시 추가)

pull/2/head
junh_eee(이준희) 1 year ago
parent
commit
a0b753b3a7
  1. 255
      src/components/basis/flight/plan/FlightPlanAreaMapBox.js
  2. 499
      src/components/map/mapbox/draw/MapBoxDraw.js
  3. 10
      src/components/map/naver/draw/FlightPlanDraw.js
  4. 6
      src/containers/basis/flight/plan/FlightPlanAreaContainer.js

255
src/components/basis/flight/plan/FlightPlanAreaMapBox.js

@ -3,12 +3,11 @@ import 'mapbox-gl/dist/mapbox-gl.css';
import mapboxgl from 'mapbox-gl'; import mapboxgl from 'mapbox-gl';
import MapboxLanguage from '@mapbox/mapbox-gl-language'; import MapboxLanguage from '@mapbox/mapbox-gl-language';
import { MAPBOX_TOKEN } from '../../../../configs/constants'; import { MAPBOX_TOKEN } from '../../../../configs/constants';
import * as turf from '@turf/turf';
import proj4 from 'proj4/dist/proj4';
import { import {
Card, Card,
CardBody, CardBody,
Button, Button,
ButtonGroup,
Input, Input,
InputGroup, InputGroup,
InputGroupAddon, InputGroupAddon,
@ -20,12 +19,17 @@ import {
} from 'reactstrap'; } from 'reactstrap';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { initFlightBas } from '../../../../modules/basis/flight/models/basisFlightModel'; import { initFlightBas } from '../../../../modules/basis/flight/models/basisFlightModel';
import { AREA_DETAIL_INIT } from '../../../../modules/basis/flight/actions/basisFlightAction'; import {
AREA_COORDINATE_LIST_SAVE,
AREA_DETAIL_INIT,
FLIGHT_PLAN_AREA_BUFFER_LIST
} from '../../../../modules/basis/flight/actions/basisFlightAction';
import { flightPlanAPI } from '../../../../modules/basis/flight/apis/basisFlightApi'; import { flightPlanAPI } from '../../../../modules/basis/flight/apis/basisFlightApi';
import { Search } from 'react-feather'; import { Search } from 'react-feather';
import { FeatureAirZone } from '../../../map/mapbox/feature/FeatureAirZone'; import { FeatureAirZone } from '../../../map/mapbox/feature/FeatureAirZone';
import { drawTypeChangeAction } from '../../../../modules/control/map/actions/controlMapActions'; import { drawTypeChangeAction } from '../../../../modules/control/map/actions/controlMapActions';
import { MapBoxDraw } from '../../../map/mapbox/draw/MapBoxDraw'; import { MapBoxDraw } from '../../../map/mapbox/draw/MapBoxDraw';
import { WeatherContainer } from '../../../../containers/basis/flight/plan/WeatherContainer';
export const FlightPlanAreaMapBox = props => { export const FlightPlanAreaMapBox = props => {
const dispatch = useDispatch(); const dispatch = useDispatch();
@ -45,12 +49,55 @@ export const FlightPlanAreaMapBox = props => {
const [isSearch, setIsSearch] = useState(false); const [isSearch, setIsSearch] = useState(false);
const [dragSize, setDragSize] = useState(70); const [dragSize, setDragSize] = useState(70);
const [pastDragCircle, setDragCircle] = useState([]); const [pastDragCircle, setDragCircle] = useState();
const [number, setNumber] = useState(0); const [number, setNumber] = useState(0);
const [formModal, setFormModal] = useState(false); const [formModal, setFormModal] = useState(false);
const [layerId, setLayerId] = useState();
const buildingLayer = {
id: 'add-3d-buildings',
source: 'composite',
'source-layer': 'building',
filter: ['==', 'extrude', 'true'],
type: 'fill-extrusion',
minzoom: 15,
paint: {
'fill-extrusion-color': '#aaa',
// Use an 'interpolate' expression to
// add a smooth transition effect to
// the buildings as the user zooms in.
'fill-extrusion-height': [
'interpolate',
['linear'],
['zoom'],
15,
0,
15.05,
['get', 'height']
],
'fill-extrusion-base': [
'interpolate',
['linear'],
['zoom'],
15,
0,
15.05,
['get', 'min_height']
],
'fill-extrusion-opacity': 0.6
}
};
const terrainLayer = {
type: 'raster-dem',
url: 'mapbox://mapbox.mapbox-terrain-dem-v1'
// url: 'mapbox://mapbox.mapbox-street-v1',
// tileSize: 512,
// maxZoom: 16,
};
const geojson = { const geojson = {
type: 'FeatureCollection', type: 'FeatureCollection',
features: [] features: []
@ -64,6 +111,36 @@ export const FlightPlanAreaMapBox = props => {
}; };
}, []); }, []);
// useEffect(() => {
// pastDragCircle.forEach(c => c.setRadius(dragSize));
// }, [dragSize]);
// useEffect(() => {
// setIsMapLoad(true);
// }, [airArea]);
useEffect(() => {
setMode(mapControl.drawType);
}, [mapControl.drawType]);
useEffect(() => {
if (areaCoordList && mapObject) {
if (
areaCoordList[0].coordList[0].lat !== 0 &&
areaCoordList[0].coordList[0].lon !== 0
) {
if (number === 0) {
mapObject.setCenter([
areaCoordList[0].coordList[0].lon,
areaCoordList[0].coordList[0].lat
]);
setNumber(number + 1);
}
}
setMapAreaCoordList(areaCoordList);
}
}, [areaCoordList, mapObject, number]);
const mapBoxMapInit = () => { const mapBoxMapInit = () => {
const bufferZoom = {}; const bufferZoom = {};
if (areaCoordList) { if (areaCoordList) {
@ -107,77 +184,31 @@ export const FlightPlanAreaMapBox = props => {
const labelLayerId = layers.find( const labelLayerId = layers.find(
layer => layer.type === 'symbol' && layer.layout['text-field'] layer => layer.type === 'symbol' && layer.layout['text-field']
).id; ).id;
setLayerId(labelLayerId);
// 지형 3d start // 지형 3d start
map.addSource('mapbox-dem', { map.addSource('mapbox-dem', terrainLayer);
type: 'raster-dem',
url: 'mapbox://mapbox.mapbox-terrain-dem-v1',
tileSize: 512,
maxZoom: 16
});
map.setTerrain({ source: 'mapbox-dem', exaggeration: 1.5 }); map.setTerrain({ source: 'mapbox-dem', exaggeration: 1.5 });
map.addLayer({ map.addLayer(buildingLayer, labelLayerId);
id: 'contours',
type: 'line',
source: {
type: 'vector',
url: 'mapbox://mapbox.mapbox-terrain-v2'
},
'source-layer': 'contour',
layout: {
visibility: 'visible',
'line-join': 'round',
'line-cap': 'round'
},
paint: {
'line-color': '#877b59',
'line-width': 1
}
});
map.addLayer(
{
id: 'add-3d-buildings',
source: 'composite',
'source-layer': 'building',
filter: ['==', 'extrude', 'true'],
type: 'fill-extrusion',
minzoom: 15,
paint: {
'fill-extrusion-color': '#aaa',
// Use an 'interpolate' expression to
// add a smooth transition effect to
// the buildings as the user zooms in.
'fill-extrusion-height': [
'interpolate',
['linear'],
['zoom'],
15,
0,
15.05,
['get', 'height']
],
'fill-extrusion-base': [
'interpolate',
['linear'],
['zoom'],
15,
0,
15.05,
['get', 'min_height']
],
'fill-extrusion-opacity': 0.6
}
},
labelLayerId
);
//mapDraw layer //mapDraw layer
map.addSource('geojson', { map.addSource('geojson', {
type: 'geojson', type: 'geojson',
data: geojson data: geojson
}); });
map.addLayer({
id: 'vertex',
type: 'circle',
source: 'geojson',
paint: {
'circle-radius': 5,
'circle-color': '#ffffff',
'circle-stroke-color': '#000000',
'circle-stroke-width': 1
},
filter: ['in', '$type', 'Point']
});
map.addLayer({ map.addLayer({
id: 'waypoint', id: 'waypoint',
type: 'circle', type: 'circle',
@ -236,6 +267,31 @@ export const FlightPlanAreaMapBox = props => {
}); });
}; };
const handlerMapTypeSwitch = type => {
if (type === '2d') {
mapObject.dragRotate.disable();
if (mapObject.getLayer('add-3d-buildings')) {
mapObject.removeLayer('add-3d-buildings');
mapObject.setTerrain();
mapObject.removeSource('mapbox-dem');
mapObject.flyTo({
pitch: 0,
bearing: 0
});
}
} else if (type === '3d') {
mapObject.dragRotate.enable();
if (!mapObject.getLayer('add-3d-buildings')) {
mapObject.addLayer(buildingLayer, layerId);
mapObject.addSource('mapbox-dem', terrainLayer);
mapObject.setTerrain({ source: 'mapbox-dem', exaggeration: 1.5 });
}
}
};
//지역 검색
const handlerSearch = async () => { const handlerSearch = async () => {
const res = await flightPlanAPI.searchArea({ query: query }); const res = await flightPlanAPI.searchArea({ query: query });
setIsSearch(true); setIsSearch(true);
@ -285,6 +341,48 @@ export const FlightPlanAreaMapBox = props => {
dispatch(drawTypeChangeAction(val)); dispatch(drawTypeChangeAction(val));
}; };
const handlerInitCoordinates = () => {
const init = initFlightBas.initDetail.areaList.concat();
dispatch(AREA_COORDINATE_LIST_SAVE(init));
};
const handlerCoordinates = areaInfo => {
const initAreaList = initFlightBas.initDetail.areaList.concat();
const coordList = [];
areaInfo.coordinates.forEach((c, idx) => {
const coord = Object.assign({}, initFlightBas['coord']);
coord.lat = c.lat;
coord.lon = c.lon;
coordList.push(coord);
});
const areaList = initAreaList.map((area, idx) => {
return {
...area,
bufferZone: areaInfo.bufferZone,
areaType: areaInfo.areaType,
coordList: coordList
};
});
if (areaInfo.areaType === 'LINE') {
dispatch(FLIGHT_PLAN_AREA_BUFFER_LIST.request(areaList));
}
// setMapAreaCoordList(areaList);
};
const handlerConfirm = areaList => {
if (areaList === undefined) {
alert('영역을 설정해 주세요.');
return false;
}
dispatch(AREA_COORDINATE_LIST_SAVE(areaList));
};
return ( return (
<Card className='mb-0'> <Card className='mb-0'>
<CardBody> <CardBody>
@ -304,15 +402,19 @@ export const FlightPlanAreaMapBox = props => {
> >
{isMapLoad && mapObject ? ( {isMapLoad && mapObject ? (
<MapBoxDraw <MapBoxDraw
geojson={geojson}
mapObject={mapObject} mapObject={mapObject}
mapboxgl={mapboxgl} mapboxgl={mapboxgl}
mode={mode} mode={mode}
areaCoordList={mapAreaCoordList}
handlerCoordinates={handlerCoordinates}
handlerInitCoordinates={handlerInitCoordinates}
handlerConfirm={handlerConfirm}
isDone={props.isDone} isDone={props.isDone}
isDisabled={props.isDisabled} isDisabled={props.isDisabled}
dragSize={dragSize} dragSize={dragSize}
pastDragCircle={pastDragCircle} pastDragCircle={pastDragCircle}
setDragCircle={setDragCircle} setDragCircle={setDragCircle}
geojson={geojson}
/> />
) : null} ) : null}
<div className='d-flex search-comp absolute'> <div className='d-flex search-comp absolute'>
@ -370,6 +472,12 @@ export const FlightPlanAreaMapBox = props => {
</ul> </ul>
</div> </div>
</div> </div>
<div>
<ButtonGroup>
<Button onClick={() => handlerMapTypeSwitch('2d')}>2D</Button>
<Button onClick={() => handlerMapTypeSwitch('3d')}>3D</Button>
</ButtonGroup>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -421,6 +529,21 @@ export const FlightPlanAreaMapBox = props => {
<></> <></>
)} )}
</div> </div>
<Modal
isOpen={formModal}
toggle={handler}
className='modal-dialog-centered'
>
<ModalHeader toggle={handler}>날씨 정보</ModalHeader>
<ModalBody>
<WeatherContainer mapAreaCoordList={mapAreaCoordList} />
</ModalBody>
<ModalFooter>
<Button color='primary' onClick={handler}>
확인
</Button>
</ModalFooter>
</Modal>
</CardBody> </CardBody>
</Card> </Card>
); );

499
src/components/map/mapbox/draw/MapBoxDraw.js

@ -1,12 +1,21 @@
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { InfoModal } from '../../../modal/InfoModal'; import { InfoModal } from '../../../modal/InfoModal';
import * as turf from '@turf/turf'; import * as turf from '@turf/turf';
import { useCallback, useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
export const InitFeature = (type, id) => {
return {
type: 'Feature',
geometry: {
type: type,
coordinates: []
},
properties: { id: id, center: '' }
};
};
export const MapBoxDraw = props => { export const MapBoxDraw = props => {
const dispatch = useDispatch();
const mapControl = useSelector(state => state.controlMapReducer); const mapControl = useSelector(state => state.controlMapReducer);
const mapboxgl = props.mapboxgl;
const mapObject = props.mapObject; const mapObject = props.mapObject;
const isDone = props.isDone; const isDone = props.isDone;
const isDisabled = props.isDisabled; const isDisabled = props.isDisabled;
@ -17,7 +26,7 @@ export const MapBoxDraw = props => {
const [pastClickEvent, setPastClickEvent] = useState(); const [pastClickEvent, setPastClickEvent] = useState();
const [pastMarker, setPastMarker] = useState([]); const [pastMarker, setPastMarker] = useState([]);
const [figure, setFigure] = useState(); const [featureObj, setFeatureObj] = useState();
const [areaDetail, setAreaDetail] = useState(); const [areaDetail, setAreaDetail] = useState();
@ -34,25 +43,39 @@ export const MapBoxDraw = props => {
let radiusline; let radiusline;
const eventListener = { const eventListener = {
clickEvent: '', click: '',
mouseMoveEvent: '', mousemove: '',
rightClickEvent: '', contextmenu: '',
mousedownEvent: '', mousedown: '',
mouseUpEvent: '', mouseup: '',
mouseEnterEvent: '', mouseenter: '',
mouseLeaveEvent: '' mouseleave: ''
};
const areaInfo = {
coordinates: [],
bufferZone: 0,
areaType: ''
}; };
const geojson = props.geojson; const geojson = props.geojson;
let wayPoint; let wayPoint = InitFeature('Point', 'point');
let guideLine; let guideLine = InitFeature('LineString', 'guideline');
let lineString; let lineString = InitFeature('LineString', 'polyline');
let bufferPolygon = InitFeature('Polygon', 'buffer');
let polygon = InitFeature('Polygon', 'polygon');
let polygon; let circle = InitFeature('Polygon', 'circle');
let circle; //꼭짓점(polyline, polygon 사용)
let vertex = InitFeature('MultiPoint', 'vertex');
let dragCircleIdx;
const canvas = mapObject.getCanvasContainer(); const canvas = mapObject.getCanvasContainer();
const [pastPolyline, setPolyline] = useState();
const [pastBuffer, setBuffer] = useState();
const [pastPolygon, setPolygon] = useState();
const [pastCircle, setCircle] = useState();
useEffect(() => { useEffect(() => {
setRadiusCircle(props.dragSize); setRadiusCircle(props.dragSize);
@ -62,35 +85,29 @@ export const MapBoxDraw = props => {
if (mapControl.drawType) drawInit(); if (mapControl.drawType) drawInit();
}, [mapControl.drawType]); }, [mapControl.drawType]);
const initFeature = type => { useEffect(() => {
return { if (featureObj) {
type: 'Feature', props.handlerConfirm(props.areaCoordList);
geometry: { }
type: type, }, [featureObj]);
coordinates: []
},
properties: { id: '', center: '' }
};
};
const drawInit = () => {
wayPoint = initFeature('Point');
wayPoint.properties.id = 'point';
guideLine = initFeature('LineString');
guideLine.properties.id = 'guideline';
lineString = initFeature('LineString');
lineString.properties.id = 'polyline';
polygon = initFeature('Polygon');
polygon.properties.id = 'polygon';
circle = initFeature('Polygon'); useEffect(() => {
circle.properties.id = 'polygon'; const areaCoordList = props.areaCoordList[0];
if (areaCoordList.areaType === 'LINE') {
if (
areaCoordList.bufferCoordList[0].lat !== 0 &&
areaCoordList.bufferCoordList[0].lon !== 0
) {
handlerPastDraw();
}
} else if (areaCoordList.areaType === 'POLYGON') {
handlerPastDraw();
}
}, [props.areaCoordList]);
const drawType = mapControl.drawType; const drawInit = () => {
handlerButtonClick(drawType); handlerButtonClick(mapControl.drawType);
}; };
//그리기 타입 선택 //그리기 타입 선택
@ -101,58 +118,101 @@ export const MapBoxDraw = props => {
mode = null; mode = null;
return; return;
} }
handlerStartMode(newMode); handlerStartMode(newMode);
}; };
const handlerClearMode = () => { const handlerClearMode = () => {
// geojson.features = []; setPolyline();
// wayPoint.geometry.coordinates = []; setPolygon();
// guideLine.geometry.coordinates = []; setCircle();
// lineString.geometry.coordinates = [];
// mapObject.getSource('geojson').setData(geojson);
finishDraw();
};
const finishDraw = () => { geojson.features = [];
removeListener(); mapObject.getSource('geojson').setData(geojson);
// geojson.features = []; finishDraw();
// wayPoint.geometry.coordinates = []; props.handlerInitCoordinates();
// guideLine.geometry.coordinates = [];
// lineString.geometry.coordinates = [];
// mapObject.getSource('geojson').setData(geojson);
}; };
const handlerStartMode = mode => { const handlerStartMode = mode => {
if (!mode) return; if (!mode) return;
eventListener.clickEvent = e => { handlerAddEvent('click', clickEve, '', 'on');
if (mode === 'LINE') onClickFeature(e, lineString, 'polyline');
if (mode === 'POLYGON') onClickFeature(e, polygon, 'polygon');
if (mode === 'CIRCLE') onClickCircle(e);
if (mode === 'RESET') handlerClearMode();
};
mapObject.on('click', eventListener.clickEvent);
}; };
const removeListener = () => { const removeListener = () => {
mapObject.off('click', eventListener.clickEvent); console.log('remove');
mapObject.off('mousemove', eventListener.mouseMoveEvent); mapObject.off('click', clickEve);
mapObject.off('contextmenu', eventListener.rightClickEvent); mapObject.off('mouseup', onMouseUp);
mapObject.off('mousedown', onMouseDown);
mapObject.off('mousemove', onMouseMove);
mapObject.off('mousemove', onMouseMovePolyline);
mapObject.off('mousemove', onMouseMovePolygon);
mapObject.off('contextmenu', finishDraw);
};
const finishDraw = e => {
removeListener();
console.log('finish');
const drawType = mapControl.drawType;
const path = geojson.features
.filter(point => point.properties?.id === 'point')
.map(point => point.geometry.coordinates);
eventListener.clickEvent = ''; if (path.length > 0) {
eventListener.mouseMoveEvent = ''; if (drawType === 'LINE') {
eventListener.rightClickEvent = ''; if (path.length > 1) {
geojson.features = geojson.features.filter(
geo => geo.properties?.id !== 'guideline'
);
handlerAreaInfo(lineString.geometry.coordinates);
setFeatureObj(lineString);
} else {
setAlertModal({
isOpen: true,
title: '좌표 최소 개수',
desc: '좌표를 두 개 점으로 이어주세요.'
});
lineString.geometry.coordinates = [];
geojson.features = [];
handlerAddEvent('click', clickEve, '', 'on');
}
mapObject.getSource('geojson').setData(geojson);
} else if (drawType === 'POLYGON') {
if (path.length > 2) {
polygon.geometry.coordinates = [path];
handlerAreaInfo(polygon.geometry.coordinates[0]);
setFeatureObj(polygon);
} else {
setAlertModal({
isOpen: true,
title: '좌표 최소 개수',
desc: '좌표를 세 개 점으로 이어주세요.'
});
polygon.geometry.coordinates = [];
geojson.features = [];
handlerAddEvent('click', clickEve, '', 'on');
}
mapObject.getSource('geojson').setData(geojson);
}
}
};
const clickEve = e => {
const drawType = mapControl.drawType;
if (drawType === 'LINE') onClickFeature(e, lineString, 'polyline');
if (drawType === 'POLYGON') onClickFeature(e, polygon, 'polygon');
if (drawType === 'CIRCLE') onClickCircle(e);
}; };
//polyline, polygon 생성 //polyline, polygon 생성
const onClickFeature = (e, figureObj, id) => { const onClickFeature = (e, featureObj, id) => {
const features = mapObject.queryRenderedFeatures(e.point, { const features = mapObject.queryRenderedFeatures(e.point, {
layers: ['waypoint'] layers: ['waypoint']
}); });
figureObj.properties.id = id; featureObj.properties.id = id;
if (geojson.features.length > 1) { if (geojson.features.length > 1) {
geojson.features = geojson.features.filter( geojson.features = geojson.features.filter(
geo => geo.properties?.id !== id geo => geo.properties?.id !== id
@ -165,13 +225,17 @@ export const MapBoxDraw = props => {
point => point.properties.id !== id point => point.properties.id !== id
); );
} else { } else {
const index = geojson.features.filter(
geo => geo.properties?.id === 'point'
).length;
const point = { const point = {
type: 'Feature', type: 'Feature',
geometry: { geometry: {
type: 'Point', type: 'Point',
coordinates: [e.lngLat.lng, e.lngLat.lat] coordinates: [e.lngLat.lng, e.lngLat.lat]
}, },
properties: { id: 'point' } properties: { id: 'point', index: index }
}; };
geojson.features.push(point); geojson.features.push(point);
} }
@ -184,25 +248,65 @@ export const MapBoxDraw = props => {
.filter(point => point.properties?.id === 'point') .filter(point => point.properties?.id === 'point')
.map(point => point.geometry.coordinates); .map(point => point.geometry.coordinates);
figureObj.geometry.coordinates = featureObj.geometry.coordinates =
id === 'polyline' ? coordinates : [coordinates]; id === 'polyline' ? coordinates : [coordinates];
geojson.features.push(figureObj); geojson.features.push(featureObj);
} else { } else {
eventListener.rightClickEvent = () => { handlerAddEvent('contextmenu', finishDraw, '', 'on');
finishDraw(); handlerAddEvent(
'mousemove',
id === 'polyline' ? onMouseMovePolyline : onMouseMovePolygon,
'',
'on'
);
}
mapObject.getSource('geojson').setData(geojson);
}; };
mapObject.on('contextmenu', eventListener.rightClickEvent);
eventListener.mouseMoveEvent = e => { //polyline 가이드 생성
id === 'polyline' ? onMouseMovePolyline(e) : onMouseMovePolygon(e); const onMouseMovePolyline = e => {
if (guideLine.geometry.coordinates.length > 1) {
guideLine.geometry.coordinates.pop();
//기존 guideline 제거
geojson.features = geojson.features.filter(
point => point.properties?.id !== 'guideline'
);
//새로운 가이드라인 push
geojson.features.push(guideLine);
}
guideLine.geometry.coordinates.push([e.lngLat.lng, e.lngLat.lat]);
mapObject.getSource('geojson').setData(geojson);
}; };
mapObject.on('mousemove', eventListener.mouseMoveEvent);
//polygon 가이드 생성
const onMouseMovePolygon = e => {
if (polygon.geometry.coordinates.length > 0) {
const proj = mapObject.getProjection();
if (polygon.geometry.coordinates[0].length > 1) {
if (guideLine.geometry.coordinates.length > 1) {
guideLine.geometry.coordinates.pop();
polygon.geometry.coordinates[0].pop();
geojson.features = geojson.features.filter(
point => point.properties?.id !== 'polygon'
);
geojson.features.push(polygon);
} }
guideLine.geometry.coordinates.push([e.lngLat.lng, e.lngLat.lat]);
polygon.geometry.coordinates[0].push([e.lngLat.lng, e.lngLat.lat]);
mapObject.getSource('geojson').setData(geojson); mapObject.getSource('geojson').setData(geojson);
}
}
}; };
//circle 생성 //circle 생성
const onClickCircle = e => { const onClickCircle = e => {
console.log('click');
circle.properties.id = 'circle'; circle.properties.id = 'circle';
geojson.features.pop(); geojson.features.pop();
@ -219,58 +323,60 @@ export const MapBoxDraw = props => {
circle.geometry.coordinates = circleCoords; circle.geometry.coordinates = circleCoords;
geojson.features.push(circle); geojson.features.push(circle);
eventListener.mouseEnterEvent = () => { if (eventListener.mousedown === '') {
onMouseEnter(); handlerAddEvent('mousedown', onMouseDown, 'polygon', 'on');
}; }
mapObject.on('mouseenter', 'polygon', eventListener.mouseEnterEvent);
eventListener.mouseLeaveEvent = () => {
onMouseLeave();
};
mapObject.on('mouseleave', 'polygon', eventListener.mouseLeaveEvent);
eventListener.mousedownEvent = e => {
//mouseDown event추가하기
onMouseDown(e);
};
mapObject.on('mousedown', 'polygon', eventListener.mousedownEvent);
mapObject.getSource('geojson').setData(geojson); mapObject.getSource('geojson').setData(geojson);
}; };
//원에 마우스 닿았을 때
const onMouseEnter = () => {
mapObject.setPaintProperty('polygon', 'fill-color', '#3bb2d0');
canvas.style.cursor = 'move';
};
//원에 마우스 떠났을 때
const onMouseLeave = () => {
mapObject.setPaintProperty('polygon', 'fill-color', '#7367F0');
canvas.style.cursor = '';
};
//원에 마우스 클릭되었을 때
const onMouseDown = e => { const onMouseDown = e => {
e.preventDefault(); e.preventDefault();
console.log('down');
canvas.style.cursor = 'grab'; canvas.style.cursor = 'grab';
eventListener.mouseMoveEvent = e => { if (vertex.geometry.coordinates.length > 0) {
onMouseMove(e); dragCircleIdx = e.features[0].properties.index;
}; }
mapObject.on('mousemove', eventListener.mouseMoveEvent);
eventListener.mouseUpEvent = e => { if (circle.geometry.coordinates.length > 0) {
onMouseUp(e); //이벤트 다 지워
}; removeListener();
mapObject.once('mouseup', eventListener.mouseUpEvent); }
handlerAddEvent('mousemove', onMouseMove, '', 'on');
handlerAddEvent('mouseup', onMouseUp, '', 'on');
mapObject.off('click', clickEve);
}; };
//원에 마우스 클릭되어서 움직일 때
const onMouseMove = e => { const onMouseMove = e => {
canvas.style.cursor = 'grabbing'; canvas.style.cursor = 'grabbing';
if (vertex.geometry.coordinates.length > 0) {
geojson.features.map(geo => {
if (geo.properties?.id === 'polyline') {
geo.geometry.coordinates[dragCircleIdx] = [
e.lngLat.lng,
e.lngLat.lat
];
}
if (geo.properties?.id === 'polygon') {
geo.geometry.coordinates[0][dragCircleIdx] = [
e.lngLat.lng,
e.lngLat.lat
];
}
if (geo.properties?.index === dragCircleIdx) {
geo.geometry.coordinates = [e.lngLat.lng, e.lngLat.lat];
}
});
}
if (circle.geometry.coordinates.length > 0) {
const centerCoord = turf.point(circle.properties.center); const centerCoord = turf.point(circle.properties.center);
const currentCoord = turf.point([e.lngLat.lng, e.lngLat.lat]); const currentCoord = turf.point([e.lngLat.lng, e.lngLat.lat]);
@ -288,6 +394,7 @@ export const MapBoxDraw = props => {
.geometry.coordinates; .geometry.coordinates;
circle.geometry.coordinates = circleCoords; circle.geometry.coordinates = circleCoords;
}
mapObject.getSource('geojson').setData(geojson); mapObject.getSource('geojson').setData(geojson);
}; };
@ -295,45 +402,149 @@ export const MapBoxDraw = props => {
const onMouseUp = e => { const onMouseUp = e => {
canvas.style.cursor = ''; canvas.style.cursor = '';
mapObject.off('mousemove', eventListener.mouseMoveEvent); console.log('up');
eventListener.onMouseMove = '';
mapObject.off('mousemove', onMouseMove);
mapObject.off('mouseup', onMouseUp);
mapObject.off('click', clickEve);
if (circle.geometry.coordinates.length > 0) {
handlerAddEvent('click', clickEve, '', 'on');
}
}; };
//polyline 가이드 생성 //이벤트 리스너 생성
const onMouseMovePolyline = e => { const handlerAddEvent = (eventType, eventFunction, target, time) => {
if (guideLine.geometry.coordinates.length > 1) { Object.keys(eventListener).map(eve => {
guideLine.geometry.coordinates.pop(); if (eve === eventType) {
eventListener[eve] = e => {
eventFunction(e);
};
}
});
//기존 guideline 제거 if (time === 'on') {
geojson.features = geojson.features.filter( target !== ''
point => point.properties?.id !== 'guideline' ? mapObject.on(eventType, target, eventFunction)
); : mapObject.on(eventType, eventFunction);
//새로운 가이드라인 push } else if (time === 'once') {
geojson.features.push(guideLine); target !== ''
? mapObject.once(eventType, target, eventFunction)
: mapObject.once(eventType, eventFunction);
} }
guideLine.geometry.coordinates.push([e.lngLat.lng, e.lngLat.lat]); };
mapObject.getSource('geojson').setData(geojson); const handlerAreaInfo = path => {
let bufferZone = 100;
if (polygon.geometry.coordinates.length > 0) bufferZone = 0;
const prePath = [];
if (path) {
path.forEach(item => {
const p = {
lat: item[1],
lon: item[0]
};
prePath.push(p);
});
}
if (lineString.geometry.coordinates.length > 0) {
areaInfo.coordinates = prePath;
areaInfo.bufferZone = bufferZone;
areaInfo.areaType = 'LINE';
} else if (polygon.geometry.coordinates.length > 0) {
areaInfo.coordinates = prePath;
areaInfo.bufferZone = bufferZone;
areaInfo.areaType = 'POLYGON';
} else if (circle.geometry.coordinates.length > 0) {
const point = {
lat: circle.properties.center[1],
lon: circle.properties.center[0]
};
areaInfo.coordinates.push(point);
areaInfo.bufferZone =
turf.distance(
turf.point(circle.properties.center),
turf.point(circle.geometry.coordinates[0]),
{ units: 'kilometers' }
) * 1000;
areaInfo.areaType = 'CIRCLE';
}
props.handlerCoordinates(areaInfo);
}; };
//polygon 가이드 생성 const handlerPastDraw = () => {
const onMouseMovePolygon = e => { if (props.areaCoordList) {
if (polygon.geometry.coordinates.length > 0) { console.log('pastDraw');
if (polygon.geometry.coordinates[0].length > 1) {
if (guideLine.geometry.coordinates.length > 1) { const areas = props.areaCoordList[0];
guideLine.geometry.coordinates.pop();
polygon.geometry.coordinates[0].pop(); const paths = [];
areas.coordList.forEach(coord => {
const path = [coord.lon, coord.lat];
paths.push(path);
});
//let이라서 지워지는 도형 다시 생성
const reCreatePoint = featureObj => {
const id = featureObj.properties?.id;
featureObj.geometry.coordinates = id === 'polyline' ? paths : [paths];
if (id === 'polyline') {
setPolyline(featureObj);
//버퍼 생성
if (areas.bufferCoordList) {
const bufferPaths = [];
areas.bufferCoordList.forEach(bfCoord => {
const path = [bfCoord.lon, bfCoord.lat];
bufferPaths.push(path);
});
if (pastBuffer) {
geojson.features = geojson.features.filter( geojson.features = geojson.features.filter(
point => point.properties?.id !== 'polygon' geo => geo.properties?.id !== 'buffer'
); );
}
geojson.features.push(polygon); bufferPolygon.geometry.coordinates = [bufferPaths];
setBuffer(bufferPolygon);
geojson.features.push(bufferPolygon);
} }
guideLine.geometry.coordinates.push([e.lngLat.lng, e.lngLat.lat]); } else if (id === 'polygon') {
polygon.geometry.coordinates[0].push([e.lngLat.lng, e.lngLat.lat]); setPolygon(featureObj);
}
geojson.features.push(featureObj);
//서버에 좌표 전달 편하게 하기 위해서 vertex에 좌표를 저장해주지만
//geojson에 넣어줄 데이터는 point임(index 때문에)
paths.map((path, index) => {
const point = {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: path
},
properties: { id: 'point', index: index }
};
vertex.geometry.coordinates.push(path);
geojson.features.push(point);
});
handlerAddEvent('mousedown', onMouseDown, 'waypoint', 'on');
mapObject.setPaintProperty('waypoint', 'circle-radius', 8);
mapObject.getSource('geojson').setData(geojson); mapObject.getSource('geojson').setData(geojson);
};
if (areas.areaType === 'LINE') {
reCreatePoint(lineString);
}
if (areas.areaType === 'POLYGON') {
reCreatePoint(polygon);
}
if (areas.areaType === 'CIRCLE') {
} }
} }
}; };

10
src/components/map/naver/draw/FlightPlanDraw.js

@ -69,6 +69,7 @@ export const FlightPlanDraw_init = props => {
}, [mapControl.drawType]); }, [mapControl.drawType]);
useEffect(() => { useEffect(() => {
console.log(props.areaCoordList, '빈양식');
handleDetailDraw(); handleDetailDraw();
}, [props.areaCoordList]); }, [props.areaCoordList]);
@ -80,6 +81,7 @@ export const FlightPlanDraw_init = props => {
}, [figure]); }, [figure]);
useEffect(() => { useEffect(() => {
console.log(areaDetail, '채워진양식?');
if (pastPolyline) { if (pastPolyline) {
handleBufferList(); handleBufferList();
} }
@ -184,6 +186,7 @@ export const FlightPlanDraw_init = props => {
if (polypaths.length >= 2) { if (polypaths.length >= 2) {
setPolyline(polyline); setPolyline(polyline);
setAreaInfo(polypaths); setAreaInfo(polypaths);
setFigure(polyline);
} else { } else {
setAlertModal({ setAlertModal({
isOpen: true, isOpen: true,
@ -193,7 +196,6 @@ export const FlightPlanDraw_init = props => {
polyline.setMap(null); polyline.setMap(null);
polyline = ''; polyline = '';
} }
setFigure(polyline);
} else if (polygon) { } else if (polygon) {
let path = polygon.getPath(); let path = polygon.getPath();
path.pop(); path.pop();
@ -212,6 +214,7 @@ export const FlightPlanDraw_init = props => {
if (polygonpaths.length >= 3) { if (polygonpaths.length >= 3) {
setPolygon(polygon); setPolygon(polygon);
setAreaInfo(polygonpaths); setAreaInfo(polygonpaths);
setFigure(polygon);
} else { } else {
setAlertModal({ setAlertModal({
isOpen: true, isOpen: true,
@ -221,8 +224,6 @@ export const FlightPlanDraw_init = props => {
polygon.setMap(null); polygon.setMap(null);
polygon = ''; polygon = '';
} }
setFigure(polygon);
} }
}; };
@ -634,6 +635,7 @@ export const FlightPlanDraw_init = props => {
//bufferline 생성 //bufferline 생성
if (areas.bufferCoordList) { if (areas.bufferCoordList) {
console.log(areas.bufferCoordList, '>>>');
const bufferPaths = []; const bufferPaths = [];
areas.bufferCoordList.forEach(bfCoord => { areas.bufferCoordList.forEach(bfCoord => {
@ -879,8 +881,6 @@ export const FlightPlanDraw_init = props => {
if (circle) { if (circle) {
midPoint = coord; midPoint = coord;
} else { } else {
console.log(dis1.y + dis2.y, 'y더한 값');
console.log((dis1.y + dis2.y) / 2, 'y나눈 값');
midPoint = new naver.maps.LatLng( midPoint = new naver.maps.LatLng(
(dis1.y + dis2.y) / 2, (dis1.y + dis2.y) / 2,
(dis1.x + dis2.x) / 2 (dis1.x + dis2.x) / 2

6
src/containers/basis/flight/plan/FlightPlanAreaContainer.js

@ -45,11 +45,7 @@ const FlightPlanAreaContainer = ({ handleModal, isDone, isDisabled }) => {
isDone={isDone} isDone={isDone}
isDisabled={isDisabled} isDisabled={isDisabled}
/> />
) : // <FlightPlanAreaMapBox ) : // <FlightPlanAreaMapBox isDone={isDone} isDisabled={isDisabled} />
// handleConfirm={handleConfirm}
// isDone={isDone}
// isDisabled={isDisabled}
// />
null} null}
</Col> </Col>
<Col md={6} lg={6}> <Col md={6} lg={6}>

Loading…
Cancel
Save