Browse Source

비행계획서 draw기능 polyline, polygon

pull/2/head
junh_eee(이준희) 1 year ago
parent
commit
2ece4d0ddc
  1. 1
      src/assets/css/custom.css
  2. 105
      src/components/basis/flight/plan/FlightPlanAreaMapBox.js
  3. 256
      src/components/map/mapbox/draw/MapBoxDraw.js

1
src/assets/css/custom.css

@ -846,3 +846,4 @@ background-size: 75% auto;
.box_4n div{width:50%;height:50vh;} .box_4n div{width:50%;height:50vh;}
.mapboxgl-popup-content {padding: 0 !important;border-radius:6px !important;} .mapboxgl-popup-content {padding: 0 !important;border-radius:6px !important;}
.mapboxgl-popup-tip {display: none!important;} .mapboxgl-popup-tip {display: none!important;}
.absolute {position: absolute!important;}

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

@ -51,6 +51,11 @@ export const FlightPlanAreaMapBox = props => {
const [formModal, setFormModal] = useState(false); const [formModal, setFormModal] = useState(false);
const geojson = {
type: 'FeatureCollection',
features: []
};
useEffect(() => { useEffect(() => {
mapBoxMapInit(); mapBoxMapInit();
@ -110,37 +115,7 @@ export const FlightPlanAreaMapBox = props => {
maxZoom: 16 maxZoom: 16
}); });
map.setTerrain({ source: 'mapbox-dem', exaggeration: 1.5 }); map.setTerrain({ source: 'mapbox-dem', exaggeration: 1.5 });
map.addLayer({
id: 'contour-labels',
type: 'symbol',
source: {
type: 'vector',
url: 'mapbox://mapbox.mapbox-terrain-v2'
},
'source-layer': 'contour',
layout: {
visibility: 'visible',
'symbol-placement': 'line',
'text-field': ['concat', ['to-string', ['get', 'ele']], 'm']
},
paint: {
'icon-color': '#877b59',
'icon-halo-width': 1,
'text-color': '#877b59',
'text-halo-width': 1
}
});
map.addLayer({
id: 'sky',
type: 'sky',
paint: {
'sky-type': 'atmosphere',
'sky-atmosphere-sun': [0.0, 90.0],
'sky-atmosphere-sun-intensity': 15
}
});
// 지형 3d end
// 등고선 start
map.addLayer({ map.addLayer({
id: 'contours', id: 'contours',
type: 'line', type: 'line',
@ -159,8 +134,6 @@ export const FlightPlanAreaMapBox = props => {
'line-width': 1 'line-width': 1
} }
}); });
// 등고선 end
// 3d building
map.addLayer( map.addLayer(
{ {
id: 'add-3d-buildings', id: 'add-3d-buildings',
@ -198,7 +171,65 @@ export const FlightPlanAreaMapBox = props => {
}, },
labelLayerId labelLayerId
); );
// 3d building
//mapDraw layer
map.addSource('geojson', {
type: 'geojson',
data: geojson
});
map.addLayer({
id: 'waypoint',
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({
id: 'guideline',
type: 'line',
source: 'geojson',
layout: {
'line-cap': 'round',
'line-join': 'round'
},
paint: {
'line-color': '#283046',
'line-width': 2,
'line-opacity': 0.1
},
filter: ['in', '$type', 'LineString']
});
map.addLayer({
id: 'polyline',
type: 'line',
source: 'geojson',
layout: {
'line-cap': 'round',
'line-join': 'round'
},
paint: {
'line-color': '#283046',
'line-width': 1
},
filter: ['in', '$type', 'LineString']
});
map.addLayer({
id: 'polygon',
type: 'fill',
source: 'geojson',
layout: {},
paint: {
'fill-color': '#7367F0',
'fill-opacity': 0.5,
'fill-outline-color': '#000000'
},
filter: ['in', '$type', 'Polygon']
});
setMapObject(map); setMapObject(map);
setIsMapLoad(true); setIsMapLoad(true);
}); });
@ -270,9 +301,9 @@ export const FlightPlanAreaMapBox = props => {
ref={mapContainer} ref={mapContainer}
style={{ width: '100%', height: '60vh' }} style={{ width: '100%', height: '60vh' }}
> >
{/* 여기에 draw 하는 파일 들어와야 함 */} {isMapLoad && mapObject ? (
{mapObject ? (
<MapBoxDraw <MapBoxDraw
geojson={geojson}
mapObject={mapObject} mapObject={mapObject}
mapboxgl={mapboxgl} mapboxgl={mapboxgl}
mode={mode} mode={mode}
@ -283,7 +314,7 @@ export const FlightPlanAreaMapBox = props => {
setDragCircle={setDragCircle} setDragCircle={setDragCircle}
/> />
) : null} ) : null}
<div className='d-flex search-comp'> <div className='d-flex search-comp absolute'>
<div className=''> <div className=''>
<InputGroup className='search-feather'> <InputGroup className='search-feather'>
<InputGroupAddon addonType='prepend'> <InputGroupAddon addonType='prepend'>

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

@ -1,8 +1,7 @@
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 { useEffect, useState } from 'react'; import { useCallback, useEffect, useState } from 'react';
import MapboxDraw from '@mapbox/mapbox-gl-draw';
export const MapBoxDraw = props => { export const MapBoxDraw = props => {
const dispatch = useDispatch(); const dispatch = useDispatch();
@ -12,11 +11,6 @@ export const MapBoxDraw = props => {
const isDone = props.isDone; const isDone = props.isDone;
const isDisabled = props.isDisabled; const isDisabled = props.isDisabled;
const [pastPolyline, setPastPolyline] = useState();
const [pastBuffer, setBuffer] = useState();
const [pastPolygon, setPastPolygon] = useState();
const [pastCircle, setCircle] = useState([]);
const pastDragCircle = props.pastDragCircle; const pastDragCircle = props.pastDragCircle;
const setDragCircle = props.setDragCircle; const setDragCircle = props.setDragCircle;
@ -37,38 +31,54 @@ export const MapBoxDraw = props => {
let mode = props.mode; let mode = props.mode;
let areaInfo;
let lastDistance;
let polyline;
let guideline;
let bufferPolygon;
let polygon;
let circle; let circle;
let radiusline; let radiusline;
let event = { const eventListener = {
clickEvent: '', clickEvent: '',
mousedownEvent: '', mousemoveEvent: '',
rightClickEvent: '' rightClickEvent: ''
}; };
let dragCircle = []; const geojson = props.geojson;
let dragCircleEvent = []; let wayPoint;
let guideLine;
let lineString;
let distanceMarker = []; let polygon;
useEffect(() => { useEffect(() => {
setRadiusCircle(props.dragSize); setRadiusCircle(props.dragSize);
}, [props.dragSize]); }, [props.dragSize]);
useEffect(() => { useEffect(() => {
drawInit(); if (mapControl.drawType) drawInit();
}, [mapControl.drawType]); }, [mapControl.drawType]);
const initFeature = type => {
return {
type: 'Feature',
geometry: {
type: type,
coordinates: []
},
properties: { id: '' }
};
};
const drawInit = () => { 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';
const drawType = mapControl.drawType; const drawType = mapControl.drawType;
handlerButtonClick(drawType); handlerButtonClick(drawType);
}; };
@ -85,55 +95,189 @@ export const MapBoxDraw = props => {
}; };
const handlerClearMode = () => { const handlerClearMode = () => {
// if (pastPolyline) { // geojson.features = [];
// pastP // wayPoint.geometry.coordinates = [];
// } // guideLine.geometry.coordinates = [];
// lineString.geometry.coordinates = [];
// mapObject.getSource('geojson').setData(geojson);
finishDraw();
};
const finishDraw = () => {
removeListener();
// geojson.features = [];
// wayPoint.geometry.coordinates = [];
// guideLine.geometry.coordinates = [];
// lineString.geometry.coordinates = [];
// mapObject.getSource('geojson').setData(geojson);
}; };
const handlerStartMode = mode => { const handlerStartMode = mode => {
if (!mode) return; if (!mode) return;
if (pastClickEvent) { eventListener.clickEvent = e => {
mapObject.removeEventListener(pastClickEvent); if (mode === 'LINE') onClickPolyline(e);
if (mode === 'POLYGON') onClickPolygon(e);
if (mode === 'RESET') handlerClearMode();
};
mapObject.on('click', eventListener.clickEvent);
};
const removeListener = () => {
mapObject.off('click', eventListener.clickEvent);
mapObject.off('mousemove', eventListener.mousemoveEvent);
mapObject.off('contextmenu', eventListener.rightClickEvent);
eventListener.clickEvent = '';
eventListener.mousemoveEvent = '';
eventListener.rightClickEvent = '';
};
const onClickPolyline = e => {
const features = mapObject.queryRenderedFeatures(e.point, {
layers: ['waypoint']
});
lineString.properties.id = 'polyline';
if (geojson.features.length > 1) {
geojson.features = geojson.features.filter(
geo => geo.properties?.id !== 'polyline'
);
} }
// event.clickEvent = mapObject.addEventListener('click', function (e) { if (features.length) {
// if (mode === 'LINE') { const id = features[0].properties.id;
// onClickPolyline(e); geojson.features = geojson.features.filter(
// } point => point.properties.id !== id
// else if (mode === 'POLYGON') { );
// onClickPolygon(e); } else {
// } else if (mode === 'CIRCLE') { const point = {
// onClickCircle(e); type: 'Feature',
// } geometry: {
// }); type: 'Point',
if (mode === 'CIRCLE') setPastClickEvent(event.clickEvent); coordinates: [e.lngLat.lng, e.lngLat.lat]
},
properties: { id: 'point' }
}; };
geojson.features.push(point);
}
const removeListener = () => { guideLine.properties.id = 'guideline';
mapObject.removeEventListener(event.clickEvent); guideLine.geometry.coordinates = [[e.lngLat.lng, e.lngLat.lat]];
mapObject.removeEventListener(pastClickEvent);
setPastClickEvent();
mapObject.removeEventListener(event.mousedownEvent); if (geojson.features.length > 1) {
mapObject.removeEventListener(event.rightClickEvent); //point들의 좌표만 뽑아서 polyline의 좌표로 넣어줌
if (!circle) $(document).off('mousemove.measure'); lineString.geometry.coordinates = geojson.features
.filter(point => point.properties?.id === 'point')
.map(point => point.geometry.coordinates);
geojson.features.push(lineString);
console.log(lineString.geometry, '>>>lineString');
} else {
eventListener.rightClickEvent = () => {
finishDraw();
};
mapObject.on('contextmenu', eventListener.rightClickEvent);
eventListener.mousemoveEvent = e => {
onMouseMovePolyline(e);
};
mapObject.on('mousemove', eventListener.mousemoveEvent);
}
mapObject.getSource('geojson').setData(geojson);
}; };
// const handlerFinishDraw = () => { const onMouseMovePolyline = e => {
// removeListener(); if (guideLine.geometry.coordinates.length > 1) {
guideLine.geometry.coordinates.pop();
// if(polyline) { //기존 guideline 제거
// if(guideline) { geojson.features = geojson.features.filter(
// guideline point => point.properties?.id !== 'guideline'
// } );
// } //새로운 가이드라인 push
// } geojson.features.push(guideLine);
}
guideLine.geometry.coordinates.push([e.lngLat.lng, e.lngLat.lat]);
const onClickPolyline = e => { mapObject.getSource('geojson').setData(geojson);
const coord = e.coord; };
const onClickPolygon = e => {
const features = mapObject.queryRenderedFeatures(e.point, {
layers: ['waypoint']
});
polygon.properties.id = 'polygon';
if (geojson.features.length > 1) {
geojson.features = geojson.features.filter(
geo => geo.properties?.id !== 'polygon'
);
}
if (features.length) {
const id = features[0].properties.id;
geojson.features = geojson.features.filter(
point => point.properties.id !== id
);
} else {
const point = {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [e.lngLat.lng, e.lngLat.lat]
},
properties: { id: 'point' }
};
geojson.features.push(point);
}
guideLine.properties.id = 'guideline';
guideLine.geometry.coordinates = [[e.lngLat.lng, e.lngLat.lat]];
if (geojson.features.length > 1) {
//point들의 좌표만 뽑아서 Polygon의 좌표로 넣어줌
polygon.geometry.coordinates = [
geojson.features
.filter(point => point.properties?.id === 'point')
.map(point => point.geometry.coordinates)
];
geojson.features.push(polygon);
} else {
eventListener.rightClickEvent = () => {
finishDraw();
};
mapObject.on('contextmenu', eventListener.rightClickEvent);
console.log(coord, '>>>coord'); eventListener.mousemoveEvent = e => {
onMouseMovePolygon(e);
};
mapObject.on('mousemove', eventListener.mousemoveEvent);
}
mapObject.getSource('geojson').setData(geojson);
};
const onMouseMovePolygon = e => {
if (polygon.geometry.coordinates.length > 0) {
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);
}
}
}; };
const addMileStone = (coord, text) => { const addMileStone = (coord, text) => {

Loading…
Cancel
Save