diff --git a/package-lock.json b/package-lock.json index ee88100b..d76f8028 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14305,6 +14305,11 @@ } } }, + "mapbox-gl-draw-waypoint": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/mapbox-gl-draw-waypoint/-/mapbox-gl-draw-waypoint-1.2.3.tgz", + "integrity": "sha512-O6vAAKjPTcTyPth0Y4DI/QDLljFitRYM5f3iGgTNNgJa/KKPd1MrqbM0h5HPQ6EfTWpUGG878dsIsMq8agOUsw==" + }, "marker-clusterer-plus": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/marker-clusterer-plus/-/marker-clusterer-plus-2.1.4.tgz", diff --git a/package.json b/package.json index e9097e9d..6989ee5b 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "leaflet": "1.6.0", "mapbox-gl": "^2.15.0", "mapbox-gl-draw-circle": "1.1.2", + "mapbox-gl-draw-waypoint": "1.2.3", "nouislider": "14.6.2", "nouislider-react": "3.3.8", "postcss-rtl": "1.5.0", diff --git a/src/components/map/mapbox/MapBoxMap.js b/src/components/map/mapbox/MapBoxMap.js index 1bc3e417..8c7be2f7 100644 --- a/src/components/map/mapbox/MapBoxMap.js +++ b/src/components/map/mapbox/MapBoxMap.js @@ -96,7 +96,7 @@ export default function MapBoxMap({ handlerDrawObjInit }) { // 노탐 정보 모달 const [centeredModal, setCenteredModal] = useState(false); - const mouseCursorRef = useRef(null); + // 거리 측정 // 비행예상경로 geoJson 정보 const [planGeo, setPlanGeo] = useState({ @@ -572,72 +572,11 @@ export default function MapBoxMap({ handlerDrawObjInit }) { setMapLoaded(true); }); - map.on('click', e => { - console.log(drawObj.getMode()); - if (drawObj.getMode() === 'draw_line_string') { - startPoint = e.lngLat; - } - }); - - map.on('mousemove', e => { - let distance = 0; - if (startPoint) { - // console.log(drawObj.getAll()); - const feature = []; - drawObj - .getAll() - .features[0].geometry.coordinates.map(i => feature.push(i)); - const obj = { - geometry: { - coordinates: [...feature], - type: 'LineString' - }, - type: 'Feature' - }; - distance = turf.length(obj, { units: 'kilometers' }); - distance = distance * 1000; - distance = distance.toFixed(2); - mouseCursorRef.current.style.left = e.originalEvent.pageX + 'px'; - mouseCursorRef.current.style.top = e.originalEvent.pageY + 45 + 'px'; - mouseCursorRef.current.innerText = `${distance.toLocaleString()}m`; - // const endPoint = e.lngLat; - // const distance = calculateDistance(startPoint, endPoint); - // mouseCursorRef.current.innerText = `Distance from start point: ${distance.toFixed( - // 2 - // )} meters`; - if (drawObj.getMode() === 'simple_select') { - // startPoint = null; - const box = document.getElementById('distance_box'); - box.innerText = `${distance.toLocaleString()}m`; - box.style.display = 'block'; - mouseCursorRef.current.style.display = 'none'; - mouseCursorRef.current.style.innerText = ''; - } - if (drawObj.getMode() === 'direct_select') { - const box = document.getElementById('distance_box'); - box.innerText = `${distance.toLocaleString()}km`; - } - } else { - if (drawObj.getMode() === 'draw_line_string') { - mouseCursorRef.current.style.display = 'block'; - mouseCursorRef.current.style.left = e.originalEvent.pageX + 'px'; - mouseCursorRef.current.style.top = e.originalEvent.pageY + 45 + 'px'; - mouseCursorRef.current.innerText = '시작점 선택'; - } - } - }); - handlerDrawObjInit(drawObj); setMapObject(map); dispatch(clientMapInit(map)); }; - function calculateDistance(point1, point2) { - return mapboxgl.MercatorCoordinate.fromLngLat(point1).distanceTo( - mapboxgl.MercatorCoordinate.fromLngLat(point2) - ); - } - return ( <>
-
{isMapLoaded && mapObject ? ( <> diff --git a/src/containers/flight/OperationApprovalsContainer.js b/src/containers/flight/OperationApprovalsContainer.js index 34c0f641..3977898c 100644 --- a/src/containers/flight/OperationApprovalsContainer.js +++ b/src/containers/flight/OperationApprovalsContainer.js @@ -9,7 +9,8 @@ import { flightlayerPolyline, flightlayerPolygon, flightlayerBuffer, - handlerStartMode + handlerStartMode, + handlerOnClickDrawLineString } from '../../utility/MapUtils'; import { useHistory } from 'react-router-dom'; import useMapType from '@hooks/useMapType'; @@ -48,6 +49,7 @@ import { X } from 'react-feather'; import mapboxgl from 'mapbox-gl'; import * as turf from '@turf/turf'; +let distanceMarkers = []; export default function OperationApprovalsContainer({ mode }) { const dispatch = useDispatch(); const history = useHistory(); @@ -62,6 +64,7 @@ export default function OperationApprovalsContainer({ mode }) { // 비행구역 그리기 const [drawObj, setDrawObj] = useState(); const [filter, setFilter] = useState(''); + const mouseCursorRef = useRef(null); // 지도 const [mapObject, setMapObject] = useState(); @@ -133,6 +136,7 @@ export default function OperationApprovalsContainer({ mode }) { window._mapbox = map; let mapInstance = mode === 'container' ? map : window.opener._mapbox; setMapObject(mapInstance); + handlerOnClickDrawLineString(mapInstance, handlerDrawMarker); } }, [map]); @@ -462,11 +466,8 @@ export default function OperationApprovalsContainer({ mode }) { }; const handlerDrawTypeChange = (e, val) => { - // const cursor = document.getElementById('distance_cursor'); - // cursor.style.display = 'block'; - // cursor.style.left = e.clientX + 'px'; - // cursor.style.top = e.clientY + 45 + 'px'; - // cursor.innerText = '시작점 선택'; + drawObj.deleteAll(); + distanceMarkers.map(i => i.remove()); dispatch(clientChangeDrawType(val)); handlerStartMode(val, drawObj); }; @@ -480,6 +481,36 @@ export default function OperationApprovalsContainer({ mode }) { setMapType(val); }; + const handlerDistanceClose = () => { + drawObj.deleteAll(); + dispatch(clientChangeDrawType('')); + document.getElementById('distance_box').style.display = 'none'; + }; + + const handlerDrawMarker = (mapInstance, markerList, startPoint) => { + const marker = markerList.filter(i => { + return i.coord[0][0] === startPoint.lng; + }); + if (marker.length > 0) { + let distanceMarker = new mapboxgl.Popup({ + closeButton: false, + closeOnClick: false, + anchor: 'bottom', + focusAfterOpen: false + }) + .setLngLat([ + marker[0].coord[0][0].toFixed(6), + marker[0].coord[0][1].toFixed(6) + ]) + .setHTML( + `
${marker[0].text}
` + ) + .addTo(mapInstance); + + distanceMarkers.push(distanceMarker); + } + }; + const handlerLogout = async () => { const { payload } = await dispatch(setLogout()); @@ -493,6 +524,18 @@ export default function OperationApprovalsContainer({ mode }) { return ( <>
+
-
+

측정

-
+
@@ -799,7 +847,13 @@ export default function OperationApprovalsContainer({ mode }) {

지도에서 지점을 클릭하여 거리를 측정하세요. - 총 거리 : 1050.24m + + 총 거리 : 1050.24m +

diff --git a/src/utility/MapUtils.js b/src/utility/MapUtils.js index c1a28193..12cac922 100644 --- a/src/utility/MapUtils.js +++ b/src/utility/MapUtils.js @@ -1,6 +1,7 @@ import * as turf from '@turf/turf'; import mapboxgl from 'mapbox-gl'; import MapboxDraw from '@mapbox/mapbox-gl-draw'; +import * as MapboxDrawWaypoint from 'mapbox-gl-draw-waypoint'; import { CircleMode, DragCircleMode, @@ -477,8 +478,9 @@ export const flightlayerBuffer = source => { // 비행구역 상세맵 draw 정보 셋팅 export const getDraw = mode => { + let drawObj = null; if (mode === 'laanc') { - return new MapboxDraw({ + drawObj = new MapboxDraw({ displayControlsDefault: false, userProperties: true, boxSelect: false, @@ -568,16 +570,17 @@ export const getDraw = mode => { ] }); } else { - return new MapboxDraw({ + let modes = MapboxDraw.modes; + modes = MapboxDrawWaypoint.enable(modes); + + drawObj = new MapboxDraw({ displayControlsDefault: false, userProperties: true, boxSelect: false, modes: { - ...MapboxDraw.modes, + ...modes, draw_circle: CircleMode, - drag_circle: DragCircleMode, - direct_select: DirectMode, - simple_select: SimpleSelectMode + drag_circle: DragCircleMode }, styles: [ { @@ -643,6 +646,7 @@ export const getDraw = mode => { // vertex points id: 'gl-draw-polygon-and-line-vertex-active', type: 'circle', + filter: ['all', ['==', '$type', 'Point']], paint: { 'circle-radius': 6, 'circle-color': '#8a1c05' @@ -651,6 +655,8 @@ export const getDraw = mode => { ] }); } + + return drawObj; }; /** @@ -666,3 +672,86 @@ export const handlerStartMode = (mode, drawObj) => { drawObj.changeMode('draw_circle', { initialRadiusInKm: 100 / 1000 }); } }; + +export const handlerOnClickDrawLineString = (mapInstance, callback) => { + const originClickHandler = MapboxDraw.modes.draw_line_string.onClick; + const originMouseMoveHandler = MapboxDraw.modes.draw_line_string.onMouseMove; + let startPoint; + let markerList = []; + + MapboxDraw.modes.draw_line_string.onClick = function (state, e) { + originClickHandler.call(this, state, e); + startPoint = e.lngLat; + state.line.coordinates.map((i, idx) => { + if ( + i[0] !== state.line.coordinates[state.line.coordinates.length - 1][0] + ) { + const obj = { + geometry: { + coordinates: [i, state.line.coordinates[idx + 1]], + type: 'LineString' + }, + type: 'Feature' + }; + let distance = turf.length(obj, { units: 'kilometers' }); + distance = distance * 1000; + distance = distance.toFixed(2); + markerList.push({ + text: `${distance.toLocaleString()}m`, + coord: [state.line.coordinates[idx + 1]] + }); + } + }); + callback(mapInstance, markerList, startPoint); + }; + + MapboxDraw.modes.draw_line_string.onMouseMove = function (state, e) { + originMouseMoveHandler.call(this, state, e); + let distance = 0; + console.log; + if (startPoint) { + console.log(state); + + const drawGeometry = state.line.coordinates; + if (drawGeometry) { + const feature = []; + drawGeometry.map(i => feature.push(i)); + const obj = { + geometry: { + coordinates: [...feature], + type: 'LineString' + }, + type: 'Feature' + }; + distance = turf.length(obj, { units: 'kilometers' }); + distance = distance * 1000; + distance = distance.toFixed(2); + // mouseCursorRef.current.style.display = 'none'; + } + + // if (drawObj.getMode() === 'simple_select') { + // // startPoint = null; + // const totalDistance = document.getElementById('total_distance'); + // totalDistance.style.display = 'block'; + // totalDistance.innerText = `총 거리 : ${distance.toLocaleString()}m`; + // mouseCursorRef.current.style.display = 'none'; + // mouseCursorRef.current.style.innerText = ''; + // } + // if (drawObj.getMode() === 'direct_select') { + // distanceMarkers.map(i => i.remove()); + // distanceMarkers = []; + // const totalDistance = document.getElementById('total_distance'); + // totalDistance.innerText = `총 거리 : ${distance.toLocaleString()}m`; + // } + } + // else { + // if (drawObj.getMode() === 'draw_line_string') { + // document.getElementById('distance_box').style.display = 'block'; + // mouseCursorRef.current.style.display = 'block'; + // mouseCursorRef.current.style.left = e.originalEvent.pageX + 'px'; + // mouseCursorRef.current.style.top = e.originalEvent.pageY + 45 + 'px'; + // mouseCursorRef.current.innerText = '시작점 선택'; + // } + // } + }; +};