Browse Source

naverMap draw파일 삭제

pull/2/head
junh_eee(이준희) 10 months ago
parent
commit
9828de120f
  1. 671
      src/components/map/mapbox/draw/LaancDraw.js
  2. 574
      src/components/map/mapbox/draw/LaancDrawRe.js
  3. 683
      src/components/map/mapbox/draw/MapBoxDraw.js
  4. 201
      src/components/map/naver/draw/ControlDraw.js
  5. 918
      src/components/map/naver/draw/FlightPlanDraw.js
  6. 683
      src/components/map/naver/draw/FlightPlanDraw_JQuery.js
  7. 971
      src/components/map/naver/draw/FlightPlanDraw_Test.js
  8. 519
      src/components/map/naver/sensor/SensorZone.js

671
src/components/map/mapbox/draw/LaancDraw.js

@ -1,671 +0,0 @@
import { useSelector } from 'react-redux';
import { InfoModal } from '../../../modal/InfoModal';
import { useCallback, useEffect, useMemo, useState } from 'react';
import {
CalculateDistance,
FormattingCoord,
InitFeature,
handlerCreatePoint,
handlerGetCircleCoord,
handlerGetHtmlContent,
handlerGetMidPoint
} from '../../../../utility/DrawUtil';
export const LaancDraw = props => {
const mapControl = useSelector(state => state.controlMapReducer);
const mapObject = props.mapObject;
const canvas = mapObject.getCanvasContainer();
//비행계획서 작성 완료 후에는 수정 불가일거라서 이거는 임시 보류
// const isDone = props.isDone;
// const isDisabled = props.isDisabled;
const [clickEve, setClickEve] = useState();
const [mouseMoveEve, setMouseMoveEve] = useState(false);
const [alertModal, setAlertModal] = useState({
isOpen: false,
title: '',
desc: ''
});
//도형들이 온전히 그려진 후 변경 될 때 마다 감지
const [isDrawDone, setIsDrawDone] = useState(false);
const [mouseDownEve, setMouseDownEve] = useState(false);
const geojson = props.geojson;
const [geoState, setGeoState] = useState(geojson);
const detailLayer = props.detailLayer;
const [clickNum, setClickNum] = useState(0);
let mode = props.mode;
let guideLine = InitFeature('LineString', 'guideline');
let lineString = InitFeature('LineString', 'polyline');
let bufferPolyline = InitFeature('LineString', 'buffer');
let polygon = InitFeature('Polygon', 'polygon');
let circle = InitFeature('Polygon', 'circle');
let point = [];
let dragCircleIdx;
useEffect(() => {
const areaType = props.areaCoordList[0].areaType;
const drawType = mapControl.drawType;
if (areaType !== drawType && detailLayer) {
console.log('drawInit');
geojson.features = geoState.features;
drawInit();
}
}, [mapControl.drawType, detailLayer]);
useEffect(() => {
const area = props.areaCoordList[0];
//자세히보기 두번째에는 area가 사라져..! 왜?!
//첫번째 열면 도형 그려진 다음에 areaCoordList가 사라짐 왜????
//clearMode가 자동으로 실행돼서 props.handlerInitCoordinates도 실행되기 때문 ㅠㅠ 그래서 초기화 됨
//해결완료. 나중에 꼬일 때 까먹지 말라고 주석 삭제 안함
if (area.areaType && area.areaType !== '') {
if (detailLayer) handlerPastDraw();
}
}, [props.areaCoordList, detailLayer]);
useEffect(() => {
if (isDrawDone) {
props.handlerConfirm(props.areaCoordList);
setIsDrawDone(false);
}
}, [isDrawDone]);
useEffect(() => {
if (clickEve) {
console.log('click>>>>>>>>>>>>>>>>>>>>>>>>>');
}
}, [clickEve]);
const drawInit = () => {
handlerButtonClick(mapControl.drawType);
};
//그리기 타입 선택
const handlerButtonClick = newMode => {
handlerClearMode(mode);
if (mode === newMode) {
mode = null;
return;
}
handlerStartMode(newMode);
};
const handlerClearMode = () => {
console.log('clearMode');
removeListener();
removeGeoJson();
props.handlerInitCoordinates();
};
const handlerStartMode = mode => {
if (!mode || mode === 'RESET') return;
// mapObject.off('click', onClickFeature);
console.log('startMode');
// mapObject.on('click', clickEve);
const drawType = mapControl.drawType;
if (drawType === 'LINE') mapObject.on('click', onClickFeature);
if (drawType === 'POLYGON') mapObject.on('click', onClickFeature);
if (drawType === 'RESET') mapObject.off('click', onClickFeature);
// setClickEve(onClickFeature);
};
const removeListener = () => {
console.log('removeListener');
// mapObject.off('click', clickEve);
mapObject.off('click', onClickFeature);
mapObject.off('click', onClickCircle);
mapObject.off('mouseup', onMouseUp);
mapObject.off('mousedown', 'waypoint', onMouseDown);
mapObject.off('mousedown', 'polygon', onMouseDown);
mapObject.off('mousemove', onMouseMove);
mapObject.off('mousemove', onMouseMovePolyline);
mapObject.off('mousemove', onMouseMovePolygon);
mapObject.off('contextmenu', onRightClick);
console.log(mapObject._listeners.click, '>>>>>');
// mapObject.off('click', clickEve);
// console.log(mapObject._listeners.click, '>>>>>');
// 이거 있나 없나 뭔 차이지?
setMouseDownEve(false);
setClickNum(0);
};
const removeGeoJson = () => {
console.log('removeGeoJson');
handlerRemoveMarker();
guideLine.geometry.coordinates = [];
lineString.geometry.coordinates = [];
bufferPolyline.geometry.coordinates = [];
polygon.geometry.coordinates = [];
circle.geometry.coordinates = [];
point = [];
geojson.features = [];
setGeoState(geojson);
handlerGetSourceSetData();
};
const onRightClick = () => {
console.log('rightClick');
removeListener();
const drawType = mapControl.drawType;
const path = handlerGetGeoJsonCoord('point');
console.log(mode, drawType);
if (path.length > 0) {
if (drawType === 'LINE') {
if (path.length > 1) {
handlerReplaceDuplicate('guideline', '');
handlerSaveAreaInfo(lineString.geometry.coordinates);
} else {
setAlertModal({
isOpen: true,
title: '좌표 최소 개수',
desc: '좌표를 두 개 점으로 이어주세요.'
});
removeGeoJson();
props.handlerDrawType('RESET');
}
handlerGetSourceSetData();
} else if (drawType === 'POLYGON') {
if (path.length > 2) {
polygon.geometry.coordinates[0] = path;
handlerReplaceDuplicate('polygon', polygon);
handlerSaveAreaInfo(polygon.geometry.coordinates[0]);
} else {
setAlertModal({
isOpen: true,
title: '좌표 최소 개수',
desc: '좌표를 세 개 점으로 이어주세요.'
});
removeGeoJson();
props.handlerDrawType('RESET');
}
}
handlerGetSourceSetData();
}
};
// const clickEve = e => {
// const drawType = mapControl.drawType;
// if (drawType === 'LINE') onClickFeature(e, lineString);
// if (drawType === 'POLYGON') onClickFeature(e, polygon);
// if (drawType === 'CIRCLE') onClickCircle(e);
// };
// polyline, polygon 생성
const onClickFeature = e => {
console.log('click');
const formatCoord = FormattingCoord([e.lngLat.lng, e.lngLat.lat]);
const obj = mapControl.drawType === 'LINE' ? lineString : polygon;
//현재 내 좌표가 waypoint레이어의 geojson도형 안에 속해있는지 안해있는지?
//geojson을 반환해주는 듯?
const features = mapObject.queryRenderedFeatures(e.point, {
layers: ['waypoint']
});
const id = obj.properties.id;
if (geojson.features.length > 1) {
handlerReplaceDuplicate(id, '');
}
if (features.length) {
const featuresId = features[0].properties.id;
handlerReplaceDuplicate(featuresId, '');
} else {
const index = geojson.features.filter(
geo => geo.properties?.id === 'point'
).length;
const wayPoint = handlerCreatePoint(
formatCoord,
index,
mapControl.drawType
);
point.push(wayPoint);
handlerReplaceDuplicate('Point', wayPoint);
}
guideLine.geometry.coordinates = [formatCoord];
if (geojson.features.length > 1) {
//나머지 좌표
const coordinates = handlerGetGeoJsonCoord('point');
obj.geometry.coordinates =
id === 'polyline' ? coordinates : [coordinates];
geojson.features.push(obj);
addMileStone(coordinates, '');
} else {
//첫 좌표
mapObject.on('contextmenu', onRightClick);
mapObject.on(
'mousemove',
id === 'polyline' ? onMouseMovePolyline : onMouseMovePolygon
);
addMileStone(formatCoord, '');
}
handlerGetSourceSetData();
};
// polyline 가이드 생성
const onMouseMovePolyline = e => {
const formatCoord = FormattingCoord([e.lngLat.lng, e.lngLat.lat]);
if (guideLine.geometry.coordinates.length > 1) {
guideLine.geometry.coordinates.pop();
handlerReplaceDuplicate('guideline', guideLine);
}
guideLine.geometry.coordinates.push(formatCoord);
handlerGetSourceSetData();
};
// polygon 가이드 생성
const onMouseMovePolygon = useCallback(
e => {
const formatCoord = FormattingCoord([e.lngLat.lng, e.lngLat.lat]);
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();
}
guideLine.geometry.coordinates.push(formatCoord);
polygon.geometry.coordinates[0].push(formatCoord);
}
}
// 이거.. 왜 안해도 잘 되지....?
// handlerReplaceDuplicate('polygon', polygon);
handlerGetSourceSetData();
},
[geoState]
);
// circle 생성
const onClickCircle = e => {
console.log('circleClick');
const formatCoord = FormattingCoord([e.lngLat.lng, e.lngLat.lat]);
if (circle.geometry.coordinates.length === 0) {
mapObject.on('mousedown', 'polygon', onMouseDown);
}
const circleCoords = handlerGetCircleCoord(formatCoord, 100);
circle.properties.center = formatCoord;
circle.geometry.coordinates = circleCoords;
handlerReplaceDuplicate('circle', circle);
handlerSaveAreaInfo('');
addMileStone(formatCoord, 100);
handlerGetSourceSetData();
};
const onMouseDown = useCallback(
e => {
e.preventDefault();
console.log('down');
//타입 교체만 하면 왜 처음엔 down이 두번 잡힐까...
// console.log(e.features[0].properties.type, '>>down e');
canvas.style.cursor = 'grab';
if (circle.geometry.coordinates.length > 0) {
removeListener();
mapObject.on('mousedown', 'polygon', onMouseDown);
} else {
dragCircleIdx = e.features[0].properties.index;
}
mapObject.on('mousemove', onMouseMove);
setMouseDownEve(true);
mapObject.on('mouseup', onMouseUp);
// 이거 왜 필요했던 거지?
// mapObject.off('click', clickEve);
mapObject.off('click', onClickFeature);
},
[mapControl.drawType]
);
const onMouseMove = e => {
const formatCoord = FormattingCoord([e.lngLat.lng, e.lngLat.lat]);
canvas.style.cursor = 'grabbing';
if (circle.geometry.coordinates.length > 0) {
const distance = CalculateDistance(formatCoord, circle.properties.center);
const center = circle.properties.center;
const circleCoords = handlerGetCircleCoord(center, distance);
circle.geometry.coordinates = circleCoords;
} else {
geojson.features = geojson.features.map(geo => {
const coord = formatCoord;
if (geo.properties?.index === dragCircleIdx) {
geo.geometry.coordinates = coord;
}
if (geo.properties?.id === 'polyline') {
geo.geometry.coordinates[dragCircleIdx] = coord;
lineString = geo;
}
if (geo.properties?.id === 'buffer') {
geo.geometry.coordinates = [];
}
if (geo.properties?.id === 'polygon') {
geo.geometry.coordinates[0][dragCircleIdx] = coord;
polygon = geo;
}
return geo;
});
}
handlerGetSourceSetData();
};
useEffect(() => {
console.log('-------------');
}, [onMouseMovePolyline]);
const onMouseUp = () => {
canvas.style.cursor = '';
console.log('up');
mapObject.off('mousedown', 'waypoint', onMouseDown);
mapObject.off('mousemove', onMouseMove);
mapObject.off('mouseup', onMouseUp);
// 이거 왜 필요했던 거지?
// mapObject.off('click', clickEve);
mapObject.off('click', onClickFeature);
setMouseDownEve(false);
const type = mapControl.drawType;
const obj =
type === 'LINE'
? lineString
: type === 'POLYGON'
? polygon
: type === 'CIRCLE'
? circle
: undefined;
if (obj) {
const id = obj.properties?.id;
const coord =
id === 'polyline'
? obj.geometry.coordinates
: obj.geometry.coordinates[0];
if (id === 'circle') {
// mapObject.on('click', clickEve);
mapObject.on('click', onClickFeature);
handlerSaveAreaInfo('');
} else {
// mapObject.on('mousedown', 'waypoint', onMouseDown);
handlerSaveAreaInfo(coord);
}
} else {
// 저장된 좌표 불러왔을 때
const areas = props.areaCoordList[0];
const type = areas.areaType;
const paths = [];
areas.coordList.forEach(coord => paths.push([coord.lon, coord.lat]));
if (type === 'LINE') {
handlerSaveAreaInfo(lineString.geometry.coordinates);
} else if (type === 'POLYGON') {
handlerSaveAreaInfo(polygon.geometry.coordinates[0]);
} else if (type === 'CIRCLE') {
handlerSaveAreaInfo('');
}
}
};
// 도형 정보 변경되면 저장
const handlerSaveAreaInfo = coord => {
console.log('areaInfo');
const areaInfo = {
coordinates: [],
bufferZone: 0,
areaType: ''
};
const bufferZone = polygon.geometry.coordinates.length > 0 ? 0 : 100;
const prePath = [];
if (lineString.geometry.coordinates.length > 0) {
areaInfo.areaType = 'LINE';
} else if (polygon.geometry.coordinates.length > 0) {
areaInfo.areaType = 'POLYGON';
} else if (circle.geometry.coordinates.length > 0) {
areaInfo.areaType = 'CIRCLE';
}
if (areaInfo.areaType !== 'CIRCLE') {
coord.forEach(item => {
const p = {
lat: item[1],
lon: item[0]
};
prePath.push(p);
});
}
areaInfo.coordinates = prePath;
areaInfo.bufferZone = bufferZone;
if (areaInfo.areaType === 'CIRCLE') {
const point = {
lat: circle.properties.center[1],
lon: circle.properties.center[0]
};
areaInfo.coordinates = [point];
areaInfo.bufferZone = CalculateDistance(
circle.geometry.coordinates[0][0],
circle.properties.center
);
}
props.handlerCoordinates(areaInfo);
setIsDrawDone(true);
};
// 확정된 도형 재 생성(let이라서 지워지기 때문에)
const handlerPastDraw = () => {
if (props.areaCoordList) {
console.log('pastDraw');
const areas = props.areaCoordList[0];
const paths = [];
areas.coordList.forEach(coord => paths.push([coord.lon, coord.lat]));
if (areas.areaType) {
if (areas.areaType === 'CIRCLE') {
const radius = areas.bufferZone;
const circleCoords = handlerGetCircleCoord(paths[0], radius);
circle.properties.center = paths[0];
circle.geometry.coordinates = circleCoords;
geojson.features.push(circle);
} else {
if (areas.areaType === 'LINE') {
lineString.geometry.coordinates = paths;
geojson.features.push(lineString);
// 버퍼 생성
if (areas.bufferCoordList) {
const bufferPaths = [];
areas.bufferCoordList.forEach(bfCoord =>
bufferPaths.push([bfCoord.lon, bfCoord.lat])
);
bufferPolyline.geometry.coordinates = bufferPaths;
handlerReplaceDuplicate('buffer', bufferPolyline);
}
} else if (areas.areaType === 'POLYGON') {
polygon.geometry.coordinates = [paths];
geojson.features.push(polygon);
}
// 포인트 생성
paths.forEach((p, i) => {
const wayPoint = handlerCreatePoint(p, i, areas.areaType);
point.push(wayPoint);
});
handlerReplaceDuplicate('point', '');
point.forEach(p => geojson.features.push(p));
//once로 하면 꼬이는건 해결되는데 지도를 움직이면 이벤트가 사라짐 -> 왜? onMouseDown이 실행된게 아니잖아?
//on으로 하면 그 반대 현상 -> 이벤트 다 지워줬는데 왜 down이 두번 잡혀??????
//얘만 해결하면 끝인데...
if (!mouseDownEve) {
console.log('여기가 이벤트 등록입니다.');
mapObject.on('mousedown', 'waypoint', onMouseDown);
setMouseDownEve(true);
}
// mapObject.once('mousedown', 'waypoint', onMouseDown);
}
// 기존 마커 제거 후 재 생성
handlerRemoveMarker();
handlerCreateAllMarker(paths);
setGeoState(geojson);
mapObject.setPaintProperty('waypoint', 'circle-radius', 8);
handlerGetSourceSetData();
}
}
};
// 새로운 popup 한 개 추가 (coord의 뒤에서 두개의 좌표 이용)
const addMileStone = (coord, radius) => {
const len = coord.length;
let lngLat = coord;
let anchor;
let distance;
if (coord[0].length) {
if (
mapControl.drawType !== 'CIRCLE' ||
props.areaCoordList[0].areaType !== 'CIRCLE'
) {
lngLat = handlerGetMidPoint(coord[len - 2], coord[len - 1]);
anchor = [0, 0];
distance = CalculateDistance(coord[len - 2], coord[len - 1]);
}
} else {
if (
mapControl.drawType === 'CIRCLE' ||
props.areaCoordList[0].areaType === 'CIRCLE'
) {
anchor = [20, 35];
distance = radius;
} else {
anchor = [0, -10];
distance = 'Start';
}
}
const popup = new props.mapboxgl.Popup({
offset: anchor,
closeButton: false,
closeOnClick: false
})
.setLngLat(lngLat)
.setHTML(handlerGetHtmlContent(distance))
.addTo(mapObject);
};
// 좌표 기반으로 모든 마커 재 생성
const handlerCreateAllMarker = coord => {
console.log('allCreateMarker');
const areas = props.areaCoordList[0];
if (areas.areaType !== 'CIRCLE') {
for (let i = 0; i < coord.length; i++) {
if (i == 0) {
addMileStone(coord[i], '');
} else {
addMileStone([coord[i], coord[i - 1]], '');
}
}
if (areas.areaType === 'POLYGON') {
addMileStone([coord[0], coord[coord.length - 1]], '');
}
} else {
addMileStone(coord[0], areas.bufferZone);
}
};
// 모든 마커 삭제
const handlerRemoveMarker = () => {
const ele = document.getElementsByClassName('mapboxgl-popup');
const eleArr = Array.from(ele);
eleArr?.forEach(marker => marker.remove());
};
// geojson에서 중복되는 obj 제거 or 제거 후 새로 생성
const handlerReplaceDuplicate = (id, obj) => {
geojson.features = geojson.features.filter(
geo => geo.properties?.id !== id
);
if (obj !== '') geojson.features.push(obj);
};
// geojson에서 원하는 Id의 coord만 추출
const handlerGetGeoJsonCoord = id => {
return geojson.features
.filter(geo => geo.properties?.id === id)
.map(geo => geo.geometry.coordinates);
};
const handlerGetSourceSetData = () => {
mapObject.getSource('detail').setData(geojson);
};
return <InfoModal modal={alertModal} setModal={setAlertModal} />;
};

