junh_eee(이준희)
10 months ago
8 changed files with 0 additions and 5220 deletions
@ -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} />; |
||||
}; |
@ -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} />; |
||||
}; |
@ -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} />; |
||||
}; |
@ -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; |
||||
} |
@ -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} />; |
||||
}; |
@ -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> |
||||
</> |
||||
); |
||||
}; |
@ -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} />; |
||||
}; |
@ -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…
Reference in new issue