diff --git a/src/components/basis/flight/plan/FlightPlanAreaMapBox.js b/src/components/basis/flight/plan/FlightPlanAreaMapBox.js index 6eb4f5e..6f33087 100644 --- a/src/components/basis/flight/plan/FlightPlanAreaMapBox.js +++ b/src/components/basis/flight/plan/FlightPlanAreaMapBox.js @@ -93,7 +93,8 @@ export const FlightPlanAreaMapBox = props => { container: 'map', // container ID style: 'mapbox://styles/mapbox/streets-v12', // style URL center: [126.612647, 37.519893], // starting position [lng, lat] - zoom: !areaCoordList ? 11 : bufferZoom.bufferzoom, // starting zoom + // zoom: !areaCoordList ? 14 : bufferZoom.bufferzoom, // starting zoom + zoom: 15, antialias: true }); diff --git a/src/components/map/mapbox/draw/MapBoxDraw.js b/src/components/map/mapbox/draw/MapBoxDraw.js index 4522a2f..dd9bbcf 100644 --- a/src/components/map/mapbox/draw/MapBoxDraw.js +++ b/src/components/map/mapbox/draw/MapBoxDraw.js @@ -31,13 +31,16 @@ export const MapBoxDraw = props => { let mode = props.mode; - let circle; let radiusline; const eventListener = { clickEvent: '', - mousemoveEvent: '', - rightClickEvent: '' + mouseMoveEvent: '', + rightClickEvent: '', + mousedownEvent: '', + mouseUpEvent: '', + mouseEnterEvent: '', + mouseLeaveEvent: '' }; const geojson = props.geojson; @@ -47,6 +50,10 @@ export const MapBoxDraw = props => { let polygon; + let circle; + + const canvas = mapObject.getCanvasContainer(); + useEffect(() => { setRadiusCircle(props.dragSize); }, [props.dragSize]); @@ -62,7 +69,7 @@ export const MapBoxDraw = props => { type: type, coordinates: [] }, - properties: { id: '' } + properties: { id: '', center: '' } }; }; @@ -79,6 +86,9 @@ export const MapBoxDraw = props => { polygon = initFeature('Polygon'); polygon.properties.id = 'polygon'; + circle = initFeature('Polygon'); + circle.properties.id = 'polygon'; + const drawType = mapControl.drawType; handlerButtonClick(drawType); }; @@ -118,8 +128,9 @@ export const MapBoxDraw = props => { if (!mode) return; eventListener.clickEvent = e => { - if (mode === 'LINE') onClickPolyline(e); - if (mode === 'POLYGON') onClickPolygon(e); + 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); @@ -127,23 +138,24 @@ export const MapBoxDraw = props => { const removeListener = () => { mapObject.off('click', eventListener.clickEvent); - mapObject.off('mousemove', eventListener.mousemoveEvent); + mapObject.off('mousemove', eventListener.mouseMoveEvent); mapObject.off('contextmenu', eventListener.rightClickEvent); eventListener.clickEvent = ''; - eventListener.mousemoveEvent = ''; + eventListener.mouseMoveEvent = ''; eventListener.rightClickEvent = ''; }; - const onClickPolyline = e => { + //polyline, polygon 생성 + const onClickFeature = (e, figureObj, id) => { const features = mapObject.queryRenderedFeatures(e.point, { layers: ['waypoint'] }); - lineString.properties.id = 'polyline'; + figureObj.properties.id = id; if (geojson.features.length > 1) { geojson.features = geojson.features.filter( - geo => geo.properties?.id !== 'polyline' + geo => geo.properties?.id !== id ); } @@ -168,27 +180,126 @@ export const MapBoxDraw = props => { guideLine.geometry.coordinates = [[e.lngLat.lng, e.lngLat.lat]]; if (geojson.features.length > 1) { - //point들의 좌표만 뽑아서 polyline의 좌표로 넣어줌 - lineString.geometry.coordinates = geojson.features + const coordinates = geojson.features .filter(point => point.properties?.id === 'point') .map(point => point.geometry.coordinates); - geojson.features.push(lineString); - console.log(lineString.geometry, '>>>lineString'); + figureObj.geometry.coordinates = + id === 'polyline' ? coordinates : [coordinates]; + geojson.features.push(figureObj); } else { eventListener.rightClickEvent = () => { finishDraw(); }; mapObject.on('contextmenu', eventListener.rightClickEvent); - eventListener.mousemoveEvent = e => { - onMouseMovePolyline(e); + eventListener.mouseMoveEvent = e => { + id === 'polyline' ? onMouseMovePolyline(e) : onMouseMovePolygon(e); }; - mapObject.on('mousemove', eventListener.mousemoveEvent); + mapObject.on('mousemove', eventListener.mouseMoveEvent); } mapObject.getSource('geojson').setData(geojson); }; + //circle 생성 + const onClickCircle = e => { + circle.properties.id = 'circle'; + geojson.features.pop(); + + const center = [e.lngLat.lng, e.lngLat.lat]; + const radius = 100; + const options = { + steps: 360, + units: 'kilometers' + }; + const circleCoords = turf.circle(center, radius / 1000, options).geometry + .coordinates; + + circle.properties.center = center; + circle.geometry.coordinates = circleCoords; + geojson.features.push(circle); + + eventListener.mouseEnterEvent = () => { + onMouseEnter(); + }; + 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); + }; + + //원에 마우스 닿았을 때 + 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 => { + e.preventDefault(); + + canvas.style.cursor = 'grab'; + + eventListener.mouseMoveEvent = e => { + onMouseMove(e); + }; + mapObject.on('mousemove', eventListener.mouseMoveEvent); + + eventListener.mouseUpEvent = e => { + onMouseUp(e); + }; + mapObject.once('mouseup', eventListener.mouseUpEvent); + }; + + //원에 마우스 클릭되어서 움직일 때 + const onMouseMove = e => { + canvas.style.cursor = 'grabbing'; + + const centerCoord = turf.point(circle.properties.center); + const currentCoord = turf.point([e.lngLat.lng, e.lngLat.lat]); + + const distanceOptions = { units: 'kilometers' }; + //circle 센터와 e.coord간의 거리(meters) + const currentToCenter = + turf.distance(centerCoord, currentCoord, distanceOptions) * 1000; + + const center = circle.properties.center; + const options = { + steps: 360, + units: 'kilometers' + }; + const circleCoords = turf.circle(center, currentToCenter / 1000, options) + .geometry.coordinates; + + circle.geometry.coordinates = circleCoords; + + mapObject.getSource('geojson').setData(geojson); + }; + + const onMouseUp = e => { + canvas.style.cursor = ''; + + mapObject.off('mousemove', eventListener.mouseMoveEvent); + eventListener.onMouseMove = ''; + }; + + //polyline 가이드 생성 const onMouseMovePolyline = e => { if (guideLine.geometry.coordinates.length > 1) { guideLine.geometry.coordinates.pop(); @@ -205,60 +316,7 @@ export const MapBoxDraw = props => { mapObject.getSource('geojson').setData(geojson); }; - 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); - - eventListener.mousemoveEvent = e => { - onMouseMovePolygon(e); - }; - mapObject.on('mousemove', eventListener.mousemoveEvent); - } - mapObject.getSource('geojson').setData(geojson); - }; - + //polygon 가이드 생성 const onMouseMovePolygon = e => { if (polygon.geometry.coordinates.length > 0) { if (polygon.geometry.coordinates[0].length > 1) {