574
src/components/map/mapbox/draw/LaancDrawRe.js

@ -1,574 +0,0 @@
import { useDispatch, useSelector } from 'react-redux';
import { InfoModal } from '../../../modal/InfoModal';
import { FormattingCoord, InitFeature } from './MapBoxDraw';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { AREA_COORDINATE_LIST_SAVE } from '../../../../modules/basis/flight/actions/basisFlightAction';
import {
CalculateDistance,
handlerCreatePoint,
handlerGetCircleCoord,
handlerGetHtmlContent,
handlerGetMidPoint
} from '../../../../utility/DrawUtil';
export const LaancDrawRe = props => {
const dispatch = useDispatch();
const mapControl = useSelector(state => state.controlMapReducer);
const mapObject = props.mapObject;
const canvas = mapObject.getCanvasContainer();
const [isDrawDone, setIsDrawDone] = useState(false);
const [alertModal, setAlertModal] = useState({
isOpen: false,
title: '',
desc: ''
});
const detailLayer = props.detailLayer;
const geojson = props.geojson;
const [clickCoord, setClickCoord] = useState([]);
const drawObj = InitFeature('', '');
const guideLine = InitFeature('LineString', 'guideline');
const bufferLine = InitFeature('LineString', 'buffer');
const [pastPoint, setPoint] = useState([]);
let point = [];
const mode = props.mode;
let dragCircleIdx;
useEffect(() => {
const areaType = props.areaCoordList[0].areaType;
if (areaType !== mode && detailLayer) {
drawInit();
}
}, [mode, detailLayer]);
useEffect(() => {
const areaType = props.areaCoordList[0].areaType;
console.log(props.areaCoordList, '>>----');
if (areaType && areaType !== '' && detailLayer) {
handlerPastDraw();
}
}, [props.areaCoordList, detailLayer]);
useEffect(() => {
if (isDrawDone) {
handlerDrawConfirm(props.areaCoordList);
setIsDrawDone(false);
}
}, [isDrawDone]);
const drawInit = useCallback(() => {
console.log('drawInit');
handlerRemoveEvent();
handlerRemoveGeoJson();
props.handlerInitCoordinates();
handlerStartMode();
}, [mode]);
const handlerRemoveEvent = useCallback(() => {
console.log('removeEvent');
mapObject.off('click', onClickDrawObj);
mapObject.off('mousemove', onMouseMoveDrawObj);
mapObject.off('mousedown', 'polygon', onMouseDown);
mapObject.off('contextmenu', onRightClick);
}, [mode]);
const handlerRemoveGeoJson = useCallback(() => {
console.log('removeGeoJson');
handlerRemoveMarker();
guideLine.geometry.coordinates = [];
bufferLine.geometry.coordinates = [];
drawObj.geometry.coordinates = [];
geojson.features = [];
point = [];
setPoint([]);
handlerGetSourceSetData();
}, [mode]);
const handlerStartMode = () => {
if (!mode || mode === 'RESET') return;
console.log('startMode');
if (mode === 'LINE') {
handlerSetDrawObj('LineString', 'LINE');
} else if (mode === 'POLYGON') {
handlerSetDrawObj('Polygon', 'POLYGON');
} else if (mode === 'CIRCLE') {
handlerSetDrawObj('Polygon', 'CIRCLE');
mapObject.on('click', onClickCircle);
}
if (mode !== 'CIRCLE') mapObject.on('click', onClickDrawObj);
};
const onClickDrawObj = useCallback(
e => {
console.log('click');
const formatCoord = FormattingCoord([e.lngLat.lng, e.lngLat.lat]);
const id = drawObj.properties.id;
const features = mapObject.queryRenderedFeatures(e.point, {
layers: ['waypoint']
});
if (geojson.features.length > 1) {
handlerReplaceDuplicate(drawObj.properties.id, '');
}
if (features.length) {
const featuresId = features[0].properties.id;
handlerReplaceDuplicate(featuresId, '');
} else {
const index = geojson.features.filter(
geo => geo.properties.id === 'point'
).length;
const wayPoint = handlerCreatePoint(formatCoord, index, id);
point.push(wayPoint);
handlerReplaceDuplicate('point', '');
point.forEach(p => geojson.features.push(p));
setPoint(p => [...p, wayPoint]);
}
if (id === 'LINE') guideLine.geometry.coordinates = [formatCoord];
if (geojson.features.length > 1) {
const coordinates = handlerGetGeoJsonCoord('point');
drawObj.geometry.coordinates =
id === 'LINE' ? coordinates : [coordinates];
geojson.features.push(drawObj);
addMileStone(coordinates, '');
} else {
mapObject.on('contextmenu', onRightClick);
mapObject.on('mousemove', onMouseMoveDrawObj);
addMileStone(formatCoord, '');
}
handlerGetSourceSetData();
setClickCoord(coord => [...coord, [formatCoord]]);
},
[clickCoord, point]
);
const onMouseMoveDrawObj = e => {
const formatCoord = FormattingCoord([e.lngLat.lng, e.lngLat.lat]);
const id = drawObj.properties.id;
if (id === 'LINE') {
if (guideLine.geometry.coordinates.length > 1) {
guideLine.geometry.coordinates.pop();
handlerReplaceDuplicate('guideline', guideLine);
}
guideLine.geometry.coordinates.push(formatCoord);
} else if (id === 'POLYGON') {
if (drawObj.geometry.coordinates.length > 0) {
if (drawObj.geometry.coordinates[0].length > 1) {
if (guideLine.geometry.coordinates.length > 1) {
guideLine.geometry.coordinates.pop();
drawObj.geometry.coordinates[0].pop();
}
guideLine.geometry.coordinates.push(formatCoord);
drawObj.geometry.coordinates[0].push(formatCoord);
}
}
}
handlerGetSourceSetData();
};
const onRightClick = e => {
handlerRemoveEvent();
const drawType = mapControl.drawType;
const path = handlerGetGeoJsonCoord('point');
if (path.length > 0) {
if (drawType === 'LINE') {
if (path.length > 1) {
handlerReplaceDuplicate('guideline', '');
handlerSaveAreaInfo(drawObj.geometry.coordinates);
} else {
setAlertModal({
isOpen: true,
title: '좌표 최소 개수',
desc: '좌표를 두 개 점으로 이어주세요.'
});
handlerRemoveGeoJson();
// props.handlerDrawType('RESET');
}
handlerGetSourceSetData();
} else if (drawType === 'POLYGON') {
if (path.length > 2) {
drawObj.geometry.coordinates[0] = path;
handlerReplaceDuplicate('POLYGON', drawObj);
handlerSaveAreaInfo(drawObj.geometry.coordinates[0]);
} else {
setAlertModal({
isOpen: true,
title: '좌표 최소 개수',
desc: '좌표를 세 개 점으로 이어주세요.'
});
handlerRemoveGeoJson();
// props.handlerDrawType('RESET');
}
}
handlerGetSourceSetData();
}
};
const onClickCircle = e => {
console.log('click');
const formatCoord = FormattingCoord([e.lngLat.lng, e.lngLat.lat]);
if (drawObj.geometry.coordinates.length === 0) {
mapObject.on('mousedown', 'polygon', onMouseDown);
}
const circleCoords = handlerGetCircleCoord(formatCoord, 100);
drawObj.properties.center = formatCoord;
drawObj.geometry.coordinates = circleCoords;
handlerReplaceDuplicate('CIRCLE', drawObj);
handlerSaveAreaInfo('');
addMileStone(formatCoord, 100);
handlerGetSourceSetData();
};
const onMouseDown = e => {
e.preventDefault();
canvas.style.cursor = 'grab';
const id = drawObj.properties.id;
const coord = handlerGetGeoJsonCoord(id);
if (id !== mode || coord.length === 0) {
mapObject.off('mousedown', 'waypoint', onMouseDown);
handlerReplaceDuplicate(id, '');
return;
}
console.log('down');
if (id === 'CIRCLE') {
handlerRemoveEvent();
mapObject.on('mousedown', 'polygon', onMouseDown);
} else {
dragCircleIdx = e.features[0].properties.index;
}
mapObject.on('mousemove', onMouseMove);
mapObject.on('mouseup', onMouseUp);
mapObject.off('click', onClickDrawObj);
mapObject.off('click', onClickCircle);
};
const onMouseMove = e => {
const formatCoord = FormattingCoord([e.lngLat.lng, e.lngLat.lat]);
canvas.style.cursor = 'grabbing';
const id = drawObj.properties.id;
if (id === 'CIRCLE') {
const distance = CalculateDistance(
formatCoord,
drawObj.properties.center
);
const center = drawObj.properties.center;
const circleCoords = handlerGetCircleCoord(center, distance);
drawObj.geometry.coordinates = circleCoords;
handlerReplaceDuplicate('CIRCLE', drawObj);
} else {
geojson.features = geojson.features.map(geo => {
const coord = formatCoord;
if (geo.properties?.index === dragCircleIdx) {
geo.geometry.coordinates = coord;
}
if (geo.properties?.id === 'LINE') {
geo.geometry.coordinates[dragCircleIdx] = coord;
drawObj.geometry.coordinates = geo.geometry.coordinates;
}
if (geo.properties?.id === 'buffer') {
geo.geometry.coordinates = [];
}
if (geo.properties?.id === 'POLYGON') {
geo.geometry.coordinates[0][dragCircleIdx] = coord;
drawObj.geometry.coordinates[0] = geo.geometry.coordinates[0];
}
return geo;
});
}
handlerGetSourceSetData();
};
const onMouseUp = e => {
canvas.style.cursor = '';
console.log('up');
mapObject.off('mousedown', 'waypoint', onMouseDown);
mapObject.off('mousemove', onMouseMove);
mapObject.off('mouseup', onMouseUp);
const obj =
mode === 'LINE' || mode === 'POLYGON' || mode === 'CIRCLE' ? true : false;
const objGeo = drawObj.geometry;
const coord = mode === 'LINE' ? objGeo.coordinates : objGeo.coordinates[0];
if (obj) {
if (mode === 'CIRCLE') {
mapObject.on('click', onClickCircle);
handlerSaveAreaInfo('');
} else {
handlerSaveAreaInfo(coord);
}
} else {
const areas = props.areaCoordList[0];
const type = areas.areaType;
const paths = [];
areas.coordList.forEach(coord => paths.push([coord.lon, coord.lat]));
if (type === 'CIRCLE') {
handlerSaveAreaInfo('');
} else {
handlerSaveAreaInfo(coord);
}
}
};
const handlerPastDraw = () => {
console.log('pastDraw');
const areas = props.areaCoordList[0];
const paths = [];
areas.coordList.forEach(coord => paths.push([coord.lon, coord.lat]));
if (areas.areaType) {
if (areas.areaType === 'CIRCLE') {
const radius = areas.bufferZone;
const circleCoords = handlerGetCircleCoord(paths[0], radius);
drawObj.properties.center = paths[0];
drawObj.geometry.coordinates = circleCoords;
drawObj.properties.id = 'CIRCLE';
drawObj.geometry.type = 'Polygon';
// geojson.features.push(drawObj);
handlerReplaceDuplicate('CIRCLE', drawObj);
} else {
if (areas.areaType === 'LINE') {
drawObj.geometry.coordinates = paths;
drawObj.properties.id = 'LINE';
drawObj.geometry.type = 'LineString';
geojson.features.push(drawObj);
// 버퍼 생성
if (areas.bufferCoordList) {
const bufferPaths = [];
areas.bufferCoordList.forEach(bfCoord =>
bufferPaths.push([bfCoord.lon, bfCoord.lat])
);
bufferLine.geometry.coordinates = bufferPaths;
handlerReplaceDuplicate('buffer', bufferLine);
}
} else if (areas.areaType === 'POLYGON') {
drawObj.geometry.coordinates = [paths];
drawObj.properties.id = 'POLYGON';
drawObj.geometry.type = 'Polygon';
geojson.features.push(drawObj);
}
handlerReplaceDuplicate(drawObj.properties.id, drawObj);
// 포인트 생성
paths.forEach((p, i) => {
const wayPoint = handlerCreatePoint(p, i, areas.areaType);
point.push(wayPoint);
// setPoint(po => [...po, wayPoint]);
});
handlerReplaceDuplicate('point', '');
point.forEach(p => geojson.features.push(p));
// pastPoint.forEach(p => geojson.features.push(p));
// mouseDown이벤트
mapObject.on('mousedown', 'waypoint', onMouseDown);
}
// 기존 마커 제거 후 재 생성
handlerRemoveMarker();
handlerCreateAllMarker(paths);
mapObject.setPaintProperty('waypoint', 'circle-radius', 8);
handlerGetSourceSetData();
}
};
const handlerSaveAreaInfo = coord => {
console.log('areaInfo', coord);
const type = mapControl.drawType;
const areaInfo = {
coordinates: [],
bufferZone: 0,
areaType: ''
};
const bufferZone = type === 'POLYGON' ? 0 : 100;
const prePath = [];
areaInfo.areaType = type;
if (areaInfo.areaType !== 'CIRCLE') {
coord.forEach(item => {
const p = {
lat: item[1],
lon: item[0]
};
prePath.push(p);
});
}
areaInfo.coordinates = prePath;
areaInfo.bufferZone = bufferZone;
if (areaInfo.areaType === 'CIRCLE') {
const point = {
lat: drawObj.properties.center[1],
lon: drawObj.properties.center[0]
};
areaInfo.coordinates = [point];
areaInfo.bufferZone = CalculateDistance(
drawObj.geometry.coordinates[0][0],
drawObj.properties.center
);
}
props.handlerCoordinates(areaInfo);
setIsDrawDone(true);
};
const handlerDrawConfirm = useCallback(
areaList => {
if (areaList === undefined) {
alert('영역을 설정해 주세요.');
return false;
}
dispatch(AREA_COORDINATE_LIST_SAVE(areaList));
},
[isDrawDone]
);
const handlerSetDrawObj = useCallback(
(type, id) => {
drawObj.geometry.type = type;
drawObj.properties.id = id;
},
[mode]
);
// 새로운 popup 한 개 추가 (coord의 뒤에서 두개의 좌표 이용)
const addMileStone = (coord, radius) => {
const len = coord.length;
let lngLat = coord;
let anchor;
let distance;
if (coord[0].length) {
if (mode !== 'CIRCLE' || props.areaCoordList[0].areaType !== 'CIRCLE') {
lngLat = handlerGetMidPoint(coord[len - 2], coord[len - 1]);
anchor = [0, 0];
distance = CalculateDistance(coord[len - 2], coord[len - 1]);
}
} else {
if (mode === 'CIRCLE' || props.areaCoordList[0].areaType === 'CIRCLE') {
anchor = [20, 35];
distance = radius;
} else {
anchor = [0, -10];
distance = 'Start';
}
}
const popup = new props.mapboxgl.Popup({
offset: anchor,
closeButton: false,
closeOnClick: false
})
.setLngLat(lngLat)
.setHTML(handlerGetHtmlContent(distance))
.addTo(mapObject);
};
// 좌표 기반으로 모든 마커 재 생성
const handlerCreateAllMarker = coord => {
console.log('allCreateMarker');
const areas = props.areaCoordList[0];
if (areas.areaType !== 'CIRCLE') {
for (let i = 0; i < coord.length; i++) {
if (i == 0) {
addMileStone(coord[i], '');
} else {
addMileStone([coord[i], coord[i - 1]], '');
}
}
if (areas.areaType === 'POLYGON') {
addMileStone([coord[0], coord[coord.length - 1]], '');
}
} else {
addMileStone(coord[0], areas.bufferZone);
}
};
// 모든 마커 삭제
const handlerRemoveMarker = () => {
const ele = document.getElementsByClassName('mapboxgl-popup');
const eleArr = Array.from(ele);
eleArr?.forEach(marker => marker.remove());
};
// geojson에서 중복되는 obj 제거 or 제거 후 새로 생성
const handlerReplaceDuplicate = (id, obj) => {
geojson.features = geojson.features.filter(
geo => geo.properties?.id !== id
);
if (obj !== '') geojson.features.push(obj);
};
// geojson에서 원하는 Id의 coord만 추출
const handlerGetGeoJsonCoord = id => {
return geojson.features
.filter(geo => geo.properties?.id === id)
.map(geo => geo.geometry.coordinates);
};
// 지도에 geojson데이터 새로고침
const handlerGetSourceSetData = () => {
mapObject.getSource('detail').setData(geojson);
};
return <InfoModal modal={alertModal} setModal={setAlertModal} />;
};

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

