diff --git a/src/components/map/mapbox/MapBoxMap.js b/src/components/map/mapbox/MapBoxMap.js index 8c7be2f7..51571287 100644 --- a/src/components/map/mapbox/MapBoxMap.js +++ b/src/components/map/mapbox/MapBoxMap.js @@ -95,7 +95,7 @@ export default function MapBoxMap({ handlerDrawObjInit }) { // 노탐 정보 모달 const [centeredModal, setCenteredModal] = useState(false); - + let popup; // 거리 측정 // 비행예상경로 geoJson 정보 @@ -419,7 +419,6 @@ export default function MapBoxMap({ handlerDrawObjInit }) { type: 'custom', renderingMode: '3d', onAdd: function () { - console.log(mapState.mapType); for (let i = 0; i < gimPo.features.length; i++) { let line; const options = { @@ -572,11 +571,65 @@ export default function MapBoxMap({ handlerDrawObjInit }) { setMapLoaded(true); }); - handlerDrawObjInit(drawObj); + map.on('click', 'maine', e => { + let isMaine = false; + let isOperation = false; + + map.queryRenderedFeatures(e.point).map(feature => { + if (feature.source === 'operationLayer') isOperation = true; + if (feature.source === 'maine') isMaine = true; + }); + + if (isMaine && !isOperation) { + map.getCanvas().style.cursor = 'pointer'; + + const feature = e.features[0]; + const data = feature.properties; + data.coord = e.lngLat; + data.title = feature.properties.name; + + infowindowOpen(data, map); + } + }); + + handlerDrawObjInit(drawObj, map); setMapObject(map); dispatch(clientMapInit(map)); }; + const infowindowOpen = (data, map) => { + const content = + '
' + + '
' + + '' + + data.title + + '' + + '
' + + // '
' + + // '
' + + // '' + + // data.description + + // '' + + // '
' + + // '
' + + '
'; + + if (popup) { + popup.remove(); + } + + // Create a popup element + popup = new mapboxgl.Popup({ + offset: [0, 0], + closeButton: false, + closeOnClick: true, + closeOnMove: false + }) + .setLngLat(data.coord) + .setHTML(content) + .addTo(map); + }; + return ( <>
{ - let isMaine = false; - let isOperation = false; + // props.map.on('click', 'maine', e => { + // let isMaine = false; + // let isOperation = false; - props.map.queryRenderedFeatures(e.point).map(feature => { - if (feature.source === 'operationLayer') isOperation = true; - if (feature.source === 'maine') isMaine = true; - }); + // props.map.queryRenderedFeatures(e.point).map(feature => { + // if (feature.source === 'operationLayer') isOperation = true; + // if (feature.source === 'maine') isMaine = true; + // }); - if (isMaine && !isOperation) { - props.map.getCanvas().style.cursor = 'pointer'; + // if (isMaine && !isOperation) { + // props.map.getCanvas().style.cursor = 'pointer'; - const feature = e.features[0]; - const data = feature.properties; - data.coord = e.lngLat; - data.title = feature.properties.name; + // const feature = e.features[0]; + // const data = feature.properties; + // data.coord = e.lngLat; + // data.title = feature.properties.name; - infowindowOpen(data); - } - }); + // infowindowOpen(data); + // } + // }); // props.map.on('mouseover', 'maine', e => { // props.map.getCanvas().style.cursor = 'pointer'; @@ -133,27 +133,27 @@ export default function FeatureAirZone(props) { // } // }); - const buildingsLayer = props.map.getLayer('add-3d-buildings'); - if (buildingsLayer) { - props.map.on('click', e => { - // 클릭한 지점의 피처들을 얻어옵니다. - const features = props.map.queryRenderedFeatures(e.point, { - layers: ['add-3d-buildings'] // 빌딩 레이어의 ID를 지정합니다. - }); - - // 빌딩 피처가 있는 경우 - if (features.length > 0) { - // 첫 번째 빌딩 피처의 높이 값을 얻어옵니다. - const height = features[0].properties.height; - - // 팝업을 생성하고 지도에 추가합니다. - new props.mapboxgl.Popup() - .setLngLat(e.lngLat) - .setHTML(`Building height: ${height}m`) - .addTo(props.map); - } - }); - } + // const buildingsLayer = props.map.getLayer('add-3d-buildings'); + // if (buildingsLayer) { + // props.map.on('click', e => { + // // 클릭한 지점의 피처들을 얻어옵니다. + // const features = props.map.queryRenderedFeatures(e.point, { + // layers: ['add-3d-buildings'] // 빌딩 레이어의 ID를 지정합니다. + // }); + + // // 빌딩 피처가 있는 경우 + // if (features.length > 0) { + // // 첫 번째 빌딩 피처의 높이 값을 얻어옵니다. + // const height = features[0].properties.height; + + // // 팝업을 생성하고 지도에 추가합니다. + // new props.mapboxgl.Popup() + // .setLngLat(e.lngLat) + // .setHTML(`Building height: ${height}m`) + // .addTo(props.map); + // } + // }); + // } }; // 이착륙장 마커 이벤트 로직 diff --git a/src/containers/flight/OperationApprovalsContainer.js b/src/containers/flight/OperationApprovalsContainer.js index 99cda963..b00b8f3b 100644 --- a/src/containers/flight/OperationApprovalsContainer.js +++ b/src/containers/flight/OperationApprovalsContainer.js @@ -62,7 +62,6 @@ export default function OperationApprovalsContainer({ mode }) { // 비행구역 그리기 const [drawObj, setDrawObj] = useState(); const [filter, setFilter] = useState(''); - const mouseCursorRef = useRef(null); // 지도 const [mapObject, setMapObject] = useState(); @@ -95,6 +94,12 @@ export default function OperationApprovalsContainer({ mode }) { // 비행구역 데이터블록 const [dataBlocks, setDataBlocks] = useState([]); + // 거리측정 + const [isDistanceStartPoint, setIsDistanceStartPoint] = useState(false); + const totalDistanceRef = useRef(null); + const mouseCursorRef = useRef(null); + const distanceBoxRef = useRef(null); + // 비행구역 (운항과) 레이어 const operationLayer = { type: 'FeatureCollection', @@ -135,7 +140,6 @@ export default function OperationApprovalsContainer({ mode }) { window._mapbox = map; let mapInstance = mode === 'container' ? map : window.opener._mapbox; setMapObject(mapInstance); - handlerOnClickDrawLineString(mapInstance, handlerDrawMarker); } }, [map]); @@ -461,46 +465,78 @@ export default function OperationApprovalsContainer({ mode }) { const handlerDrawTypeChange = (e, val) => { drawObj.deleteAll(); distanceMarkers.map(i => i.remove()); + distanceBoxRef.current.style.display = 'block'; dispatch(clientChangeDrawType(val)); handlerStartMode(val, drawObj); }; - const handlerDrawObjInit = obj => { + const handlerDrawObjInit = (obj, mapInstance) => { setDrawObj(obj); + handlerOnClickDrawLineString( + mapInstance, + handlerDrawPopup, + { + totalDistanceRef, + mouseCursorRef, + distanceBoxRef + }, + obj + ); }; const handlerMapTypeChange = val => { - dispatch(clientChangeDrawType('')); + // dispatch(clientChangeDrawType('')); + drawObj.changeMode('simple_select'); setMapType(val); }; const handlerDistanceClose = () => { drawObj.deleteAll(); - dispatch(clientChangeDrawType('')); - document.getElementById('distance_box').style.display = 'none'; + dispatch(clientChangeDrawType('simple_select')); + drawObj.changeMode('simple_select'); + mouseCursorRef.current.style.display = 'none'; + distanceBoxRef.current.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 handlerDistanceRevert = () => { + if (drawObj.getMode() === 'draw_line_string') { + const allFeatures = drawObj.getAll(); + + if (allFeatures.features.length > 0) { + allFeatures.features[0].geometry.coordinates.pop(); // 마지막 좌표 제거 + allFeatures.features[0].geometry.coordinates.pop(); + allFeatures.features[0].geometry.coordinates.push( + allFeatures.features[0].geometry.coordinates[ + allFeatures.features[0].geometry.coordinates.length - 1 + ] + ); + + drawObj.set(allFeatures); + } + } + }; + + const handlerDrawPopup = (mapInstance, popupList) => { + // setIsDistanceStartPoint(true); + if (distanceMarkers.length > 0) { + distanceMarkers.map(i => i.remove()); + } + if (popupList.length > 0) { + popupList.map(i => { + let distanceMarker = new mapboxgl.Popup({ + closeButton: false, + closeOnClick: false, + anchor: 'bottom', + focusAfterOpen: false + }) + .setLngLat([i.coord[0][0].toFixed(6), i.coord[0][1].toFixed(6)]) + .setHTML( + `
${i.text}
` + ) + .addTo(mapInstance); + + distanceMarkers.push(distanceMarker); + }); } }; @@ -517,18 +553,6 @@ export default function OperationApprovalsContainer({ mode }) { return ( <>
-
@@ -822,8 +846,9 @@ export default function OperationApprovalsContainer({ mode }) {
)} +
); } diff --git a/src/utility/MapUtils.js b/src/utility/MapUtils.js index 12cac922..9678df7a 100644 --- a/src/utility/MapUtils.js +++ b/src/utility/MapUtils.js @@ -578,9 +578,7 @@ export const getDraw = mode => { userProperties: true, boxSelect: false, modes: { - ...modes, - draw_circle: CircleMode, - drag_circle: DragCircleMode + ...modes }, styles: [ { @@ -673,22 +671,106 @@ export const handlerStartMode = (mode, drawObj) => { } }; -export const handlerOnClickDrawLineString = (mapInstance, callback) => { - const originClickHandler = MapboxDraw.modes.draw_line_string.onClick; - const originMouseMoveHandler = MapboxDraw.modes.draw_line_string.onMouseMove; +export const handlerOnClickDrawLineString = ( + mapInstance, + callback, + refObj, + drawObj +) => { + const originLineClickHandler = MapboxDraw.modes.draw_line_string.onClick; + const { totalDistanceRef, mouseCursorRef, distanceBoxRef } = refObj; + let startPoint; let markerList = []; + let distance = 0; MapboxDraw.modes.draw_line_string.onClick = function (state, e) { - originClickHandler.call(this, state, e); + originLineClickHandler.call(this, state, e); startPoint = e.lngLat; - state.line.coordinates.map((i, idx) => { + + const markerList = getDintancePointPopupList(drawObj); + callback(mapInstance, markerList); + }; + + mapInstance.on('mousemove', e => { + if (startPoint) { + mouseCursorRef.current.style.display = 'none'; + if (drawObj.getMode() === 'direct_select') { + // distanceMarkers.map(i => i.remove()); + + const distance = getDrawDistance(drawObj); + totalDistanceRef.current.innerText = `총 거리 : ${distance.toLocaleString()}m`; + } + } else { + if (drawObj.getMode() === 'draw_line_string') { + console.log('@@@@'); + 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 = '시작점 선택'; + } + } + }); + + mapInstance.on('draw.modechange', obj => { + if (obj.mode === 'simple_select') { + totalDistanceRef.current.style.display = 'block'; + const distance = getDrawDistance(drawObj); + totalDistanceRef.current.innerText = `총 거리 : ${distance.toLocaleString()}m`; + mouseCursorRef.current.style.display = 'none'; + mouseCursorRef.current.style.innerText = ''; + const markerList = getDintancePointPopupList(drawObj); + callback(mapInstance, markerList); + } else if (obj.mode === 'direct_select') { + } + }); +}; + +/** + * + * @param {MapboxDraw} drawObj + * @returns 총 거리 : number + */ +export const getDrawDistance = drawObj => { + const drawGeometry = drawObj.getAll().features[0]; + let distance = 0; + if (drawGeometry) { + const feature = []; + drawGeometry.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); + } + return distance; +}; + +/** + * + * @param {MapboxDraw} drawObj + * @returns Draw 각 포인트 거리 팝업 리스트 + */ +export const getDintancePointPopupList = drawObj => { + const drawGeometry = drawObj.getAll().features[0]; + console.log(drawObj.getAll().features[0]); + let markerList = []; + if (drawGeometry?.geometry) { + drawGeometry.geometry.coordinates.map((i, idx) => { if ( - i[0] !== state.line.coordinates[state.line.coordinates.length - 1][0] + i[0] !== + drawGeometry.geometry.coordinates[ + drawGeometry.geometry.coordinates.length - 1 + ][0] ) { const obj = { geometry: { - coordinates: [i, state.line.coordinates[idx + 1]], + coordinates: [i, drawGeometry.geometry.coordinates[idx + 1]], type: 'LineString' }, type: 'Feature' @@ -698,60 +780,11 @@ export const handlerOnClickDrawLineString = (mapInstance, callback) => { distance = distance.toFixed(2); markerList.push({ text: `${distance.toLocaleString()}m`, - coord: [state.line.coordinates[idx + 1]] + coord: [drawGeometry.geometry.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 = '시작점 선택'; - // } - // } - }; + return markerList; };