From 4168a3fd23317dbc9a42aebcfe443914479ab709 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?junh=5Feee=28=EC=9D=B4=EC=A4=80=ED=9D=AC=29?= Date: Tue, 24 Oct 2023 16:47:06 +0900 Subject: [PATCH] =?UTF-8?q?laanc=20=EB=B9=84=ED=96=89=EA=B5=AC=EC=97=AD=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=ED=96=88=EB=8D=98=20=EA=B5=AC=EC=97=AD=20?= =?UTF-8?q?=EC=82=AC=EB=9D=BC=EC=A7=80=EB=8A=94=20=ED=98=84=EC=83=81=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../map/mapbox/draw/LaancDrawControl.js | 200 ++++++++++-------- src/utility/DrawUtil.js | 36 +++- 2 files changed, 149 insertions(+), 87 deletions(-) diff --git a/src/components/map/mapbox/draw/LaancDrawControl.js b/src/components/map/mapbox/draw/LaancDrawControl.js index 6123e5a3..24d7a2d1 100644 --- a/src/components/map/mapbox/draw/LaancDrawControl.js +++ b/src/components/map/mapbox/draw/LaancDrawControl.js @@ -3,7 +3,8 @@ import { InfoModal } from '../../../modal/InfoModal'; import { useDispatch, useSelector } from 'react-redux'; import { CalculateDistance, - handlerGetHtmlContent, + handlerCreateGroupMarker, + handlerCreateOneMarker, handlerGetMidPoint, handlerRemoveAllMarker, handlerRemoveGroupMarker, @@ -12,7 +13,6 @@ import { import { drawTypeChangeAction } from '../../../../modules/control/map/actions/controlMapActions'; import MapboxDraw from '@mapbox/mapbox-gl-draw'; import { CircleMode } from 'mapbox-gl-draw-circle'; -import axios from '../../../../modules/utils/customAxiosUtil'; export const LaancDrawControl = props => { const dispatch = useDispatch(); @@ -96,9 +96,10 @@ export const LaancDrawControl = props => { const lngLat = handlerGetMidPoint(coords[len - 2], coords[len - 1]); const text = CalculateDistance(coords[len - 2], coords[len - 1]); - handlerCreateOneMarker([0, 0], lngLat, text, obj.id); + handlerCreateOneMarker(mapObject, [0, 0], lngLat, text, obj.id); } else { handlerCreateOneMarker( + mapObject, [0, -10], [e.lngLat.lng, e.lngLat.lat], 'Start', @@ -125,7 +126,13 @@ export const LaancDrawControl = props => { }; drawObj.setFeatureProperty(data.id, 'id', mode); - handlerCreateOneMarker([0, -10], data.coord, data.radius, data.id); + handlerCreateOneMarker( + mapObject, + [0, -10], + data.coord, + data.radius, + data.id + ); handlerAbnormalityCheck(data, mode); } else { const obj = state[mode.toLowerCase()]; @@ -204,7 +211,13 @@ export const LaancDrawControl = props => { id: obj.id }; handlerRemoveGroupMarker(obj.id); - handlerCreateOneMarker([0, -10], data.coord, data.radius, data.id); + handlerCreateOneMarker( + mapObject, + [0, -10], + data.coord, + data.radius, + data.id + ); handlerAbnormalityCheck(data, mode); } else { // 폴리곤은 중첩좌표 제거해서 서버에 넘겨야함 @@ -294,7 +307,6 @@ export const LaancDrawControl = props => { }; // areaInfo 셋팅 - // const handlerSaveAreaInfo = (coord, mode) => { const handlerSaveAreaInfo = data => { if (!data.coord || !data.mode) { alert('에러 발생. 다시 시도해 주세요.'); @@ -353,6 +365,7 @@ export const LaancDrawControl = props => { } }; + // 두 좌표배열이 완전히 일치하는지 판단 const handlerArraysAreEqual = (arr1, arr2) => { if (arr1 === arr2) return true; if (arr1.length !== arr2.length) return false; @@ -375,7 +388,7 @@ export const LaancDrawControl = props => { const areas = props.areaCoordList; if (areas.length > 0 && objs.length > 0) { // areas -> 현재는 1개이지만 추후에 데이터가 바뀌면 여러개의 도형도 처리 가능! - areas.forEach((area, idx) => { + areas.map((area, idx) => { const paths = []; area.coordList.forEach(coord => paths.push([coord.lon, coord.lat])); if (area.areaType) { @@ -411,16 +424,15 @@ export const LaancDrawControl = props => { const oldBuffer = objs.find( obj => obj.properties?.lineId === lineId ); - drawObj.delete(oldBuffer.id); + if (oldBuffer) drawObj.delete(oldBuffer?.id); // 새 버퍼 생성 - const newBuffer = { - type: 'LineString', - coordinates: bufferPaths - }; - const newBufferId = drawObj.add(newBuffer); - drawObj.setFeatureProperty(newBufferId[0], 'id', 'BUFFER'); - drawObj.setFeatureProperty(newBufferId[0], 'lineId', lineId); + const bufferId = handlerCreateDrawObj( + 'LineString', + bufferPaths, + 'BUFFER' + ); + drawObj.setFeatureProperty(bufferId, 'lineId', lineId); objId = lineId; } @@ -449,94 +461,117 @@ export const LaancDrawControl = props => { id: objId }; handlerRemoveGroupMarker(data.id); - handlerCreateGroupMarker(data, area.areaType); + handlerCreateGroupMarker(mapObject, data, area.areaType); } dispatch(drawTypeChangeAction('DONE')); } }); + } else if (areas.length > 0 && areas[0].areaType) { + // 이미 그려진 지도 다시 열었을 때 + areas.map(area => { + const paths = []; + area.coordList.forEach(coord => paths.push([coord.lon, coord.lat])); + if (area.areaType) { + console.log('ReDraw', area); + if (area.areaType === 'CIRCLE') { + const center = paths[0]; + const km = area.bufferZone / 1000; + const step = 64; + + const ret = []; + const disX = + km / (111.32 * Math.cos((center[1] * Math.PI) / 180)); + const disY = km / 110.574; + + for (let i = 0; i < step; i++) { + const theta = (i / step) * (2 * Math.PI); + const x = disX * Math.cos(theta); + const y = disY * Math.sin(theta); + + ret.push([center[0] + x, center[1] + y]); + } + ret.push(ret[0]); + + const circle = { + type: 'Feature', + geometry: { + type: 'Polygon', + coordinates: [ret] + }, + properties: { + id: 'CIRCLE', + isCircle: true, + radiusInKm: km, + center: center + } + }; + const newCircleId = drawObj.add(circle); + const data = { + coord: paths[0], + id: newCircleId[0], + bufferZone: km * 1000 + }; + handlerCreateGroupMarker(mapObject, data, area.areaType); + } else { + if (area.areaType === 'LINE') { + const lineId = handlerCreateDrawObj( + 'LineString', + paths, + 'LINE' + ); + // 버퍼 생성 + if (area.bufferCoordList) { + const bufferPaths = []; + + area.bufferCoordList.forEach(bfCoord => + bufferPaths.push([bfCoord.lon, bfCoord.lat]) + ); + + const bufferId = handlerCreateDrawObj( + 'LineString', + bufferPaths, + 'BUFFER' + ); + drawObj.setFeatureProperty(bufferId, 'lineId', lineId); + } + } else if (area.areaType === 'POLYGON') { + paths.push(paths[0]); + handlerCreateDrawObj('Polygon', [paths], 'POLYGON'); + } + } + } + }); + const viewCoordObj = drawObj + .getAll() + .features.filter(o => o.properties.id !== 'BUFFER'); + props.setViewCoordObj(viewCoordObj); } } }; - // 기존에 그려진 도형 지우고 새 도형 생성 - const handlerCreateDrawObj = (id, setter, type, data, propertyId) => { - const obj = drawObj.get(id); - if (obj) drawObj.delete(id); - + // 도형 생성 + 마커 생성(circle만 사용안함) + const handlerCreateDrawObj = (type, paths, propertyId) => { const newObj = { type: type, - coordinates: data.path + coordinates: paths }; - const newObjId = drawObj.add(newObj); - if (propertyId === 'CIRCLE') { - drawObj.setFeatureProperty(newObjId[0], 'isCircle', true); - drawObj.setFeatureProperty(newObjId[0], 'center', data.center); - drawObj.setFeatureProperty(newObjId[0], 'radiusInKm', data.radius / 1000); - } drawObj.setFeatureProperty(newObjId[0], 'id', propertyId); - setter(newObjId[0]); - if (propertyId !== 'BUFFER') { - drawObj.changeMode('direct_select', { - featureId: newObjId[0] - }); - } - }; - - // // 지도에 있는 모든 마커 삭제 - // const handlerRemoveAllMarker = () => { - // const ele = document.getElementsByClassName('mapboxgl-popup'); - // const eleArr = Array.from(ele); - // eleArr?.forEach(marker => marker.remove()); - // }; - - // // 해당되는 id의 마커 삭제 - // const handlerRemoveGroupMarker = id => { - // const ele = document.getElementsByClassName('mapboxgl-popup'); - // const eleArr = Array.from(ele); - // eleArr?.forEach(marker => { - // if (marker.innerHTML.includes(id)) marker.remove(); - // }); - // }; - - // 개별 마커 생성 - const handlerCreateOneMarker = (anchor, lngLat, text, id) => { - const popup = new props.mapboxgl.Popup({ - offset: anchor, - closeButton: false, - closeOnClick: false - }) - .setLngLat(lngLat) - .setHTML(handlerGetHtmlContent(text, id)) - .addTo(mapObject); - }; + const data = { + coord: paths, + id: newObjId[0] + }; - // 해당되는 id의 마커 생성 - const handlerCreateGroupMarker = (data, mode) => { - const areas = props.areaCoordList[0]; + if (propertyId !== 'BUFFER') + handlerCreateGroupMarker(mapObject, data, propertyId); - if (mode !== 'CIRCLE') { - const coord = mode === 'LINE' ? data.coord : data.coord[0]; - for (let i = 0; i < coord.length; i++) { - const coords = coord; - if (i === 0) { - handlerCreateOneMarker([0, -10], coords[i], 'Start', data.id); - } else { - const lngLat = handlerGetMidPoint(coords[i - 1], coords[i]); - const text = CalculateDistance(coords[i - 1], coords[i]); - handlerCreateOneMarker([0, 0], lngLat, text, data.id); - } - } - } else { - handlerCreateOneMarker([0, -10], coords[0], areas.bufferZone, data.id); - } + return newObjId[0]; }; const drawInit = () => { const mode = mapControl.drawType; if (mode !== 'DONE') { - // console.log(mode, 'mode----'); if (!props.addData.isAddable) { // 추가 상태가 아닐 때 drawObj.deleteAll(); @@ -546,7 +581,6 @@ export const LaancDrawControl = props => { props.handlerSaveCheck(false); props.handlerInitCoordinates(); - // setDrawObjId(); } if (!mode || mode === 'RESET') { diff --git a/src/utility/DrawUtil.js b/src/utility/DrawUtil.js index a91beedf..dc957271 100644 --- a/src/utility/DrawUtil.js +++ b/src/utility/DrawUtil.js @@ -17,7 +17,6 @@ export const InitFeature = (type, id) => { export const FormattingCoord = coord => { const resultArr = []; - // console.log(coord, '>>>>>>>>coord'); if (!Array.isArray(coord)) return; coord?.forEach(co => { @@ -31,8 +30,6 @@ export const FormattingCoord = coord => { }; // 거리 계산(meters로 리턴) -// 사용 1. 원의 센터로부터 e.coord까지 -// 사용 2. distance 마커 export const CalculateDistance = (mouse, center) => { const centerCoord = turf.point(center); const mouseCoord = turf.point(mouse); @@ -76,7 +73,7 @@ export const fromMetersToText = meters => { // circle 360도 좌표 반환 export const handlerGetCircleCoord = (center, distance) => { const options = { - steps: 360, + steps: 63, units: 'kilometers' }; return turf.circle(center, distance / 1000, options).geometry.coordinates; @@ -137,6 +134,37 @@ export const handlerRemoveGroupMarker = id => { }); }; +// 개별 마커 생성 +export const handlerCreateOneMarker = (map, anchor, lngLat, text, id) => { + const popup = new mapboxgl.Popup({ + offset: anchor, + closeButton: false, + closeOnClick: false + }) + .setLngLat(lngLat) + .setHTML(handlerGetHtmlContent(text, id)) + .addTo(map); +}; + +// 해당되는 id의 마커 생성 +export const handlerCreateGroupMarker = (map, data, mode) => { + if (mode !== 'CIRCLE') { + const coord = mode === 'LINE' ? data.coord : data.coord[0]; + for (let i = 0; i < coord.length; i++) { + const coords = coord; + if (i === 0) { + handlerCreateOneMarker(map, [0, -10], coords[i], 'Start', data.id); + } else { + const lngLat = handlerGetMidPoint(coords[i - 1], coords[i]); + const text = CalculateDistance(coords[i - 1], coords[i]); + handlerCreateOneMarker(map, [0, 0], lngLat, text, data.id); + } + } + } else { + handlerCreateOneMarker(map, [0, -10], data.coord, data.bufferZone, data.id); + } +}; + // draw 레이어 export const layerWayPoint = source => { return {