@ -1,683 +0,0 @@
import { useSelector } from 'react-redux';
import { InfoModal } from '../../../modal/InfoModal';
import * as turf from '@turf/turf';
import { useEffect, useState } from 'react';
//let 변수들 geoJson 형식으로 초기화
export const InitFeature = (type, id) => {
return {
type: 'Feature',
geometry: {
type: type,
coordinates: []
},
properties: { id: id, center: '' }
};
};
//소수점 7자리까지만 자름 / coord = [lng, lat]
export const FormattingCoord = coord => {
const resultArr = [];
coord.forEach(co => {
const split = String(co).split('.');
const result = split[0] + '.' + split[1].substring(0, 7);
resultArr.push(Number(result));
});
return resultArr;
};
//거리 계산(meters로 리턴)
// 사용 1. 원의 센터로부터 e.coord까지
// 사용 2. distance 마커
export const CalculateDistance = (mouse, center) => {
const centerCoord = turf.point(center);
const mouseCoord = turf.point(mouse);
const options = { units: 'kilometers' };
const distance = Math.round(
turf.distance(centerCoord, mouseCoord, options) * 1000
);
return distance;
};
// 수정해야 할 사항
// 4. 폴리곤을.. 폴리라인도 추가해야 될거 같음
// 꼭짓점 두개 찍었을 때는 영역 or 라인이 안보이기 때문
// 2. drawType을 바꾸고 그린 다음 도형을 수정하면
// move중에 처음 그린 도형 표출되는 현상도 수정해야 함
export const MapBoxDraw = props => {
const mapControl = useSelector(state => state.controlMapReducer);
const mapObject = props.mapObject;
const canvas = mapObject.getCanvasContainer();
//비행계획서 작성 완료 후에는 수정 불가일거라서 이거는 임시 보류
const isDone = props.isDone;
const isDisabled = props.isDisabled;
const [alertModal, setAlertModal] = useState({
isOpen: false,
title: '',
desc: ''
});
//도형들이 온전히 그려진 후 변경 될 때 마다 감지
const [isDrawDone, setIsDrawDone] = useState(false);
const [mouseDownEve, setMouseDownEve] = useState(false);
const areaInfo = {
coordinates: [],
bufferZone: 0,
areaType: ''
};
const geojson = props.geojson;
let mode = props.mode;
let guideLine = InitFeature('LineString', 'guideline');
let lineString = InitFeature('LineString', 'polyline');
let bufferPolyline = InitFeature('LineString', 'buffer');
let polygon = InitFeature('Polygon', 'polygon');
let circle = InitFeature('Polygon', 'circle');
let point = [];
let dragCircleIdx;
useEffect(() => {
if (mapControl.drawType) drawInit();
}, [mapControl.drawType]);
useEffect(() => {
if (isDrawDone) {
props.handlerConfirm(props.areaCoordList);
setIsDrawDone(false);
}
}, [isDrawDone]);
useEffect(() => {
const area = props.areaCoordList[0];
if (area.areaType && area.areaType !== '') {
handlerPastDraw();
}
}, [props.areaCoordList]);
const drawInit = () => {
handlerButtonClick(mapControl.drawType);
};
//그리기 타입 선택
const handlerButtonClick = newMode => {
handlerClearMode(mode);
if (mode === newMode) {
mode = null;
return;
}
handlerStartMode(newMode);
};
const handlerClearMode = () => {
console.log('clearMode');
finishDraw();
removeGeoJson();
props.handlerInitCoordinates();
};
const handlerStartMode = mode => {
if (!mode) return;
mapObject.on('click', clickEve);
};
const removeListener = () => {
console.log('removeListener');
mapObject.off('click', clickEve);
mapObject.off('click', onClickCircle);
mapObject.off('mouseup', onMouseUp);
mapObject.off('mousedown', 'waypoint', onMouseDown);
mapObject.off('mousedown', 'polygon', onMouseDown);
mapObject.off('mousemove', onMouseMove);
mapObject.off('mousemove', onMouseMovePolyline);
mapObject.off('mousemove', onMouseMovePolygon);
mapObject.off('contextmenu', finishDraw);
// 이거 있나 없나 뭔 차이지?
setMouseDownEve(false);
};
const removeGeoJson = () => {
console.log('removeGeoJson');
handlerRemoveMarker();
guideLine.geometry.coordinates = [];
lineString.geometry.coordinates = [];
bufferPolyline.geometry.coordinates = [];
polygon.geometry.coordinates = [];
circle.geometry.coordinates = [];
point = [];
geojson.features = [];
mapObject.getSource('geojson').setData(geojson);
};
const finishDraw = () => {
removeListener();
console.log('finish');
const drawType = mapControl.drawType;
const path = handlerGetGeoJsonCoord('point');
if (path.length > 0) {
if (drawType === 'LINE') {
if (path.length > 1) {
handlerReplaceDuplicate('guideline', '');
handlerSaveAreaInfo(lineString.geometry.coordinates);
} else {
setAlertModal({
isOpen: true,
title: '좌표 최소 개수',
desc: '좌표를 두 개 점으로 이어주세요.'
});
removeGeoJson();
props.handlerDrawType('RESET');
// mapObject.on('click', clickEve);
}
mapObject.getSource('geojson').setData(geojson);
} else if (drawType === 'POLYGON') {
if (path.length > 2) {
polygon.geometry.coordinates[0] = path;
handlerReplaceDuplicate('polygon', polygon);
handlerSaveAreaInfo(polygon.geometry.coordinates[0]);
} else {
setAlertModal({
isOpen: true,
title: '좌표 최소 개수',
desc: '좌표를 세 개 점으로 이어주세요.'
});
removeGeoJson();
props.handlerDrawType('RESET');
// mapObject.on('click', clickEve);
}
}
mapObject.getSource('geojson').setData(geojson);
}
};
const clickEve = e => {
const drawType = mapControl.drawType;
if (drawType === 'LINE') onClickFeature(e, lineString);
if (drawType === 'POLYGON') onClickFeature(e, polygon);
if (drawType === 'CIRCLE') onClickCircle(e);
};
// polyline, polygon 생성
const onClickFeature = (e, obj) => {
const formatCoord = FormattingCoord([e.lngLat.lng, e.lngLat.lat]);
//현재 내 좌표가 waypoint레이어의 geojson도형 안에 속해있는지 안해있는지?
//geojson을 반환해주는 듯?
const features = mapObject.queryRenderedFeatures(e.point, {
layers: ['waypoint']
});
const id = obj.properties.id;
if (geojson.features.length > 1) {
handlerReplaceDuplicate(id, '');
}
if (features.length) {
const featuresId = features[0].properties.id;
handlerReplaceDuplicate(featuresId, '');
} else {
const index = geojson.features.filter(
geo => geo.properties?.id === 'point'
).length;
const wayPoint = handlerCreatePoint(
formatCoord,
index,
mapControl.drawType
);
handlerReplaceDuplicate('Point', wayPoint);
}
guideLine.geometry.coordinates = [formatCoord];
if (geojson.features.length > 1) {
//나머지 좌표
const coordinates = handlerGetGeoJsonCoord('point');
obj.geometry.coordinates =
id === 'polyline' ? coordinates : [coordinates];
geojson.features.push(obj);
addMileStone(coordinates, '');
} else {
//첫 좌표
mapObject.on('contextmenu', finishDraw);
mapObject.on(
'mousemove',
id === 'polyline' ? onMouseMovePolyline : onMouseMovePolygon
);
addMileStone(formatCoord, '');
}
mapObject.getSource('geojson').setData(geojson);
};
// polyline 가이드 생성
const onMouseMovePolyline = e => {
const formatCoord = FormattingCoord([e.lngLat.lng, e.lngLat.lat]);
if (guideLine.geometry.coordinates.length > 1) {
guideLine.geometry.coordinates.pop();
handlerReplaceDuplicate('guideline', guideLine);
}
guideLine.geometry.coordinates.push(formatCoord);
mapObject.getSource('geojson').setData(geojson);
};
// polygon 가이드 생성
const onMouseMovePolygon = e => {
const formatCoord = FormattingCoord([e.lngLat.lng, e.lngLat.lat]);
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();
}
guideLine.geometry.coordinates.push(formatCoord);
polygon.geometry.coordinates[0].push(formatCoord);
}
}
// 이거.. 왜 안해도 잘 되지....?
// handlerReplaceDuplicate('polygon', polygon);
mapObject.getSource('geojson').setData(geojson);
};
// circle 생성
const onClickCircle = e => {
console.log('circleClick');
const formatCoord = FormattingCoord([e.lngLat.lng, e.lngLat.lat]);
if (circle.geometry.coordinates.length === 0) {
mapObject.on('mousedown', 'polygon', onMouseDown);
}
const circleCoords = handlerGetCircleCoord(formatCoord, 100);
circle.properties.center = formatCoord;
circle.geometry.coordinates = circleCoords;
handlerReplaceDuplicate('circle', circle);
handlerSaveAreaInfo('');
addMileStone(formatCoord, 100);
mapObject.getSource('geojson').setData(geojson);
};
const onMouseDown = e => {
e.preventDefault();
console.log('down');
//타입 교체만 하면 왜 처음엔 down이 두번 잡힐까...
// console.log(e.features[0].properties.type, '>>down e');
canvas.style.cursor = 'grab';
if (circle.geometry.coordinates.length > 0) {
removeListener();
mapObject.on('mousedown', 'polygon', onMouseDown);
} else {
dragCircleIdx = e.features[0].properties.index;
}
mapObject.on('mousemove', onMouseMove);
mapObject.on('mouseup', onMouseUp);
mapObject.off('click', clickEve);
};
const onMouseMove = e => {
const formatCoord = FormattingCoord([e.lngLat.lng, e.lngLat.lat]);
canvas.style.cursor = 'grabbing';
if (circle.geometry.coordinates.length > 0) {
const distance = CalculateDistance(formatCoord, circle.properties.center);
const center = circle.properties.center;
const circleCoords = handlerGetCircleCoord(center, distance);
circle.geometry.coordinates = circleCoords;
} else {
geojson.features = geojson.features.map(geo => {
const coord = formatCoord;
if (geo.properties?.index === dragCircleIdx) {
geo.geometry.coordinates = coord;
}
if (geo.properties?.id === 'polyline') {
geo.geometry.coordinates[dragCircleIdx] = coord;
lineString = geo;
}
if (geo.properties?.id === 'buffer') {
geo.geometry.coordinates = [];
}
if (geo.properties?.id === 'polygon') {
geo.geometry.coordinates[0][dragCircleIdx] = coord;
polygon = geo;
}
return geo;
});
}
mapObject.getSource('geojson').setData(geojson);
};
const onMouseUp = () => {
canvas.style.cursor = '';
console.log('up');
mapObject.off('mousedown', 'waypoint', onMouseDown);
mapObject.off('mousemove', onMouseMove);
mapObject.off('mouseup', onMouseUp);
mapObject.off('click', clickEve);
setMouseDownEve(false);
const type = mapControl.drawType;
const obj =
type === 'LINE'
? lineString
: type === 'POLYGON'
? polygon
: type === 'CIRCLE'
? circle
: undefined;
if (obj) {
const id = obj.properties?.id;
const coord =
id === 'polyline'
? obj.geometry.coordinates
: obj.geometry.coordinates[0];
if (id === 'circle') {
mapObject.on('click', clickEve);
handlerSaveAreaInfo('');
} else {
// mapObject.on('mousedown', 'waypoint', onMouseDown);
handlerSaveAreaInfo(coord);
}
} else {
// 저장된 좌표 불러왔을 때
const areas = props.areaCoordList[0];
const type = areas.areaType;
const paths = [];
areas.coordList.forEach(coord => paths.push([coord.lon, coord.lat]));
if (type === 'LINE') {
handlerSaveAreaInfo(lineString.geometry.coordinates);
} else if (type === 'POLYGON') {
handlerSaveAreaInfo(polygon.geometry.coordinates[0]);
} else if (type === 'CIRCLE') {
handlerSaveAreaInfo('');
}
}
};
// 도형 정보 변경되면 저장
const handlerSaveAreaInfo = coord => {
console.log('areaInfo');
const bufferZone = polygon.geometry.coordinates.length > 0 ? 0 : 100;
const prePath = [];
if (lineString.geometry.coordinates.length > 0) {
areaInfo.areaType = 'LINE';
} else if (polygon.geometry.coordinates.length > 0) {
areaInfo.areaType = 'POLYGON';
} else if (circle.geometry.coordinates.length > 0) {
areaInfo.areaType = 'CIRCLE';
}
if (areaInfo.areaType !== 'CIRCLE') {
coord.forEach(item => {
const p = {
lat: item[1],
lon: item[0]
};
prePath.push(p);
});
}
areaInfo.coordinates = prePath;
areaInfo.bufferZone = bufferZone;
if (areaInfo.areaType === 'CIRCLE') {
const point = {
lat: circle.properties.center[1],
lon: circle.properties.center[0]
};
areaInfo.coordinates = [point];
areaInfo.bufferZone = CalculateDistance(
circle.geometry.coordinates[0][0],
circle.properties.center
);
}
props.handlerCoordinates(areaInfo);
setIsDrawDone(true);
};
// 확정된 도형 재 생성(let이라서 지워지기 때문에)
const handlerPastDraw = () => {
if (props.areaCoordList) {
console.log('pastDraw');
const areas = props.areaCoordList[0];
const paths = [];
areas.coordList.forEach(coord => paths.push([coord.lon, coord.lat]));
if (areas.areaType) {
if (areas.areaType === 'CIRCLE') {
const radius = areas.bufferZone;
const circleCoords = handlerGetCircleCoord(paths[0], radius);
circle.properties.center = paths[0];
circle.geometry.coordinates = circleCoords;
geojson.features.push(circle);
} else {
if (areas.areaType === 'LINE') {
lineString.geometry.coordinates = paths;
geojson.features.push(lineString);
// 버퍼 생성
if (areas.bufferCoordList) {
const bufferPaths = [];
areas.bufferCoordList.forEach(bfCoord =>
bufferPaths.push([bfCoord.lon, bfCoord.lat])
);
bufferPolyline.geometry.coordinates = bufferPaths;
handlerReplaceDuplicate('buffer', bufferPolyline);
}
} else if (areas.areaType === 'POLYGON') {
polygon.geometry.coordinates = [paths];
geojson.features.push(polygon);
}
// 포인트 생성
paths.forEach((p, i) => handlerCreatePoint(p, i, areas.areaType));
handlerReplaceDuplicate('point', '');
point.forEach(p => geojson.features.push(p));
//once로 하면 꼬이는건 해결되는데 지도를 움직이면 이벤트가 사라짐 -> 왜? onMouseDown이 실행된게 아니잖아?
//on으로 하면 그 반대 현상 -> 이벤트 다 지워줬는데 왜 down이 두번 잡혀??????
//얘만 해결하면 끝인데...
if (!mouseDownEve) {
mapObject.on('mousedown', 'waypoint', onMouseDown);
setMouseDownEve(true);
}
}
// 기존 마커 제거 후 재 생성
handlerRemoveMarker();
handlerCreateAllMarker(paths);
mapObject.setPaintProperty('waypoint', 'circle-radius', 8);
mapObject.getSource('geojson').setData(geojson);
}
}
};
// 새로운 popup 한 개 추가 (coord의 뒤에서 두개의 좌표 이용)
const addMileStone = (coord, radius) => {
const len = coord.length;
let lngLat = coord;
let anchor;
let distance;
if (coord[0].length) {
if (
mapControl.drawType !== 'CIRCLE' ||
props.areaCoordList[0].areaType !== 'CIRCLE'
) {
lngLat = handlerGetMidPoint(coord[len - 2], coord[len - 1]);
anchor = [0, 0];
distance = CalculateDistance(coord[len - 2], coord[len - 1]);
}
} else {
if (
mapControl.drawType === 'CIRCLE' ||
props.areaCoordList[0].areaType === 'CIRCLE'
) {
anchor = [20, 35];
distance = radius;
} else {
anchor = [0, -10];
distance = 'Start';
}
}
const popup = new props.mapboxgl.Popup({
offset: anchor,
closeButton: false,
closeOnClick: false
})
.setLngLat(lngLat)
.setHTML(handlerGetHtmlContent(distance))
.addTo(mapObject);
};
// 좌표 기반으로 모든 마커 재 생성
const handlerCreateAllMarker = coord => {
console.log('allCreateMarker');
const areas = props.areaCoordList[0];
if (areas.areaType !== 'CIRCLE') {
for (let i = 0; i < coord.length; i++) {
if (i == 0) {
addMileStone(coord[i], '');
} else {
addMileStone([coord[i], coord[i - 1]], '');
}
}
if (areas.areaType === 'POLYGON') {
addMileStone([coord[0], coord[coord.length - 1]], '');
}
} else {
addMileStone(coord[0], areas.bufferZone);
}
};
// 모든 마커 삭제
const handlerRemoveMarker = () => {
const ele = document.getElementsByClassName('mapboxgl-popup');
const eleArr = Array.from(ele);
eleArr?.forEach(marker => marker.remove());
};
// 두 좌표 간의 중간 지점 좌표 반환
const handlerGetMidPoint = (dis1, dis2) => {
return [(dis1[0] + dis2[0]) / 2, (dis1[1] + dis2[1]) / 2];
};
// html Content 반환
const handlerGetHtmlContent = distance => {
const text =
typeof distance === 'number' ? fromMetersToText(distance) : distance;
return (
'<div style="display:inline-block;padding:5px;text-align:center;background-color:#fff;border:1px solid #000;font-size:13px;color:#ff0000;"><span>' +
text +
'</span></div>'
);
};
// 미터 반환(m붙여서)
const fromMetersToText = meters => {
meters = meters || 0;
const text = parseFloat(meters.toFixed(1)) + 'm';
return text;
};
// geojson에서 중복되는 obj 제거 or 제거 후 새로 생성
const handlerReplaceDuplicate = (id, obj) => {
geojson.features = geojson.features.filter(
geo => geo.properties?.id !== id
);
if (obj !== '') geojson.features.push(obj);
};
// geojson에서 원하는 Id의 coord만 추출
const handlerGetGeoJsonCoord = id => {
return geojson.features
.filter(geo => geo.properties?.id === id)
.map(geo => geo.geometry.coordinates);
};
// circle 360도 좌표 반환
const handlerGetCircleCoord = (center, distance) => {
const options = {
steps: 360,
units: 'kilometers'
};
return turf.circle(center, distance / 1000, options).geometry.coordinates;
};
// 포인트 생성
const handlerCreatePoint = (coord, index, type) => {
const wayPoint = {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: coord
},
properties: { id: 'point', index: index, type: type }
};
point.push(wayPoint);
return wayPoint;
};
return <InfoModal modal={alertModal} setModal={setAlertModal} />;
};

