ctrlDraw #2

Merged
junh_eee merged 3 commits from ctrlDraw into master 1 year ago
  1. 12
      src/components/map/naver/NaverMap.js
  2. 201
      src/components/map/naver/draw/ControlDraw.js
  3. 11
      src/modules/control/map/actions/controlMapActions.ts
  4. 16
      src/modules/control/map/reducers/controlMapReducer.ts
  5. 29
      src/views/control/main/ControlMain.js

12
src/components/map/naver/NaverMap.js

@ -11,6 +11,7 @@ import NewDronPlan from './dron/NewDronPlan';
import { NewDronHistory } from './dron/NewDronHistroy'; import { NewDronHistory } from './dron/NewDronHistroy';
import DronToast from './dron/DronToast'; import DronToast from './dron/DronToast';
import SensorZone from './sensor/SensorZone'; import SensorZone from './sensor/SensorZone';
import ControlDraw from './draw/ControlDraw';
export const NaverCustomMap = () => { export const NaverCustomMap = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
@ -126,7 +127,8 @@ export const NaverCustomMap = () => {
useEffect(() => { useEffect(() => {
NaverMapInit(); NaverMapInit();
airPort?.map(air => polyArea(air)); // airPort?.map(air => polyArea(air));
airPort?.map((air, idx) => polyArea(air, idx));
}, []); }, []);
useEffect(() => { useEffect(() => {
@ -198,11 +200,11 @@ export const NaverCustomMap = () => {
setArrPolyline([...arrPolyline, line]); setArrPolyline([...arrPolyline, line]);
}; };
const polyArea = air => { const polyArea = (air, idx) => {
//격자 공역 //격자 공역
const polyArr = []; const polyArr = [];
const radius = air.buffer; const radius = air.buffer;
const position = air.center; const position = air.center; //공역 센터
const color = '#000'; const color = '#000';
const opacity = 0.7; const opacity = 0.7;
@ -215,6 +217,8 @@ export const NaverCustomMap = () => {
// buffer += 2000; // buffer += 2000;
buffer += 1000; buffer += 1000;
//EPSG3857.getDestinationCoord
//지정한 좌표에서 북쪽을 기준으로 각도와 거리만큼 떨어진 위치의 좌표 반환
const coord = new naver.maps.EPSG3857.getDestinationCoord( const coord = new naver.maps.EPSG3857.getDestinationCoord(
position, position,
angle, angle,
@ -308,6 +312,8 @@ export const NaverCustomMap = () => {
<NaverMapControl map={mapObject} /> <NaverMapControl map={mapObject} />
<ControlDraw map={mapObject} naver={naver} />
{/* <DronHistory {/* <DronHistory
map={mapObject} map={mapObject}
naver={naver} naver={naver}

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

@ -0,0 +1,201 @@
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;
}

11
src/modules/control/map/actions/controlMapActions.ts

@ -2,12 +2,12 @@
export const mapTypeChangeAction = (value: any) => dispatch => export const mapTypeChangeAction = (value: any) => dispatch =>
dispatch({ type: 'MAP_TYPE_CHANGE', value }); dispatch({ type: 'MAP_TYPE_CHANGE', value });
// draw 옵션 변경 Action // draw 옵션 변경 Action
export const drawTypeChangeAction = (value: any) => dispatch => export const drawTypeChangeAction = (value: any) => dispatch =>
dispatch({type: 'DRAW_TYPE_CHANGE', value}); dispatch({ type: 'DRAW_TYPE_CHANGE', value });
export const drawCheckAction = (value: any) => dispatch => export const drawCheckAction = (value: any) => dispatch =>
dispatch({type: 'DRAW_CHECK', value}); dispatch({ type: 'DRAW_CHECK', value });
// 드론체 클릭 시 Action // 드론체 클릭 시 Action
export const objectClickAction = (value: any) => dispatch => export const objectClickAction = (value: any) => dispatch =>
@ -20,4 +20,7 @@ export const areaClickAction = (value: any) => dispatch =>
dispatch({ type: 'AREA_CLICK', value }); dispatch({ type: 'AREA_CLICK', value });
export const sensorClickAction = (value: any) => dispatch => export const sensorClickAction = (value: any) => dispatch =>
dispatch({type: 'SENSOR_CLICK', value}) dispatch({ type: 'SENSOR_CLICK', value });
export const ctrlDrawTypeChangeAction = (value: any) => dispatch =>
dispatch({ type: 'CTRL_DRAW_TYPE_CHANGE', value });

16
src/modules/control/map/reducers/controlMapReducer.ts

@ -13,19 +13,21 @@ const initialState = {
drawType: null, drawType: null,
ctrlDrawType: null,
drawCheck: '' drawCheck: ''
}; };
const controlReducerReducer = (state = initialState, action) => { const controlReducerReducer = (state = initialState, action) => {
switch (action.type) { switch (action.type) {
case 'MAP_TYPE_CHANGE': case 'MAP_TYPE_CHANGE':
return {...state, mapType: action.value}; return { ...state, mapType: action.value };
case 'OBJECT_CLICK': case 'OBJECT_CLICK':
return {...state, objectId: action.value, isClickObject: true}; return { ...state, objectId: action.value, isClickObject: true };
case 'OBEJCT_UN_CLICK': case 'OBEJCT_UN_CLICK':
return {...state, isClickObject: false}; return { ...state, isClickObject: false };
case 'AREA_CLICK': case 'AREA_CLICK':
if (action.value === '0001') { if (action.value === '0001') {
@ -67,7 +69,7 @@ const controlReducerReducer = (state = initialState, action) => {
return { return {
...state, ...state,
sensor: action.value sensor: action.value
} };
break; break;
default: default:
return state; return state;
@ -78,6 +80,12 @@ const controlReducerReducer = (state = initialState, action) => {
drawType: action.value drawType: action.value
}; };
case 'CTRL_DRAW_TYPE_CHANGE':
return {
...state,
ctrlDrawType: action.value
};
case 'DRAW_CHECK': case 'DRAW_CHECK':
return { return {
...state, ...state,

29
src/views/control/main/ControlMain.js

@ -19,7 +19,7 @@ import {
import { AiOutlinePoweroff, AiOutlineExclamation } from 'react-icons/ai'; import { AiOutlinePoweroff, AiOutlineExclamation } from 'react-icons/ai';
import { IoAlertOutline } from 'react-icons/io5'; import { IoAlertOutline } from 'react-icons/io5';
import { ReactComponent as DroneMenuIcon } from '../../../assets/images/drone_menu_icon.svg'; import { ReactComponent as DroneMenuIcon } from '../../../assets/images/drone_menu_icon.svg';
import { Card } from 'reactstrap'; import { Card, Button } from 'reactstrap';
import ControlAlarmNotice from '../alarm/ControlAlarmNotice'; import ControlAlarmNotice from '../alarm/ControlAlarmNotice';
import ControlReportList from '../report/ControlReportList'; import ControlReportList from '../report/ControlReportList';
import ControlReportDetail from '../report/ControlReportDetail'; import ControlReportDetail from '../report/ControlReportDetail';
@ -30,7 +30,10 @@ import WebsocketClient from '../../../components/websocket/WebsocketClient';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { controlweatherAction } from '../../../modules/control/gp/actions/controlGpAction'; import { controlweatherAction } from '../../../modules/control/gp/actions/controlGpAction';
import * as Actions from '../../../modules/account/login/actions/authAction'; import * as Actions from '../../../modules/account/login/actions/authAction';
import { objectUnClickAction } from '../../../modules/control/map/actions/controlMapActions'; import {
ctrlDrawTypeChangeAction,
objectUnClickAction
} from '../../../modules/control/map/actions/controlMapActions';
const ControlMain = () => { const ControlMain = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
@ -149,6 +152,11 @@ const ControlMain = () => {
} else return <Cloud size={20} />; } else return <Cloud size={20} />;
} }
} }
const handlerDrawType = val => {
dispatch(ctrlDrawTypeChangeAction(val));
};
return ( return (
<> <>
<ControlAlarmNotice /> <ControlAlarmNotice />
@ -295,6 +303,23 @@ const ControlMain = () => {
</div> </div>
</Card> </Card>
</div> </div>
<div className='main-data-box flight-data'>
<Card>
<div className='data-box-header'>
<span className='box-ti'>화재경보</span>
</div>
<div className='data-list-box'>
<div className='data-list' style={{ cursor: 'pointer' }}>
<span onClick={() => handlerDrawType('CIRCLE')}>
화재구역설정
</span>
</div>
<div className='data-list' style={{ cursor: 'pointer' }}>
<span onClick={() => handlerDrawType('RESET')}>초기화</span>
</div>
</div>
</Card>
</div>
</div> </div>
{oepnReportList ? ( {oepnReportList ? (
<ControlReportList <ControlReportList

Loading…
Cancel
Save