201
src/components/map/naver/draw/ControlDraw.js

@ -1,201 +0,0 @@
import $ from 'jquery';
import { useState, useEffect } from 'react';
import { useSelector } from 'react-redux';
export default function ControlDraw(props) {
const mapControl = useSelector(state => state.controlMapReducer);
const naver = props.naver;
const map = props.map;
const [circleArr, setCircleArr] = useState([]);
const [markerArr, setMarkerArr] = useState([]);
const [upCircle, setUpCircle] = useState(false);
useEffect(() => {
if (upCircle) {
const delay = 100;
const timer = setTimeout(() => {
resumeMapClick();
setUpCircle(false);
const index = circleArr.findIndex(
prev => prev.center === upCircle.getCenter()
);
markerArr.map((prev, idx) => {
if (idx === index) {
const text = fromMetersToText(upCircle.getRadius());
const content =
'<div style="display:inline-block;padding:5px;text-align:center;background-color:#fff;border:1px solid #000;font-size:13px;color:#737373;"><span>' +
text +
'</span></div>';
prev.setIcon({
...prev.getIcon(),
content: content
});
}
});
}, delay);
return () => {
clearTimeout(timer);
};
}
}, [upCircle]);
useEffect(() => {
naver.maps.Event.addListener(map, 'click', onClickCircle);
stopMapClick();
}, []);
useEffect(() => {
drawInit();
}, [mapControl.ctrlDrawType]);
const drawInit = () => {
if (mapControl.ctrlDrawType === 'CIRCLE') {
onClickButton('CIRCLE');
} else if (mapControl.ctrlDrawType === 'RESET') {
clearMode();
}
};
const onClickButton = newMode => {
clearMode();
startMode(newMode);
};
const clearMode = () => {
if (circleArr.length != 0) {
circleArr.map(obj => obj.circle.setMap(null));
setCircleArr([]);
markerArr.map(marker => marker.setMap(null));
setMarkerArr([]);
stopMapClick();
}
};
const startMode = mode => {
if (!mode) return;
if (mode === 'CIRCLE') {
resumeMapClick();
}
};
const stopMapClick = () => {
naver.maps.Event.stopDispatch(map, 'click');
};
const resumeMapClick = () => {
naver.maps.Event.resumeDispatch(map, 'click');
};
const onClickCircle = e => {
const coord = e.coord;
const circle = new naver.maps.Circle({
strokeColor: '#ff0000',
strokeOpacity: 1,
fillColor: '#ff0000',
fillOpacity: 0.3,
center: coord,
radius: 100,
map: map,
clickable: true
});
setCircleArr(prev => [
...prev,
{ center: coord, circle: circle, radius: 100 }
]);
naver.maps.Event.addListener(circle, 'mousedown', function () {
onMouseDown(circle);
});
addMileStone(coord, fromMetersToText(100));
};
const onMouseDown = circle => {
map.setOptions({
draggable: false,
pinchZoom: false,
scrollWheel: false,
keyboardShortcuts: false,
disableDoubleTapZoom: true,
disableDoubleClickZoom: true,
disableTwoFingerTapZoom: true
});
$(document).on('mousemove.measure', function (e) {
onMouseMove(e, circle);
});
$(document).on('mouseup.measure', function () {
onMouseUp(circle);
});
};
const onMouseMove = (e, circle) => {
const proj = map.getProjection();
const coord = proj.fromPageXYToCoord(
new naver.maps.Point(e.pageX, e.pageY)
);
const center = circle.getCenter();
const r = proj.getDistance(coord, center);
circle.setRadius(r);
};
const onMouseUp = circle => {
map.setOptions({
draggable: true,
pinchZoom: true,
scrollWheel: true,
keyboardShortcuts: true,
disableDoubleTapZoom: false,
disableDoubleClickZoom: false,
disableTwoFingerTapZoom: false
});
$(document).off('mousemove.measure');
$(document).off('mouseup.measure');
stopMapClick();
setUpCircle(circle);
};
const addMileStone = (coord, text) => {
const content =
'<div style="display:inline-block;padding:5px;text-align:center;background-color:#fff;border:1px solid #000;font-size:13px;color:#737373;"><span>' +
text +
'</span></div>';
const midPoint = coord;
const anchor = new naver.maps.Point(20, 35);
const marker = new naver.maps.Marker({
position: midPoint,
icon: {
content: content,
anchor: anchor
}
});
marker.setMap(map);
setMarkerArr(prev => [...prev, marker]);
};
const fromMetersToText = meters => {
meters = meters || 0;
const text = parseFloat(meters.toFixed(1)) + 'm';
return text;
};
return null;
}

918
src/components/map/naver/draw/FlightPlanDraw.js

@ -1,918 +0,0 @@
import $ from 'jquery';
import { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import * as Actions from '../../../../modules/basis/flight/actions/basisFlightAction';
import { InfoModal } from '../../../modal/InfoModal';
export const FlightPlanDraw_init = props => {
const dispatch = useDispatch();
const mapControl = useSelector(state => state.controlMapReducer);
const isDone = props.isDone;
const isDisabled = props.isDisabled;
const [pastPolyline, setPolyline] = useState();
const [pastBuffer, setBuffer] = useState();
const [pastPolygon, setPolygon] = useState();
const [pastCircle, setCircle] = useState([]);
// const [pastDragCircle, setDragCircle] = useState([]);
const pastDragCircle = props.pastDragCircle;
const setDragCircle = props.setDragCircle;
const [pastClickEve, setClickEve] = useState();
const [pastMarker, setMarker] = useState([]);
const [figure, setFigure] = useState();
const [areaDetail, setAreaDetail] = useState();
const [alertModal, setAlertModal] = useState({
isOpen: false,
title: '',
desc: ''
});
const [radiusCircle, setRadiusCircle] = useState();
const naver = props.naver;
const map = props.map;
let mode = props.mode;
let areaInfo;
let lastDistance;
let polyline;
let guideline;
let bufferPolygon;
let polygon;
let circle;
let radiusline;
let Eve = {
clickEve: '',
mousedownEve: '',
rightclickEve: ''
};
let dragCircle = [];
let dragCircleEve = [];
let distanceMarker = [];
useEffect(() => {
setRadiusCircle(props.dragSize);
}, [props.dragSize]);
useEffect(() => {
drawInit();
}, [mapControl.drawType]);
useEffect(() => {
console.log(props.areaCoordList, '빈양식');
handleDetailDraw();
}, [props.areaCoordList]);
useEffect(() => {
if (figure) {
setAreaDetail(props.areaCoordList);
props.handleConfirm(props.areaCoordList);
}
}, [figure]);
useEffect(() => {
console.log(areaDetail, '채워진양식?');
if (pastPolyline) {
handleBufferList();
}
}, [areaDetail]);
const handleBufferList = () => {
dispatch(Actions.FLIGHT_PLAN_AREA_BUFFER_LIST.request(areaDetail));
};
const drawInit = () => {
const drawType = mapControl.drawType;
onClickButton(drawType);
};
const onClickButton = newMode => {
clearMode(mode);
if (mode === newMode) {
mode = null;
return;
}
startMode(newMode);
};
const clearMode = mode => {
// if(!mode) return;
if (pastPolyline) {
pastPolyline.setMap(null);
pastDragCircle.forEach(c => c.setMap(null));
pastBuffer.setMap(null);
setPolyline();
setDragCircle([]);
setBuffer();
}
if (pastPolygon) {
pastPolygon.setMap(null);
pastDragCircle.forEach(c => c.setMap(null));
setPolygon();
setDragCircle([]);
}
if (pastCircle.length != 0) {
pastCircle.forEach(prev => prev.setMap(null));
naver.maps.Event.removeListener(pastClickEve);
setCircle([]);
}
if (pastMarker.length != 0) {
pastMarker.forEach(m => m.setMap(null));
setMarker([]);
}
finishDraw();
props.handleInitCoordinates();
};
const startMode = mode => {
if (!mode) return;
if (pastClickEve) {
naver.maps.Event.removeListener(pastClickEve);
}
Eve.clickEve = naver.maps.Event.addListener(map, 'click', function (e) {
if (mode === 'LINE') {
onClickPolyline(e);
} else if (mode === 'POLYGON') {
onClickPolygon(e);
} else if (mode === 'CIRCLE') {
onClickCircle(e);
}
});
if (mode === 'CIRCLE') setClickEve(Eve.clickEve);
};
const removeListener = () => {
naver.maps.Event.removeListener(Eve.clickEve);
naver.maps.Event.removeListener(pastClickEve);
setClickEve();
naver.maps.Event.removeListener(Eve.mousedownEve);
naver.maps.Event.removeListener(Eve.rightclickEve);
if (!circle) $(document).off('mousemove.measure');
};
const finishDraw = () => {
removeListener();
if (polyline) {
if (guideline) {
guideline.setMap(null);
guideline = '';
}
let polypaths = polyline.getPath()._array;
setMarker(distanceMarker);
distanceMarker.forEach(c => c.setMap(null));
if (polypaths.length >= 2) {
setPolyline(polyline);
setAreaInfo(polypaths);
setFigure(polyline);
} else {
setAlertModal({
isOpen: true,
title: '좌표 최소 개수',
desc: '좌표를 두 개 점으로 이어주세요.'
});
polyline.setMap(null);
polyline = '';
}
} else if (polygon) {
let path = polygon.getPath();
path.pop();
let polygonpaths = polygon.getPath()._array;
//마지막 path와 시작점을 이어주는 라인 생성
lastDistance = guideline.getDistance();
guideline.getPath().push(polygonpaths[0]);
var distance = guideline.getDistance();
// addMileStone(polygonpaths[0], fromMetersToText(distance - lastDistance));
setMarker(distanceMarker);
distanceMarker.forEach(c => c.setMap(null));
if (polygonpaths.length >= 3) {
setPolygon(polygon);
setAreaInfo(polygonpaths);
setFigure(polygon);
} else {
setAlertModal({
isOpen: true,
title: '좌표 최소 개수',
desc: '좌표를 세 개 점으로 이어주세요.'
});
polygon.setMap(null);
polygon = '';
}
}
};
const onClickPolyline = e => {
var coord = e.coord;
if (!polyline) {
//가이드라인
guideline = new naver.maps.Polyline({
strokeColor: '#283046',
strokeWeight: 2,
strokeOpacity: 0.3,
path: [coord],
map: map
});
// lastDistance = guideline.getDistance();
//실제 사용되는 라인
polyline = new naver.maps.Polyline({
strokeLineCap: 'round',
strokeLineJoin: 'round',
strokeColor: '#283046',
// strokeColor: '#ff0000',
strokeWeight: 1,
strokeOpacity: 1,
path: [coord],
map: map
});
Eve.rightclickEve = naver.maps.Event.addListener(
map,
'rightclick',
function () {
finishDraw();
}
);
$(document).on('mousemove.measure', function (e) {
onMouseMovePolyline(e);
});
lastDistance = polyline.getDistance();
addMileStone(coord, 'Start');
} else {
guideline.setPath([e.coord]);
polyline.getPath().push(coord);
var distance = polyline.getDistance();
// addMileStone(coord, fromMetersToText(distance - lastDistance));
addMileStone(
polyline.getPath()._array,
fromMetersToText(distance - lastDistance)
);
lastDistance = distance;
}
};
const onMouseMovePolyline = e => {
var proj = map.getProjection(),
coord = proj.fromPageXYToCoord(new naver.maps.Point(e.pageX, e.pageY)),
path = guideline.getPath();
if (path.getLength() === 2) {
path.pop();
}
path.push(coord);
};
const onClickPolygon = e => {
var coord = e.coord;
// let guide;
if (!polygon) {
polygon = new naver.maps.Polygon({
strokeColor: '#283046',
strokeOpacity: 1,
fillColor: '#8a1c05',
fillOpacity: 0.1,
paths: [coord],
map: map
});
//거리재기를 위한 가이드
guideline = new naver.maps.Polyline({
path: [coord],
map: map
});
guideline.setVisible(false);
Eve.rightclickEve = naver.maps.Event.addListener(
map,
'rightclick',
function () {
finishDraw();
}
);
$(document).on('mousemove.measure', function (e) {
onMouseMovePolygon(e);
});
lastDistance = guideline.getDistance();
addMileStone(coord, 'Start');
} else {
polygon.getPath().push(coord);
guideline.getPath().push(coord);
var distance = guideline.getDistance();
// addMileStone(coord, fromMetersToText(distance - lastDistance));
addMileStone(
guideline.getPath()._array,
fromMetersToText(distance - lastDistance)
);
lastDistance = distance;
}
};
const onMouseMovePolygon = e => {
if (!polygon) return;
var proj = map.getProjection(),
coord = proj.fromPageXYToCoord(new naver.maps.Point(e.pageX, e.pageY)),
path = polygon.getPath();
if (path.getLength() >= 2) {
path.pop();
}
path.push(coord);
};
const onClickCircle = e => {
var coord = e.coord;
if (!circle) {
radiusline = new naver.maps.Polyline({
strokeStyle: [4, 4],
strokeOpacity: 0.6,
path: [coord]
// map: map
});
lastDistance = radiusline.getDistance();
circle = new naver.maps.Circle({
strokeColor: '#283046',
strokeOpacity: 1,
fillColor: '#8a1c05',
fillOpacity: 0.1,
center: coord,
radius: 100,
map: map,
clickable: true
});
Eve.mousedownEve = naver.maps.Event.addListener(
circle,
'mousedown',
function () {
onMouseDownDrag(0);
}
);
addMileStone(coord, fromMetersToText(100));
} else {
circle.setCenter(coord);
circle.setRadius(100);
distanceMarker.setPosition(coord);
}
setCircle(prev => [...prev, circle]);
setAreaInfo('');
setMarker(distanceMarker);
setFigure(circle.center);
};
const onMouseDownDrag = index => {
map.setOptions({
draggable: false,
pinchZoom: false,
scrollWheel: false,
keyboardShortcuts: false,
disableDoubleTapZoom: true,
disableDoubleClickZoom: true,
disableTwoFingerTapZoom: true
});
if (circle) {
removeListener();
}
$(document).on('mousemove.measure', function (e) {
onMouseMoveDrag(e, index);
});
$(document).on('mouseup.measure', function () {
onMouseUpDrag(index);
});
};
const onMouseMoveDrag = (e, index) => {
var proj = map.getProjection(),
coord = proj.fromPageXYToCoord(new naver.maps.Point(e.pageX, e.pageY));
if (polyline) {
var polypaths = polyline.getPath()._array;
let movepath = [];
for (let i = 0; i < polypaths.length; i++) {
let path;
if (i === index) {
path = coord;
} else {
path = polypaths[i];
}
movepath.push(path);
}
polyline.setPath(movepath);
} else if (polygon) {
var polygonpaths = polygon.getPath()._array;
let movepath = [];
for (let i = 0; i < polygonpaths.length; i++) {
let path;
if (i === index) {
path = coord;
} else {
path = polygonpaths[i];
}
movepath.push(path);
}
polygon.setPaths(movepath);
} else if (circle) {
var center = circle.getCenter(),
r = proj.getDistance(coord, center);
circle.setRadius(r);
}
if (!circle) {
dragCircle[index].setCenter(coord);
}
};
const onMouseUpDrag = index => {
map.setOptions({
draggable: true,
pinchZoom: true,
scrollWheel: true,
keyboardShortcuts: true,
disableDoubleTapZoom: false,
disableDoubleClickZoom: false,
disableTwoFingerTapZoom: false
});
if (polyline) {
var path = polyline.getPath()._array;
// setPolyline(polyline);
setAreaInfo(path);
setFigure(polyline);
}
if (polygon) {
var path = polygon.getPath()._array;
// setPolygon(polygon);
setAreaInfo(path);
setFigure(polygon);
}
$(document).off('mousemove.measure');
$(document).off('mouseup.measure');
if (circle) {
Eve.clickEve = naver.maps.Event.addListener(map, 'click', function (e) {
onClickCircle(e);
});
setClickEve(Eve.clickEve);
// setCircle(prev => [...prev, circle]);
setAreaInfo('');
setFigure(circle);
}
};
const setAreaInfo = path => {
let bufferZone = 100;
if (polygon) bufferZone = 0;
areaInfo = {
coordinates: [],
bufferZone: bufferZone
};
let prePath = [];
if (path) {
path.forEach(item => {
const p = {
lat: item.y,
lon: item.x
};
prePath.push(p);
});
// path.forEach(prev=> prePath.push([prev.x, prev.y]))
}
if (polyline) {
areaInfo.coordinates = prePath;
areaInfo.areaType = 'LINE';
} else if (polygon) {
areaInfo.coordinates = prePath;
areaInfo.areaType = 'POLYGON';
} else if (circle) {
const point = {
lat: circle.getCenter().y,
lon: circle.getCenter().x
};
areaInfo.coordinates.push(point);
areaInfo.bufferZone = Math.round(circle.getRadius());
areaInfo.areaType = 'CIRCLE';
}
props.handleCoordinates(areaInfo);
};
const createMarker = data => {
distanceMarker.push(
new naver.maps.Marker({
position: data.position,
icon: {
content:
'<div style="display:inline-block;padding:5px;text-align:center;background-color:#fff;border:1px solid #000;font-size:13px;color:' +
data.color +
';"><span>' +
data.content +
'</span></div>',
anchor: data.anchor
},
map: map
})
);
};
const handleDetailDraw = () => {
if (props.areaCoordList) {
const areas = props.areaCoordList[0];
const paths = [];
areas.coordList.forEach(coord => {
const path = new naver.maps.LatLng(coord.lat, coord.lon);
paths.push(path);
});
let clickSet;
{
(isDisabled || isDone) === true
? (clickSet = false)
: (clickSet = true);
}
if (areas.areaType && areas.areaType === 'LINE') {
//polyline 생성
// if (pastPolyline) {
pastPolyline?.setMap(null);
pastDragCircle?.forEach(c => c.setMap(null));
// }
polyline = new naver.maps.Polyline({
strokeLineCap: 'round',
strokeLineJoin: 'round',
strokeColor: '#283046',
strokeWeight: 1,
strokeOpacity: 1,
path: paths,
map: map
});
setPolyline(polyline);
//dragCircle 생성
for (let i = 0; i < paths.length; i++) {
dragCircle.push(
new naver.maps.Circle({
strokestrokeOpacity: 1,
strokeColor: '#000000',
fillColor: '#ffffff',
fillOpacity: 1,
center: paths[i],
map: map,
clickable: clickSet,
...(props.dragSize ? { radius: radiusCircle } : { radius: 140 })
// radius: 17,
// clickable: true
})
);
{
isDisabled || isDone
? {}
: dragCircleEve.push(
naver.maps.Event.addListener(
dragCircle[i],
'mousedown',
function () {
onMouseDownDrag(i);
}
)
);
}
}
setDragCircle(dragCircle);
//bufferline 생성
if (areas.bufferCoordList) {
console.log(areas.bufferCoordList, '>>>');
const bufferPaths = [];
areas.bufferCoordList.forEach(bfCoord => {
const path = new naver.maps.LatLng(bfCoord.lat, bfCoord.lon);
bufferPaths.push(path);
});
if (pastBuffer) {
pastBuffer.setMap(null);
}
bufferPolygon = new naver.maps.Polyline({
strokeColor: '#283046',
strokeOpacity: 1,
strokeStyle: [2, 3],
path: bufferPaths,
map: map
});
setBuffer(bufferPolygon);
}
//marker 생성
if (pastMarker) {
pastMarker.forEach(c => c.setMap(null));
}
for (let i = 0; i < paths.length; i++) {
if (i == 0) {
const data = {};
data.position = paths[i];
data.color = '#ff0000';
data.content = 'Start';
data.anchor = new naver.maps.Point(45, 35);
createMarker(data);
} else {
var proj = map.getProjection(),
r = proj.getDistance(paths[i - 1], paths[i]);
let text = fromMetersToText(r);
let dis1 = paths[i - 1];
let dis2 = paths[i];
let midPoint = new naver.maps.LatLng(
(dis1.y + dis2.y) / 2,
(dis1.x + dis2.x) / 2
);
const data = {};
data.position = midPoint;
data.color = '#737373';
data.content = text;
data.anchor = new naver.maps.Point(20, 35);
createMarker(data);
}
}
setMarker(distanceMarker);
}
if (areas.areaType && areas.areaType === 'POLYGON') {
//polygon 생성
if (pastPolygon) {
pastPolygon.setMap(null);
pastDragCircle.forEach(c => c.setMap(null));
}
polygon = new naver.maps.Polygon({
strokeColor: '#283046',
strokeOpacity: 1,
fillColor: '#8a1c05',
fillOpacity: 0.1,
paths: paths,
map: map
});
setPolygon(polygon);
//dragCircle 생성
for (let i = 0; i < paths.length; i++) {
dragCircle.push(
new naver.maps.Circle({
strokestrokeOpacity: 1,
strokeColor: '#000000',
fillColor: '#ffffff',
fillOpacity: 1,
center: paths[i],
map: map,
clickable: clickSet,
...(props.dragSize ? { radius: radiusCircle } : { radius: 140 })
// radius: 17,
// clickable: true
})
);
{
isDisabled || isDone
? {}
: dragCircleEve.push(
naver.maps.Event.addListener(
dragCircle[i],
'mousedown',
function () {
onMouseDownDrag(i);
}
)
);
}
}
setDragCircle(dragCircle);
//marker 생성
if (pastMarker) {
pastMarker.forEach(c => c.setMap(null));
}
for (let i = 0; i < paths.length + 1; i++) {
//start
if (i == 0) {
const data = {};
data.position = paths[0];
data.color = '#ff0000';
data.content = 'Start';
data.anchor = new naver.maps.Point(45, 35);
createMarker(data);
//첫좌표이자 마지막 좌표
} else if (i == paths.length) {
var proj = map.getProjection(),
r = proj.getDistance(paths[0], paths[i - 1]);
let text = fromMetersToText(r);
let dis1 = paths[0];
let dis2 = paths[i - 1];
let midPoint = new naver.maps.LatLng(
(dis1.y + dis2.y) / 2,
(dis1.x + dis2.x) / 2
);
const data = {};
data.position = midPoint;
data.color = '#737373';
data.content = text;
data.anchor = new naver.maps.Point(0, 35);
createMarker(data);
//그 외 나머지
} else {
var proj = map.getProjection(),
r = proj.getDistance(paths[i - 1], paths[i]);
let text = fromMetersToText(r);
let dis1 = paths[i - 1];
let dis2 = paths[i];
let midPoint = new naver.maps.LatLng(
(dis1.y + dis2.y) / 2,
(dis1.x + dis2.x) / 2
);
const data = {};
data.position = midPoint;
data.color = '#737373';
data.content = text;
anchor: new naver.maps.Point(20, 35);
createMarker(data);
}
}
setMarker(distanceMarker);
}
if (areas.areaType && areas.areaType === 'CIRCLE') {
//circle 생성
if (pastCircle) {
pastCircle.forEach(prev => prev.setMap(null));
}
circle = new naver.maps.Circle({
strokeColor: '#283046',
strokeOpacity: 1,
fillColor: '#8a1c05',
fillOpacity: 0.1,
center: paths[0],
radius: areas.bufferZone,
map: map,
clickable: clickSet
// clickable: true
});
{
isDisabled || isDone
? {}
: (Eve.mousedownEve = naver.maps.Event.addListener(
circle,
'mousedown',
function () {
onMouseDownDrag(0);
}
));
}
setCircle([circle]);
//marker 생성
if (pastMarker) {
pastMarker.forEach(c => c.setMap(null));
}
let text = fromMetersToText(areas.bufferZone);
distanceMarker = new naver.maps.Marker({
position: paths[0],
icon: {
content:
'<div style="display:inline-block;padding:5px;text-align:center;background-color:#fff;border:1px solid #000;font-size:13px;color:#737373;"><span>' +
text +
'</span></div>',
anchor: new naver.maps.Point(-5, -5)
},
map: map
});
setMarker([distanceMarker]);
}
}
};
//div로 보여주기
const addMileStone = (coord, text) => {
let content;
let midPoint;
let anchor;
if (text == 'Start') {
content =
'<div style="display:inline-block;padding:5px;text-align:center;background-color:#fff;border:1px solid #000;font-size:13px;color:#ff0000;"><span>' +
text +
'</span></div>';
midPoint = coord;
anchor = new naver.maps.Point(45, 35);
} else {
content =
'<div style="display:inline-block;padding:5px;text-align:center;background-color:#fff;border:1px solid #000;font-size:13px;color:#ff0000;"><span>' +
text +
'</span></div>';
let dis1 = coord[coord.length - 2];
let dis2 = coord[coord.length - 1];
if (circle) {
midPoint = coord;
} else {
midPoint = new naver.maps.LatLng(
(dis1.y + dis2.y) / 2,
(dis1.x + dis2.x) / 2
);
}
anchor = new naver.maps.Point(20, 35);
}
var marker = new naver.maps.Marker({
position: midPoint,
icon: {
content: content,
anchor: anchor
}
// map: map
});
// marker.setVisible(false)
if (circle) {
distanceMarker = marker;
} else {
marker.setMap(map);
distanceMarker.push(marker);
}
};
//거리 재기
const fromMetersToText = meters => {
meters = meters || 0;
let text = parseFloat(meters.toFixed(1)) + 'm';
return text;
};
return <InfoModal modal={alertModal} setModal={setAlertModal} />;
};

683
src/components/map/naver/draw/FlightPlanDraw_JQuery.js

@ -1,683 +0,0 @@
import $ from 'jquery';
import '../../../../assets/css/custom.css';
import { CustomInput } from 'reactstrap';
import buffer from '@turf/buffer';
export const FlightPlanDraw = props => {
const { naver } = props;
const { map } = props;
var Measure = function (buttons) {
this.$btnLine = buttons.line;
this.$btnPolygon = buttons.polygon;
this.$btnCircle = buttons.circle;
this.$btnRectangle = buttons.rectangle;
this._mode = null;
this._bindDOMEvents();
};
$.extend(Measure.prototype, {
constructor: Measure,
setMap: function (map) {
if (this.map) {
this._unbindMap(this.map);
}
this.map = map;
if (map) {
this._bindMap(map);
}
},
startMode: function (mode) {
if (!mode) return;
if (mode === 'line') {
this._startDistance();
}
if (mode === 'polygon') {
this._startArea();
}
if (mode === 'circle') {
this._startCircle();
}
if (mode === 'rectangle') {
this._startRectangle();
}
},
_startDistance: function () {
var map = this.map;
this._distanceListeners = [
naver.maps.Event.addListener(
map,
'click',
this._onClickDistance.bind(this)
)
];
},
_startArea: function () {
var map = this.map;
this._areaListeners = [
naver.maps.Event.addListener(
map,
'click',
this._onClickArea.bind(this)
),
naver.maps.Event.addListener(
map,
'rightclick',
this._finishArea.bind(this)
)
];
$(document).on('mousemove.measure', this._onMouseMoveArea.bind(this));
},
_startCircle: function () {
var map = this.map;
this._circleListeners = [
naver.maps.Event.addListener(
map,
'click',
this._onClickCircle.bind(this)
),
naver.maps.Event.addListener(
map,
'rightclick',
this._finishCircle.bind(this)
)
];
},
_startRectangle: function () {
var map = this.map;
this._rectangleListeners = [
naver.maps.Event.addListener(
map,
'click',
this._onClickRectangle.bind(this)
),
naver.maps.Event.addListener(
map,
'rightclick',
this._finishRectangle.bind(this)
)
];
},
_finishDistance: function () {
naver.maps.Event.removeListener(this._distanceListeners);
delete this._distanceListeners;
$(document).off('mousemove.measure');
if (this._guideline) {
this._guideline.setMap(null);
delete this._guideline;
}
if (this._polyline) {
let polypaths = this._polyline.getPath()._array;
//파싱
let polypathJSON = new Array();
for (let i = 0; i < polypaths.length; i++) {
//파싱
let obj = new Object();
obj.x = '' + polypaths[i]._lng + '';
obj.y = '' + polypaths[i]._lat + '';
obj = JSON.stringify(obj);
polypathJSON.push(JSON.parse(obj));
}
//버퍼 생성에 필요한 coordinates 배열 변환
let lineStringPaths = [];
for (let i = 0; i < this._polyline.getPath().length; i++) {
lineStringPaths.push([
this._polyline.getPath()._array[i].x,
this._polyline.getPath()._array[i].y
]);
}
//버퍼 생성을 위한 line 객체
const originalGeojson = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {},
geometry: {
type: 'LineString',
coordinates: lineStringPaths
}
}
]
};
//버퍼 객체
const bufferObj = buffer(originalGeojson, 50, { units: 'meters' });
//버퍼 라인 생성
let bufferPath = bufferObj.features[0].geometry.coordinates[0];
this.bufferPolyline = new naver.maps.Polyline({
strokeColor: '#ff0000',
strokeWeight: 2,
strokeStyle: [4, 4],
strokeOpacity: 0.6,
path: bufferPath,
map: map
});
// 이거 하면 그동안 한거 싹 사라짐 -> 얘를 통해서 drawType이 바뀌면 다 날라가는 걸로 해보면 될듯
// this._polyline.setMap(null)
delete this._polyline;
}
//onfocus()의 반대기능 = blur()
this.$btnLine.removeClass('control-on').blur();
this._mode = null;
},
_finishArea: function () {
naver.maps.Event.removeListener(this._areaListeners);
delete this._areaListeners;
$(document).off('mousemove.measure');
if (this._polygon) {
var path = this._polygon.getPath();
path.pop();
delete this._polygon;
}
this.$btnPolygon.removeClass('control-on').blur();
this._mode = null;
},
_finishCircle: function () {
naver.maps.Event.removeListener(this._circleListeners);
delete this._circleListeners;
$(document).off('mousemove.measure');
if (this._guidecircle) {
this._guidecircle.setMap(null);
this._radius.setMap(null);
delete this._raidus;
delete this._guidecircle;
}
if (this._circle) {
delete this._circle;
}
this.$btnCircle.removeClass('control-on').blur();
// delete this._lastDistance;
this._mode = null;
},
_finishRectangle: function () {
naver.maps.Event.removeListener(this._rectangleListeners);
delete this._rectangleListeners;
$(document).off('mousemove.measure');
if (this._rectangle) {
this._guiderectangle.setMap(null);
delete this._guiderectangle;
}
this.$btnRectangle.removeClass('control-on').blur();
this._mode = null;
},
finishMode: function (mode) {
if (!mode) return;
if (mode === 'line') {
this._finishDistance();
}
if (mode === 'polygon') {
this._finishArea();
}
if (mode === 'circle') {
this._finishCircle();
}
if (mode === 'rectangle') {
this._finishRectangle();
}
},
_fromMetersToText: function (meters) {
meters = meters || 0;
var km = 1000,
text = meters;
if (meters >= km) {
text = parseFloat((meters / km).toFixed(1)) + 'km';
} else {
text = parseFloat(meters.toFixed(1)) + 'm';
}
return text;
},
_addMileStone: function (coord, text, css) {
if (!this._ms) this._ms = [];
let content;
if (text == 'Start') {
content =
'<div style="display:inline-block;padding:5px;text-align:center;background-color:#fff;border:1px solid #000;font-size:14px;color:#ff0000;"><span>' +
text +
'</span></div>';
} else {
content =
'<div style="display:inline-block;padding:5px;text-align:center;background-color:#fff;border:1px solid #000;color:#737373;"><span>' +
text +
'</span></div>';
}
var ms = new naver.maps.Marker({
position: coord,
icon: {
content: content,
anchor: new naver.maps.Point(-5, -5)
},
map: this.map
});
var msElement = $(ms.getElement());
if (css) {
msElement.css(css);
} else {
msElement.css('font-size', '13px');
}
this._ms.push(ms);
},
_onClickDistance: function (e) {
var map = this.map,
coord = e.coord;
if (!this._polyline) {
// 임시로 보여줄 점선 폴리라인을 생성합니다.
this._guideline = new naver.maps.Polyline({
strokeColor: '#0000ff',
strokeWeight: 3,
strokeStyle: [4, 4],
strokeOpacity: 0.2,
path: [coord],
map: map
});
// this._lastDistance = this._guideline.getDistance();
$(document).on(
'mousemove.measure',
this._onMouseMoveDistance.bind(this)
);
this._distanceListeners.push(
naver.maps.Event.addListener(
map,
'rightclick',
this._finishDistance.bind(this)
)
);
// 실제 거리재기에 사용되는 폴리라인을 생성합니다.
this._polyline = new naver.maps.Polyline({
strokeLineCap: 'round',
strokeLineJoin: 'round',
strokeColor: '#0000ff',
strokeWeight: 3,
strokeOpacity: 0.6,
path: [coord],
map: map
});
this._lastDistance = this._polyline.getDistance();
this._addMileStone(coord, 'Start');
} else {
this._guideline.setPath([e.coord]);
this._polyline.getPath().push(coord);
var distance = this._polyline.getDistance();
this._addMileStone(
coord,
this._fromMetersToText(distance - this._lastDistance)
);
this._lastDistance = distance;
}
},
_onMouseMoveDistance: function (e) {
var map = this.map,
proj = this.map.getProjection(),
coord = proj.fromPageXYToCoord(new naver.maps.Point(e.pageX, e.pageY)),
path = this._guideline.getPath();
if (path.getLength() === 2) {
//맨 뒷 값 삭제 = 기존클릭좌표만 남겨둬라 = 실시간으로 좌표들어가야 하니까
path.pop();
}
// [기존 클릭 좌표, 실시간 좌표]
path.push(coord);
},
_onClickArea: function (e) {
var map = this.map,
coord = e.coord;
if (!this._polygon) {
this._polygon = new naver.maps.Polygon({
strokeOpacity: 0.8,
fillColor: '#0000ff',
fillOpacity: 0.1,
paths: [coord],
map: map
});
} else {
this._polygon.getPath().push(coord);
}
},
_onMouseMoveArea: function (e) {
if (!this._polygon) return;
var map = this.map,
proj = this.map.getProjection(),
coord = proj.fromPageXYToCoord(new naver.maps.Point(e.pageX, e.pageY)),
path = this._polygon.getPath();
if (path.getLength() >= 2) {
path.pop();
}
path.push(coord);
},
_onClickCircle: function (e) {
var map = this.map,
coord = e.coord;
if (!this._circle) {
//가이드 라인
this._radius = new naver.maps.Polyline({
strokeStyle: [4, 4],
strokeOpacity: 0.6,
path: [coord],
map: map
});
this._lastDistance = this._radius.getDistance();
// 임시로 보여줄 원형
this._guidecircle = new naver.maps.Circle({
strokeOpacity: 0.8,
strokeStyle: [4, 4],
fillColor: '#0000ff',
fillOpacity: 0.1,
center: coord,
radius: this._lastDistance,
map: map
});
$(document).on('mousemove.measure', this._onMouseMoveCircle.bind(this));
this._circleListeners.push(
naver.maps.Event.addListener(
map,
'rightclick',
this._finishCircle.bind(this)
)
);
// 실제 사용되는 원형
this._circle = new naver.maps.Circle({
strokeOpacity: 0.8,
fillColor: '#0000ff',
fillOpacity: 0.1,
center: coord,
radius: this._lastDistance,
map: map
});
} else {
// this._guidecircle.setCenter(e.coord);
// this._circle.setCenter(coord);
// if(this._radius.getPath().length() === 2) {
// this._radius.getPath().pop();
// }
// this._radius.getPath().push(coord);
var distance = this._radius.getDistance();
this._lastDistance = distance;
this._circle.setRadius(this._lastDistance);
}
},
_onMouseMoveCircle: function (e) {
if (!this._circle) return;
var map = this.map,
proj = this.map.getProjection(),
coord = proj.fromPageXYToCoord(new naver.maps.Point(e.pageX, e.pageY)),
path = this._radius.getPath(),
center = this._guidecircle.getCenter(), //LatLng으로 나옴
r = proj.getDistance(coord, center);
if (path.getLength() === 2) {
path.pop();
}
path.push(coord);
this._guidecircle.setRadius(r);
},
_onClickRectangle: function (e) {
var map = this.map,
coord = e.coord;
this.max_x = 0;
this.max_y = 0;
if (!this._rectangle) {
//min = 고정값
this.fixed = coord;
this.min = [this.fixed.x, this.fixed.y];
this.max = [this.max_x, this.max_y];
this.boundscoord = [this.min[0], this.min[1], this.min[0], this.min[1]];
// 임시로 보여줄 사각형
this._guiderectangle = new naver.maps.Rectangle({
strokeStyle: [4, 4],
strokeOpacity: 0.6,
bounds: this.boundscoord,
map: map
});
$(document).on(
'mousemove.measure',
this._onMouseMoveRectangle.bind(this)
);
this._rectangleListeners.push(
naver.maps.Event.addListener(
map,
'rightclick',
this._finishRectangle.bind(this)
)
);
//실제 사용되는 사각형
this._rectangle = new naver.maps.Rectangle({
strokeOpacity: 0.8,
fillColor: '#0000ff',
fillOpacity: 0.1,
bounds: this.boundscoord,
map: map
});
} else {
this.max = [coord.x, coord.y];
this.boundscoord = [this.min[0], this.min[1], this.max[0], this.max[1]];
this._rectangle.setBounds(this.boundscoord);
}
},
_onMouseMoveRectangle: function (e) {
if (!this._rectangle) return;
var map = this.map,
proj = this.map.getProjection(),
coord = proj.fromPageXYToCoord(new naver.maps.Point(e.pageX, e.pageY)),
bounds = this._guiderectangle.getBounds(),
max = [coord.x, coord.y];
this.boundscoord = [this.min[0], this.min[1], max[0], max[1]];
this._guiderectangle.setBounds(this.boundscoord);
},
_bindMap: function (map) {},
_unbindMap: function () {
this.unbindAll();
},
_bindDOMEvents: function () {
this.$btnLine.on('click.measure', this._onClickButton.bind(this, 'line'));
this.$btnPolygon.on(
'click.measure',
this._onClickButton.bind(this, 'polygon')
);
this.$btnCircle.on(
'click.measure',
this._onClickButton.bind(this, 'circle')
);
this.$btnRectangle.on(
'click.measure',
this._onClickButton.bind(this, 'rectangle')
);
},
_onClickButton: function (newMode, e) {
//newMode는 방금 클릭한 값(line, polygon, circle...)
e.preventDefault();
var btn = $(e.target),
map = this.map,
mode = this._mode;
//this._mode는 클릭하기 전 값(첫 클릭이면 null)
if (btn.hasClass('control-on')) {
btn.removeClass('control-on');
} else {
btn.addClass('control-on');
}
this._clearMode(mode);
if (mode === newMode) {
this._mode = null;
return;
}
this._mode = newMode;
this.startMode(newMode);
},
_clearMode: function (mode) {
if (!mode) return;
if (mode === 'line') {
if (this._polyline) {
this._polyline.setMap(null);
delete this._polyline;
}
this._finishDistance();
} else if (mode === 'polygon') {
if (this._polygon) {
this._polygon.setMap(null);
delete this._polygon;
}
this._finishArea();
} else if (mode === 'circle') {
if (this._circle) {
this._circle.setMap(null);
delete this._circle;
}
this._finishCircle();
} else if (mode === 'rectangle') {
if (this._rectangle) {
this._rectangle.setMap(null);
delete this._rectangle;
}
}
}
});
// id랑 매치시켜서 옵션 지정함
var measures = new Measure({
line: $('#line'),
polygon: $('#polygon'),
circle: $('#circle'),
rectangle: $('#rectangle')
});
measures.setMap(map);
return (
<>
<div style={{ position: 'relative' }}>
<ul className='measure-control'>
<li>
<CustomInput
id='line'
type='image'
className='control-btn'
src='http://static.naver.net/maps/mantle/drawing/1x/polyline.png'
/>
<CustomInput
id='polygon'
type='image'
className='control-btn'
src='http://static.naver.net/maps/mantle/drawing/1x/polygon.png'
/>
<CustomInput
id='circle'
type='image'
className='control-btn'
src='http://static.naver.net/maps/mantle/drawing/1x/ellipse.png'
/>
<CustomInput
id='rectangle'
type='image'
className='control-btn'
src='http://static.naver.net/maps/mantle/drawing/1x/rectangle.png'
/>
</li>
</ul>
</div>
</>
);
};

971
src/components/map/naver/draw/FlightPlanDraw_Test.js

@ -1,971 +0,0 @@
import $ from 'jquery';
import { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import * as Actions from '../../../../modules/basis/flight/actions/basisFlightAction';
import { InfoModal } from '../../../modal/InfoModal';
export const FlightPlanDraw = props => {
const dispatch = useDispatch();
const mapControl = useSelector(state => state.controlMapReducer);
const [pastPolyline, setPolyline] = useState();
const [pastBuffer, setBuffer] = useState();
const [pastPolygon, setPolygon] = useState();
const [pastCircle, setCircle] = useState([]);
const [pastDragCircle, setDragCircle] = useState([]);
const [pastClickEve, setClickEve] = useState();
const [pastMarker, setMarker] = useState([]);
const [figure, setFigure] = useState();
const [areaDetail, setAreaDetail] = useState();
const [alertModal, setAlertModal] = useState({
isOpen: false,
title: '',
desc: ''
});
const naver = props.naver;
const map = props.map;
let mode = props.mode;
let dragCircleSize = props.dragCircleSize;
let areaInfo;
let lastDistance;
let polyline;
let guideline;
let bufferPolygon;
let polygon;
let circle;
let radiusline;
let Eve = {
clickEve: '',
mousedownEve: '',
rightclickEve: ''
};
let dragCircle = [];
let dragCircleEve = [];
let distanceMarker = [];
const handleBufferList = () => {
dispatch(Actions.FLIGHT_PLAN_AREA_BUFFER_LIST.request(areaDetail));
};
useEffect(() => {
drawInit();
}, [mapControl.drawType]);
useEffect(() => {
handleDetailDraw();
}, [props.areaCoordList]);
useEffect(() => {
if (figure) {
props.handleConfirm(props.areaCoordList);
setAreaDetail(props.areaCoordList);
}
}, [figure]);
useEffect(() => {
if (pastPolyline) {
handleBufferList();
}
}, [areaDetail]);
const drawInit = () => {
if (mapControl.drawType === 'LINE') {
onClickButton('LINE');
} else if (mapControl.drawType === 'CIRCLE') {
onClickButton('CIRCLE');
} else if (mapControl.drawType === 'POLYGON') {
onClickButton('POLYGON');
} else if (mapControl.drawType === 'RESET') {
onClickReset('RESET');
}
};
const onClickButton = newMode => {
clearMode(mode);
if (mode === newMode) {
mode = null;
return;
}
// mode = newMode;
startMode(newMode);
};
const clearMode = mode => {
// if(!mode) return;
if (pastPolyline) {
pastPolyline.setMap(null);
pastDragCircle.forEach(c => c.setMap(null));
pastBuffer.setMap(null);
setPolyline();
setDragCircle([]);
setBuffer();
}
if (pastCircle.length != 0) {
pastCircle.forEach(prev => prev.setMap(null));
naver.maps.Event.removeListener(pastClickEve);
setCircle([]);
}
if (pastPolygon) {
pastPolygon.setMap(null);
pastDragCircle.forEach(c => c.setMap(null));
setPolygon();
setDragCircle([]);
}
if (pastMarker.length != 0) {
pastMarker.forEach(m => m.setMap(null));
setMarker([]);
}
finishDraw();
props.handleInitCoordinates();
};
const startMode = mode => {
if (!mode) return;
if (pastClickEve) {
naver.maps.Event.removeListener(pastClickEve);
}
if (mode === 'LINE') {
Eve.clickEve = naver.maps.Event.addListener(map, 'click', function (e) {
onClickPolyline(e);
});
setClickEve(Eve.clickEve);
} else if (mode === 'POLYGON') {
Eve.clickEve = naver.maps.Event.addListener(map, 'click', function (e) {
onClickPolygon(e);
});
setClickEve(Eve.clickEve);
} else if (mode === 'CIRCLE') {
Eve.clickEve = naver.maps.Event.addListener(map, 'click', function (e) {
onClickCircle(e);
});
setClickEve(Eve.clickEve);
}
};
const removeListener = () => {
naver.maps.Event.removeListener(Eve.clickEve);
naver.maps.Event.removeListener(pastClickEve);
setClickEve();
naver.maps.Event.removeListener(Eve.mousedownEve);
naver.maps.Event.removeListener(Eve.rightclickEve);
if (!circle) $(document).off('mousemove.measure');
};
const finishDraw = () => {
removeListener();
if (polyline) {
if (guideline) {
guideline.setMap(null);
guideline = '';
}
let polypaths = polyline.getPath()._array;
setMarker(distanceMarker);
distanceMarker.forEach(c => c.setMap(null));
if (polypaths.length >= 2) {
setPolyline(polyline);
setAreaInfo(polypaths);
} else {
setAlertModal({
isOpen: true,
title: '좌표 최소 개수',
desc: '좌표를 두 개 점으로 이어주세요.'
});
polyline.setMap(null);
polyline = '';
}
setFigure(polyline);
} else if (polygon) {
let path = polygon.getPath();
path.pop();
let polygonpaths = polygon.getPath()._array;
//마지막 path와 시작점을 이어주는 라인 생성
lastDistance = guideline.getDistance();
guideline.getPath().push(polygonpaths[0]);
var distance = guideline.getDistance();
// addMileStone(polygonpaths[0], fromMetersToText(distance - lastDistance));
setMarker(distanceMarker);
distanceMarker.forEach(c => c.setMap(null));
if (polygonpaths.length >= 3) {
setPolygon(polygon);
setAreaInfo(polygonpaths);
} else {
setAlertModal({
isOpen: true,
title: '좌표 최소 개수',
desc: '좌표를 세 개 점으로 이어주세요.'
});
polygon.setMap(null);
polygon = '';
}
setFigure(polygon);
}
};
const onClickPolyline = e => {
var coord = e.coord;
if (!polyline) {
//가이드라인
guideline = new naver.maps.Polyline({
strokeColor: '#283046',
strokeWeight: 2,
strokeOpacity: 0.3,
path: [coord],
map: map
});
// lastDistance = guideline.getDistance();
//실제 사용되는 라인
polyline = new naver.maps.Polyline({
strokeLineCap: 'round',
strokeLineJoin: 'round',
strokeColor: '#283046',
// strokeColor: '#ff0000',
strokeWeight: 1,
strokeOpacity: 1,
path: [coord],
map: map
});
Eve.rightclickEve = naver.maps.Event.addListener(
map,
'rightclick',
function () {
finishDraw();
}
);
$(document).on('mousemove.measure', function (e) {
onMouseMovePolyline(e);
});
lastDistance = polyline.getDistance();
addMileStone(coord, 'Start');
} else {
guideline.setPath([e.coord]);
polyline.getPath().push(coord);
var distance = polyline.getDistance();
// addMileStone(coord, fromMetersToText(distance - lastDistance));
addMileStone(
polyline.getPath()._array,
fromMetersToText(distance - lastDistance)
);
lastDistance = distance;
}
};
const onMouseMovePolyline = e => {
var proj = map.getProjection(),
coord = proj.fromPageXYToCoord(new naver.maps.Point(e.pageX, e.pageY)),
path = guideline.getPath();
if (path.getLength() === 2) {
path.pop();
}
path.push(coord);
};
const onClickPolygon = e => {
var coord = e.coord;
// let guide;
if (!polygon) {
polygon = new naver.maps.Polygon({
strokeColor: '#283046',
strokeOpacity: 1,
fillColor: '#8a1c05',
fillOpacity: 0.1,
paths: [coord],
map: map
});
//거리재기를 위한 가이드
guideline = new naver.maps.Polyline({
path: [coord],
map: map
});
guideline.setVisible(false);
Eve.rightclickEve = naver.maps.Event.addListener(
map,
'rightclick',
function () {
finishDraw();
}
);
$(document).on('mousemove.measure', function (e) {
onMouseMovePolygon(e);
});
lastDistance = guideline.getDistance();
addMileStone(coord, 'Start');
} else {
polygon.getPath().push(coord);
guideline.getPath().push(coord);
var distance = guideline.getDistance();
// addMileStone(coord, fromMetersToText(distance - lastDistance));
addMileStone(
guideline.getPath()._array,
fromMetersToText(distance - lastDistance)
);
lastDistance = distance;
}
};
const onMouseMovePolygon = e => {
if (!polygon) return;
var proj = map.getProjection(),
coord = proj.fromPageXYToCoord(new naver.maps.Point(e.pageX, e.pageY)),
path = polygon.getPath();
if (path.getLength() >= 2) {
path.pop();
}
path.push(coord);
};
const onClickCircle = e => {
var coord = e.coord;
if (!circle) {
radiusline = new naver.maps.Polyline({
strokeStyle: [4, 4],
strokeOpacity: 0.6,
path: [coord]
// map: map
});
lastDistance = radiusline.getDistance();
circle = new naver.maps.Circle({
strokeColor: '#283046',
strokeOpacity: 1,
fillColor: '#8a1c05',
fillOpacity: 0.1,
center: coord,
radius: 100,
map: map,
clickable: true
});
Eve.mousedownEve = naver.maps.Event.addListener(
circle,
'mousedown',
function () {
onMouseDownDrag(0);
}
);
addMileStone(coord, fromMetersToText(100));
} else {
circle.setCenter(coord);
circle.setRadius(100);
distanceMarker.setPosition(coord);
}
setCircle(prev => [...prev, circle]);
setAreaInfo('');
setMarker(distanceMarker);
setFigure(circle.center);
};
const onMouseDownDrag = index => {
map.setOptions({
draggable: false,
pinchZoom: false,
scrollWheel: false,
keyboardShortcuts: false,
disableDoubleTapZoom: true,
disableDoubleClickZoom: true,
disableTwoFingerTapZoom: true
});
if (circle) {
removeListener();
}
$(document).on('mousemove.measure', function (e) {
onMouseMoveDrag(e, index);
});
$(document).on('mouseup.measure', function () {
onMouseUpDrag(index);
});
};
const onMouseMoveDrag = (e, index) => {
var proj = map.getProjection(),
coord = proj.fromPageXYToCoord(new naver.maps.Point(e.pageX, e.pageY));
if (polyline) {
var polypaths = polyline.getPath()._array;
let movepath = [];
for (let i = 0; i < polypaths.length; i++) {
let path;
if (i === index) {
path = coord;
} else {
path = polypaths[i];
}
movepath.push(path);
}
polyline.setPath(movepath);
} else if (polygon) {
var polygonpaths = polygon.getPath()._array;
let movepath = [];
for (let i = 0; i < polygonpaths.length; i++) {
let path;
if (i === index) {
path = coord;
} else {
path = polygonpaths[i];
}
movepath.push(path);
}
polygon.setPaths(movepath);
} else if (circle) {
var center = circle.getCenter(),
r = proj.getDistance(coord, center);
circle.setRadius(r);
}
if (!circle) {
dragCircle[index].setCenter(coord);
}
};
const onMouseUpDrag = index => {
map.setOptions({
draggable: true,
pinchZoom: true,
scrollWheel: true,
keyboardShortcuts: true,
disableDoubleTapZoom: false,
disableDoubleClickZoom: false,
disableTwoFingerTapZoom: false
});
if (polyline) {
var path = polyline.getPath()._array;
setPolyline(polyline);
setAreaInfo(path);
setFigure(polyline);
}
if (polygon) {
var path = polygon.getPath()._array;
setPolygon(polygon);
setAreaInfo(path);
setFigure(polygon);
// if(pastMarker.length !=0) {
// //마커 위치 변경
// pastMarker[index].setPosition(path[index]);
// //마커 content 변경
// if(index == 0) {
// //시작 지점 이동
// pastMarker[index].setIcon({
// content: '<div style="display:inline-block;padding:5px;text-align:center;background-color:#fff;border:1px solid #000;font-size:13px;color:#ff0000;"><span>'+ 'Start' +'</span></div>',
// anchor: new naver.maps.Point(-5, -5)
// })
// } else {
// let isLastIndex;
// if(pastMarker.length === index+1) {
// //종료 지점 이동(index 마커만 변경)
// isLastIndex = 1;
// } else {
// //사이 지점 이동(index+1 마커도 변경)
// isLastIndex = 2;
// }
// for(let i = index; i < index+isLastIndex; i++) {
// var proj = map.getProjection(),
// r = proj.getDistance(pastMarker[i-1].position, pastMarker[i].position);
// let text = fromMetersToText(r);
// pastMarker[i].setIcon({
// content: '<div style="display:inline-block;padding:5px;text-align:center;background-color:#fff;border:1px solid #000;font-size:13px;color:#737373;"><span>'+ text +'</span></div>',
// anchor: new naver.maps.Point(-5, -5)
// })
// }
// }
// }
}
$(document).off('mousemove.measure');
$(document).off('mouseup.measure');
if (circle) {
Eve.clickEve = naver.maps.Event.addListener(map, 'click', function (e) {
onClickCircle(e);
});
setClickEve(Eve.clickEve);
setCircle(prev => [...prev, circle]);
setAreaInfo('');
setFigure(circle);
}
};
const setAreaInfo = path => {
let bufferZone = 100;
if (polygon) bufferZone = 0;
areaInfo = {
coordinates: [],
bufferZone: bufferZone
};
let prePath = [];
if (path) {
path.forEach(item => {
const p = {
lat: item.y,
lon: item.x
};
prePath.push(p);
});
// path.forEach(prev=> prePath.push([prev.x, prev.y]))
}
if (polyline) {
areaInfo.coordinates = prePath;
areaInfo.areaType = 'LINE';
} else if (polygon) {
areaInfo.coordinates = prePath;
areaInfo.areaType = 'POLYGON';
} else if (circle) {
const point = {
lat: circle.getCenter().y,
lon: circle.getCenter().x
};
areaInfo.coordinates.push(point);
areaInfo.bufferZone = circle.getRadius();
areaInfo.areaType = 'CIRCLE';
}
props.handleCoordinates(areaInfo);
};
const onClickReset = () => {
if (mapControl.drawType === 'RESET') {
clearMode('RESET');
}
};
const handleDetailDraw = () => {
if (props.areaCoordList) {
const areas = props.areaCoordList[0];
const paths = [];
areas.coordList.forEach(coord => {
const path = new naver.maps.LatLng(coord.lat, coord.lon);
paths.push(path);
});
if (areas.areaType && areas.areaType === 'LINE') {
//polyline 생성
if (pastPolyline) {
pastPolyline.setMap(null);
pastDragCircle.forEach(c => c.setMap(null));
}
polyline = new naver.maps.Polyline({
strokeLineCap: 'round',
strokeLineJoin: 'round',
strokeColor: '#283046',
strokeWeight: 1,
strokeOpacity: 1,
path: paths,
map: map
});
setPolyline(polyline);
//dragCircle 생성
for (let i = 0; i < paths.length; i++) {
dragCircle.push(
new naver.maps.Circle({
strokestrokeOpacity: 1,
strokeColor: '#000000',
fillColor: '#ffffff',
fillOpacity: 1,
center: paths[i],
radius: 17,
// radius: dragCircleSize,
map: map,
clickable: true
})
);
dragCircleEve.push(
naver.maps.Event.addListener(
dragCircle[i],
'mousedown',
function () {
onMouseDownDrag(i);
}
)
);
}
setDragCircle(dragCircle);
//bufferline 생성
if (areas.bufferCoordList) {
const bufferPaths = [];
areas.bufferCoordList.forEach(bfCoord => {
const path = new naver.maps.LatLng(bfCoord.lat, bfCoord.lon);
bufferPaths.push(path);
});
if (pastBuffer) {
pastBuffer.setMap(null);
}
bufferPolygon = new naver.maps.Polyline({
strokeColor: '#283046',
strokeOpacity: 1,
strokeStyle: [2, 3],
path: bufferPaths,
map: map
});
setBuffer(bufferPolygon);
}
//marker 생성
if (pastMarker) {
pastMarker.forEach(c => c.setMap(null));
}
for (let i = 0; i < paths.length; i++) {
if (i == 0) {
distanceMarker.push(
new naver.maps.Marker({
position: paths[i],
icon: {
content:
'<div style="display:inline-block;padding:5px;text-align:center;background-color:#fff;border:1px solid #000;font-size:13px;color:#ff0000;"><span>' +
'Start' +
'</span></div>',
anchor: new naver.maps.Point(45, 35)
},
map: map
})
);
} else {
var proj = map.getProjection(),
r = proj.getDistance(paths[i - 1], paths[i]);
let text = fromMetersToText(r);
let dis1 = paths[i - 1];
let dis2 = paths[i];
let midPoint = new naver.maps.LatLng(
(dis1.y + dis2.y) / 2,
(dis1.x + dis2.x) / 2
);
distanceMarker.push(
new naver.maps.Marker({
// position: paths[i],
position: midPoint,
icon: {
content:
'<div style="display:inline-block;padding:5px;text-align:center;background-color:#fff;border:1px solid #000;font-size:13px;color:#737373;"><span>' +
text +
'</span></div>',
anchor: new naver.maps.Point(20, 35)
},
map: map
})
);
}
}
setMarker(distanceMarker);
}
if (areas.areaType && areas.areaType === 'POLYGON') {
//polygon 생성
if (pastPolygon) {
pastPolygon.setMap(null);
pastDragCircle.forEach(c => c.setMap(null));
}
polygon = new naver.maps.Polygon({
strokeColor: '#283046',
strokeOpacity: 1,
fillColor: '#8a1c05',
fillOpacity: 0.1,
paths: paths,
map: map
});
setPolygon(polygon);
//dragCircle 생성
for (let i = 0; i < paths.length; i++) {
dragCircle.push(
new naver.maps.Circle({
strokestrokeOpacity: 1,
strokeColor: '#000000',
fillColor: '#ffffff',
fillOpacity: 1,
center: paths[i],
radius: 15,
// radius: dragCircleSize,
map: map,
clickable: true
})
);
dragCircleEve.push(
naver.maps.Event.addListener(
dragCircle[i],
'mousedown',
function () {
onMouseDownDrag(i);
}
)
);
}
setDragCircle(dragCircle);
//marker 생성
if (pastMarker) {
pastMarker.forEach(c => c.setMap(null));
}
for (let i = 0; i < paths.length + 1; i++) {
//start
if (i == 0) {
distanceMarker.push(
new naver.maps.Marker({
position: paths[0],
icon: {
content:
'<div style="display:inline-block;padding:5px;text-align:center;background-color:#fff;border:1px solid #000;font-size:13px;color:#ff0000;"><span>' +
'Start' +
'</span></div>',
anchor: new naver.maps.Point(45, 35)
},
map: map
})
);
//첫좌표이자 마지막 좌표
} else if (i == paths.length) {
var proj = map.getProjection(),
r = proj.getDistance(paths[0], paths[i - 1]);
let text = fromMetersToText(r);
let dis1 = paths[0];
let dis2 = paths[i - 1];
let midPoint = new naver.maps.LatLng(
(dis1.y + dis2.y) / 2,
(dis1.x + dis2.x) / 2
);
distanceMarker.push(
new naver.maps.Marker({
// position: paths[0],
position: midPoint,
icon: {
content:
'<div style="display:inline-block;padding:5px;text-align:center;background-color:#fff;border:1px solid #000;font-size:13px;color:#737373;"><span>' +
text +
'</span></div>',
anchor: new naver.maps.Point(0, 35)
},
map: map
})
);
//그 외 나머지
} else {
var proj = map.getProjection(),
r = proj.getDistance(paths[i - 1], paths[i]);
let text = fromMetersToText(r);
let dis1 = paths[i - 1];
let dis2 = paths[i];
let midPoint = new naver.maps.LatLng(
(dis1.y + dis2.y) / 2,
(dis1.x + dis2.x) / 2
);
distanceMarker.push(
new naver.maps.Marker({
// position: paths[i],
position: midPoint,
icon: {
content:
'<div style="display:inline-block;padding:5px;text-align:center;background-color:#fff;border:1px solid #000;font-size:13px;color:#737373;"><span>' +
text +
'</span></div>',
anchor: new naver.maps.Point(20, 35)
},
map: map
})
);
}
}
setMarker(distanceMarker);
}
if (areas.areaType && areas.areaType === 'CIRCLE') {
//circle 생성
if (pastCircle) {
pastCircle.forEach(prev => prev.setMap(null));
}
circle = new naver.maps.Circle({
strokeColor: '#283046',
strokeOpacity: 1,
// fillColor: '#ff0000',
fillColor: '#8a1c05',
fillOpacity: 0.1,
center: paths[0],
radius: areas.bufferZone,
map: map,
clickable: true
});
Eve.mousedownEve = naver.maps.Event.addListener(
circle,
'mousedown',
function () {
onMouseDownDrag(0);
}
);
setCircle([circle]);
//marker 생성
if (pastMarker) {
pastMarker.forEach(c => c.setMap(null));
}
let text = fromMetersToText(areas.bufferZone);
distanceMarker = new naver.maps.Marker({
position: paths[0],
icon: {
content:
'<div style="display:inline-block;padding:5px;text-align:center;background-color:#fff;border:1px solid #000;font-size:13px;color:#737373;"><span>' +
text +
'</span></div>',
anchor: new naver.maps.Point(-5, -5)
},
map: map
});
setMarker([distanceMarker]);
}
}
};
//div로 보여주기
const addMileStone = (coord, text) => {
let content;
let midPoint;
let anchor;
if (text == 'Start') {
content =
'<div style="display:inline-block;padding:5px;text-align:center;background-color:#fff;border:1px solid #000;font-size:13px;color:#ff0000;"><span>' +
text +
'</span></div>';
midPoint = coord;
anchor = new naver.maps.Point(45, 35);
} else {
content =
'<div style="display:inline-block;padding:5px;text-align:center;background-color:#fff;border:1px solid #000;font-size:13px;color:#ff0000;"><span>' +
text +
'</span></div>';
let dis1 = coord[coord.length - 2];
let dis2 = coord[coord.length - 1];
if (circle) {
midPoint = coord;
} else {
midPoint = new naver.maps.LatLng(
(dis1.y + dis2.y) / 2,
(dis1.x + dis2.x) / 2
);
}
anchor = new naver.maps.Point(20, 35);
}
var marker = new naver.maps.Marker({
position: midPoint,
icon: {
content: content,
anchor: anchor
}
// map: map
});
// marker.setVisible(false)
if (circle) {
distanceMarker = marker;
} else {
marker.setMap(map);
distanceMarker.push(marker);
}
};
//거리 재기
const fromMetersToText = meters => {
meters = meters || 0;
var km = 1000,
text = meters;
text = parseFloat(meters.toFixed(1)) + 'm';
// if(meters >= km) {
// text = parseFloat((meters / km).toFixed(1)) + 'km';
// } else {
// text = parseFloat(meters.toFixed(1)) + 'm';
// }
return text;
};
return <InfoModal modal={alertModal} setModal={setAlertModal} />;
};

519
src/components/map/naver/sensor/SensorZone.js

@ -1,519 +0,0 @@
import React, { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
const SENSOR_RADIUS = '100';
const SENSOR_RADIUS_DIVISION = '3';
let lenderCnt = 0;
const SensorZone = props => {
const { naver } = props;
// 드론 실시간 정보
const { controlGpList } = useSelector(state => state.controlGpState);
// 환경지표 타입(dust, co, o3, no2, so2)
const { sensor } = useSelector(state => state.controlMapReducer);
// 센서레이어(환경지표) 관리
const [circleLayers, setCircleLayers] = useState([]);
const [polilineGroupLayers, setPolilineGroupLayers] = useState({});
useEffect(() => {
lenderCnt++;
if (!sensor) {
removeSensorLayers();
} else {
initSensorLayer();
}
}, [controlGpList, sensor]);
let infoWindow;
// 센서 레이어 Info
const infowindowOpen = data => {
const content = `
<div class="tooltip-box" style="max-width: 300px;">
<div class="tooltip-ti">
<span>${data.title}</span>
</div>
<div class="tooltip-txt">
<div class="tooltip-txt-list">
<div style="color: ${data.sensor.sensorDust.color};">
<span style="width: 120px; display: inline-block;">${data.sensor.sensorDust.title}(${data.sensor.sensorDust.text})</span>
<span>${data.sensor.sensorDust.value}</span>
</div>
<div style="color: ${data.sensor.sensorO3.color};">
<span style="width: 120px; display: inline-block;">${data.sensor.sensorO3.title}(${data.sensor.sensorO3.text})</span>
<span>${data.sensor.sensorO3.value}</span>
</div>
<div style="color: ${data.sensor.sensorNo2.color};">
<span style="width: 120px; display: inline-block;">${data.sensor.sensorNo2.title}(${data.sensor.sensorNo2.text})</span>
<span>${data.sensor.sensorNo2.value}</span>
</div>
<div style="color: ${data.sensor.sensorCo.color};">
<span style="width: 120px; display: inline-block;">${data.sensor.sensorCo.title}(${data.sensor.sensorCo.text})</span>
<span>${data.sensor.sensorCo.value}</span>
</div>
<div style="color: ${data.sensor.sensorSo2.color};">
<span style="width: 120px; display: inline-block;">${data.sensor.sensorSo2.title}(${data.sensor.sensorSo2.text})</span>
<span>${data.sensor.sensorSo2.value}</span>
</div>
</div>
</div>
</div>
`;
infoWindow = new naver.maps.InfoWindow({
class: 'tooltip-sensor',
content: content,
maxWidth: 300,
backgroundColor: '#283046', //박스안쪽영역 컬러
// borderColor: '#333', //테두리컬러
// borderWidth: 3, //테두리 굵기
anchorSize: new naver.maps.Size(30, -10),
anchorSkew: false,
anchorColor: '#283046',
pixelOffset: new naver.maps.Point(20, -20)
});
infoWindow.open(props.map, data.coord);
};
// 센서레이어 초기화
const initSensorLayer = () => {
emtpyLayerRemove();
if (controlGpList) {
controlGpList.forEach(controlGp => {
const { controlId, lat, lng, objectId } = controlGp;
let color = undefined;
const sensorData = convtSensorData(controlGp);
if (sensorData) {
if (sensor === 'dust') color = sensorData.sensorDust.color;
else if (sensor === 'co') color = sensorData.sensorCo.color;
else if (sensor === 'so2') color = sensorData.sensorSo2.color;
else if (sensor === 'no2') color = sensorData.sensorNo2.color;
else if (sensor === 'o3') color = sensorData.sensorO3.color;
}
const position = new naver.maps.LatLng(controlGp.lat, controlGp.lng);
const polilineLayers = polilineGroupLayers[controlId];
if (polilineLayers) {
// const prevPosition = polilineLayers[0].position;
// if(!prevPosition.equals(position)){
movePolilineLayers(polilineLayers, position, color);
// }
} else {
addPolilineLayers(controlId, objectId, position, color);
}
const circleLayer = circleLayers.find(
layer => layer.controlId === controlId
);
if (circleLayer)
moveCircleLayer(circleLayer, position, color, sensorData);
else addCircleLayer(controlId, objectId, position, color, sensorData);
});
}
};
// 센서레이어 생성
const addSensorLayer = (position, id, controlId, color, sensorData) => {
addPolilineLayers(controlId, id, position, color);
addCircleLayer(controlId, id, position, color, sensorData);
};
// Circle 레이어 생성
const addCircleLayer = (controlId, id, position, color, sensorData) => {
const circleLayer = new naver.maps.Circle({
title: id,
id: id,
controlId: controlId,
clickable: true,
center: position,
radius: SENSOR_RADIUS,
// map: props.map,
strokeColor: color,
strokeOpacity: 1,
strokeWeight: 2,
fillColor: color,
fillOpacity: 0.2,
sensorData: sensorData
});
// Circle 이벤트 주입
naver.maps.Event.addListener(circleLayer, 'mouseover', function (e) {
const data = {};
data.coord = e.coord;
data.title = '환경지표';
data.controlId = e.overlay.controlId;
data.sensor = e.overlay.sensorData;
e.overlay.setOptions({
strokeWeight: 5,
fillOpacity: 0.5
});
infowindowOpen(data);
});
naver.maps.Event.addListener(circleLayer, 'mouseout', function (e) {
e.overlay.setOptions({
strokeWeight: 2,
fillOpacity: 0.2
});
// props.map.Event.revertStyle();
if (infoWindow) {
infoWindow.close();
}
});
circleLayer.setMap(props.map);
setCircleLayers(prev => [...prev, circleLayer]);
};
const addPolilineLayers = (controlId, id, position, color) => {
// 지도에 적용 및 레이어 관리 추가
const polilineLayers = createCircleInGrid(position, id, controlId, color);
polilineLayers.forEach(layer => layer.setMap(props.map));
setPolilineGroupLayers(prev => ({
...prev,
[controlId]: polilineLayers
}));
};
// 센서레이어 이동
const moveSensorLayer = (controlId, position, color) => {
const circleLayer = circleLayers.find(
layer => layer.controlId === controlId
);
moveCircleLayer(circleLayer, position, color);
const polilineLayers = polilineGroupLayers[controlId];
movePolilineLayers(polilineLayers, position, color);
};
const moveCircleLayer = (circleLayer, position, color, sensorData) => {
// const circleLayer = circleLayers.find(layer => layer.controlId === controlId);
if (circleLayer) {
circleLayer.sensorData = sensorData;
circleLayer.setOptions({
center: position,
strokeColor: color,
fillColor: color
});
}
};
const movePolilineLayers = (polilineLayers, position, color) => {
const { controlId, id, position: prevPosition } = polilineLayers[0];
if (prevPosition.equals(position)) {
if (polilineLayers) {
polilineLayers.forEach(layer =>
layer.setOptions({ strokeColor: color })
);
}
} else {
if (polilineLayers) {
polilineLayers.forEach(layer => layer.setMap(null));
}
const newPolilineLayers = createCircleInGrid(
position,
id,
controlId,
color
);
newPolilineLayers.forEach(layer => layer.setMap(props.map));
setPolilineGroupLayers(prev => ({
...prev,
[controlId]: newPolilineLayers
}));
}
};
// 센서레이어 제거
const removeSensorLayer = controlId => {
removeCircleLayer(controlId);
removePolilineLayer(controlId);
};
const removeCircleLayer = controlId => {
const idx = circleLayers.findIndex(layer => layer.controlId === controlId);
circleLayers[idx].setMap(null);
setCircleLayers(prev => {
prev.splice(idx, 1);
return prev;
});
};
const removePolilineLayer = controlId => {
const polilineLayers = polilineGroupLayers[controlId];
if (polilineLayers) polilineLayers.forEach(layer => layer.setMap(null));
setPolilineGroupLayers(prev => {
delete prev[controlId];
return prev;
});
};
// 센서레이어 모두 제거
const removeSensorLayers = () => {
circleLayers.forEach(layer => layer.setMap(null));
setCircleLayers([]);
const keys = Object.keys(polilineGroupLayers);
keys.forEach(key => {
polilineGroupLayers[key].forEach(layer => layer.setMap(null));
});
setPolilineGroupLayers({});
};
// 레이어관리시 새로운 데이터에 없는 좌표 제거
const emtpyLayerRemove = () => {
setCircleLayers(prev => {
const remainCircleLayers = prev.filter((circleLayer, i) => {
const controlId = circleLayer.controlId;
const findObj = controlGpList.find(
controlGp => controlGp.controlId === controlId
);
if (findObj) {
return circleLayer;
} else {
circleLayer.setMap(null);
}
});
return remainCircleLayers;
});
setPolilineGroupLayers(prev => {
const keys = Object.keys(prev);
const remainPolilineGroupLayer = {};
keys.forEach((controlId, i) => {
const findObj = controlGpList.find(
controlGp => controlGp.controlId === controlId
);
if (findObj) {
remainPolilineGroupLayer[controlId] = prev[controlId];
} else {
const polilineLayers = prev[controlId];
polilineLayers.forEach(layer => {
layer.setMap(null);
});
}
});
return remainPolilineGroupLayer;
});
};
// Circle안에 격자 무늬 생성
const createCircleInGrid = (position, id, controlId, color) => {
// Circle 레이어 안의 격자무늬
const polilineLayers = [];
for (let i = 0; i <= SENSOR_RADIUS_DIVISION; i++) {
// 각 사분면 각도
const diff = 90 / SENSOR_RADIUS_DIVISION;
const angleQuadrant1 = diff * i;
const angleQuadrant2 = 180 - diff * i;
const angleQuadrant3 = 180 + diff * i;
const angleQuadrant4 = diff * -i;
// 각 사분면 좌표
const coord1 = new naver.maps.EPSG3857.getDestinationCoord(
position,
angleQuadrant1,
SENSOR_RADIUS
);
const coord2 = new naver.maps.EPSG3857.getDestinationCoord(
position,
angleQuadrant2,
SENSOR_RADIUS
);
const coord3 = new naver.maps.EPSG3857.getDestinationCoord(
position,
angleQuadrant3,
SENSOR_RADIUS
);
const coord4 = new naver.maps.EPSG3857.getDestinationCoord(
position,
angleQuadrant4,
SENSOR_RADIUS
);
const polyline12 = new naver.maps.Polyline({
id,
position,
controlId,
path: [coord1, coord2],
strokeWeight: 0.8,
// strokeWeight: 2,
strokeOpacity: 1,
strokeColor: color,
strokeStyle: 'shortdash'
});
polilineLayers.push(polyline12);
const polyline23 = new naver.maps.Polyline({
id,
position,
controlId,
path: [coord2, coord3],
strokeWeight: 0.8,
// strokeWeight: 2,
strokeOpacity: 1,
strokeColor: color,
strokeStyle: 'shortdash'
});
polilineLayers.push(polyline23);
const polyline34 = new naver.maps.Polyline({
id,
position,
controlId,
path: [coord3, coord4],
strokeWeight: 0.8,
// strokeWeight: 2,
strokeOpacity: 1,
strokeColor: color,
strokeStyle: 'shortdash'
});
polilineLayers.push(polyline34);
const polyline41 = new naver.maps.Polyline({
id,
position,
controlId,
path: [coord4, coord1],
strokeWeight: 0.8,
// strokeWeight: 2,
strokeOpacity: 1,
strokeColor: color,
strokeStyle: 'shortdash'
});
polilineLayers.push(polyline41);
}
return polilineLayers;
};
// 환경지표 필요한 데이터로 변환
const convtSensorData = sensorData => {
const r = {
sensorDust: {
title: '미세먼지',
value: '-',
text: '-',
color: undefined
},
sensorCo: {
title: '일산화탄소',
value: '-',
text: '-',
color: undefined
},
sensorSo2: {
title: '아황산가스',
value: '-',
text: '-',
color: undefined
},
sensorNo2: {
title: '이산화질소',
value: '-',
text: '-',
color: undefined
},
sensorO3: {
title: '오존',
value: '-',
text: '-',
color: undefined
}
};
// 정수: 미세먼지 || 소수점 1자리 : 일산화탄소 || 소수점 3자리 : 오존, 이산화질소, 아황산가스
// 좋음 : 파랑, 보통 : 노랑, 나쁨 : 주황, 매우나쁨 : 빨강
// 미세먼지 : 좋음(0~30) 보통(31~80) 나쁨(81~150) 매우나쁨(151~)
if (sensorData.sensorDust != undefined && sensorData.sensorDust != null) {
const val = (r.sensorDust.value = Math.round(sensorData.sensorDust));
if (val <= 30) {
r.sensorDust.text = '좋음';
r.sensorDust.color = '#37c9ff';
} else if (val <= 80) {
r.sensorDust.text = '보통';
r.sensorDust.color = '#ffff44';
} else if (val <= 150) {
r.sensorDust.text = '나쁨';
r.sensorDust.color = '#ffa044';
} else if (val > 150) {
r.sensorDust.text = '매우나쁨';
r.sensorDust.color = '#ff5959';
} else {
r.sensorDust.text = '-';
r.sensorDust.color = '#a1a1a1';
}
}
// 일산화탄소 : 좋음(0~2) 보통(2.1~9) 나쁨(9.1~15) 매우나쁨(15.1~)
if (sensorData.sensorCo != undefined && sensorData.sensorCo != null) {
const val = (r.sensorCo.value =
Math.round(sensorData.sensorCo * 10) / 10);
if (val <= 0.2) {
r.sensorCo.text = '좋음';
r.sensorCo.color = '#37c9ff';
} else if (val <= 9) {
r.sensorCo.text = '보통';
r.sensorCo.color = '#ffff44';
} else if (val <= 15) {
r.sensorCo.text = '나쁨';
r.sensorCo.color = '#ffa044';
} else if (val > 15) {
r.sensorCo.text = '매우나쁨';
r.sensorCo.color = '#ff5959';
} else {
r.sensorCo.text = '-';
r.sensorCo.color = '#a1a1a1';
}
}
// 아황산가스 : 좋음(0~0.02) 보통(0.021~0.05) 나쁨(0.051~0.15) 매우나쁨 (0.151 ~)
if (sensorData.sensorSo2 != undefined && sensorData.sensorSo2 != null) {
const val = (r.sensorSo2.value =
Math.round(sensorData.sensorSo2 * 1000) / 1000);
if (val <= 0.02) {
r.sensorSo2.text = '좋음';
r.sensorSo2.color = '#37c9ff';
} else if (val <= 0.05) {
r.sensorSo2.text = '보통';
r.sensorSo2.color = '#ffff44';
} else if (val <= 0.15) {
r.sensorSo2.text = '나쁨';
r.sensorSo2.color = '#ffa044';
} else if (val > 0.15) {
r.sensorSo2.text = '매우나쁨';
r.sensorSo2.color = '#ff5959';
} else {
r.sensorSo2.text = '-';
r.sensorSo2.color = '#a1a1a1';
}
}
// 이산화질소 : 좋음(0~0.03) 보통(0.031~0.06) 나쁨(0.061~0.2) 매우나쁨(0.201~)
if (sensorData.sensorNo2 != undefined && sensorData.sensorNo2 != null) {
const val = (r.sensorNo2.value =
Math.round(sensorData.sensorNo2 * 1000) / 1000);
if (val <= 0.03) {
r.sensorNo2.text = '좋음';
r.sensorNo2.color = '#37c9ff';
} else if (val <= 0.06) {
r.sensorNo2.text = '보통';
r.sensorNo2.color = '#ffff44';
} else if (val <= 0.2) {
r.sensorNo2.text = '나쁨';
r.sensorNo2.color = '#ffa044';
} else if (val > 0.2) {
r.sensorNo2.text = '매우나쁨';
r.sensorNo2.color = '#ff5959';
} else {
r.sensorNo2.text = '-';
r.sensorNo2.color = '#a1a1a1';
}
}
// 오존 : 좋음(0~0.03) 보통(0.031~0.09) 나쁨(0.091~0.15) 매우나쁨(0.151~)
if (sensorData.sensorO3 != undefined && sensorData.sensorO3 != null) {
const val = (r.sensorO3.value =
Math.round(sensorData.sensorO3 * 1000) / 1000);
if (val <= 0.03) {
r.sensorO3.text = '좋음';
r.sensorO3.color = '#37c9ff';
} else if (val <= 0.09) {
r.sensorO3.text = '보통';
r.sensorO3.color = '#ffff44';
} else if (val <= 0.15) {
r.sensorO3.text = '나쁨';
r.sensorO3.color = '#ffa044';
} else if (val > 0.15) {
r.sensorO3.text = '매우나쁨';
r.sensorO3.color = '#ff5959';
} else {
r.sensorO3.text = '-';
r.sensorO3.color = '#a1a1a1';
}
}
return r;
};
return null;
};
export default SensorZone;
Loading…
Cancel
Save