Browse Source

mapbox 언어 변경, 관제 기체 정보 팝업 작업중, 관제 기체 이동 작업, 코드 정리

master
김장현 1 year ago
parent
commit
da8b4d1079
  1. 10
      package-lock.json
  2. 2
      package.json
  3. 4
      src/components/map/MapControl.js
  4. 114
      src/components/map/mapbox/MapBoxMap.js
  5. 657
      src/components/map/mapbox/dron/DronMarker.js
  6. 207
      src/components/map/mapbox/feature/FeatureAirZone.js
  7. 12
      test/pav-warning.js

10
package-lock.json generated

@ -1973,6 +1973,11 @@
"resolved": "https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz", "resolved": "https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz",
"integrity": "sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==" "integrity": "sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ=="
}, },
"@mapbox/mapbox-gl-language": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-language/-/mapbox-gl-language-1.0.1.tgz",
"integrity": "sha512-gL58ojl7gaWLfbSISoB2QJEfTK3j+NKvPH9og0r+c3bd5BNqhY19Eb4OPfDc5+dGmjW03LhtZBc4n2b7Xn8kjA=="
},
"@mapbox/mapbox-gl-supported": { "@mapbox/mapbox-gl-supported": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-2.0.1.tgz", "resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-2.0.1.tgz",
@ -24895,6 +24900,11 @@
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ="
}, },
"threebox-plugin": {
"version": "2.2.7",
"resolved": "https://registry.npmjs.org/threebox-plugin/-/threebox-plugin-2.2.7.tgz",
"integrity": "sha512-H87Nm4w1PfisHPHzavTGXlwIoJpx2+QU57GooQYIhF51lsg+U5A0KGf3Jrv/HWsLCGOwV2BTnv7UTLfpO1EccQ=="
},
"throat": { "throat": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz",

2
package.json

@ -13,6 +13,7 @@
"@fullcalendar/timegrid": "5.7.2", "@fullcalendar/timegrid": "5.7.2",
"@fullcalendar/timeline": "5.7.2", "@fullcalendar/timeline": "5.7.2",
"@hookform/resolvers": "1.3.4", "@hookform/resolvers": "1.3.4",
"@mapbox/mapbox-gl-language": "1.0.1",
"@stomp/stompjs": "^6.1.0", "@stomp/stompjs": "^6.1.0",
"@turf/buffer": "^6.5.0", "@turf/buffer": "^6.5.0",
"@turf/turf": "6.5.0", "@turf/turf": "6.5.0",
@ -110,6 +111,7 @@
"sweetalert2": "10.14.0", "sweetalert2": "10.14.0",
"sweetalert2-react-content": "3.0.1", "sweetalert2-react-content": "3.0.1",
"swiper": "6.0.4", "swiper": "6.0.4",
"threebox-plugin": "2.2.7",
"typesafe-actions": "^5.1.0", "typesafe-actions": "^5.1.0",
"uppy": "1.21.2", "uppy": "1.21.2",
"webpack": "4.43.0", "webpack": "4.43.0",

4
src/components/map/MapControl.js

@ -5,8 +5,8 @@ import MapBoxMap from './mapbox/MapBoxMap';
export const MapControl = props => { export const MapControl = props => {
return ( return (
// <>{props.mapType === 'google' ? <GoogleCustomMap /> : <NaverCustomMap />}</> <>{props.mapType === 'google' ? <GoogleCustomMap /> : <NaverCustomMap />}</>
// <NaverCustomMap /> // <NaverCustomMap />
<MapBoxMap /> // <MapBoxMap />
); );
}; };

114
src/components/map/mapbox/MapBoxMap.js

@ -1,7 +1,7 @@
import { MAPBOX_TOKEN } from '../../../configs/constants'; import { MAPBOX_TOKEN } from '../../../configs/constants';
import { useEffect, useState, useRef } from 'react'; import { useEffect, useState, useRef } from 'react';
import { useSelector, useDispatch } from 'react-redux'; import { useSelector, useDispatch } from 'react-redux';
// import { DronMarker } from './dron/DronMarker'; import { DronMarker } from './dron/DronMarker';
// import { DronHistory } from './dron/DronHistory'; // import { DronHistory } from './dron/DronHistory';
// import NaverMapControl from './NaverMapControl'; // import NaverMapControl from './NaverMapControl';
// import { NaverMapSearch } from './search/NaverMapSearch'; // import { NaverMapSearch } from './search/NaverMapSearch';
@ -13,7 +13,8 @@ import { FeatureAirZone } from './feature/FeatureAirZone';
// import SensorZone from './sensor/SensorZone'; // import SensorZone from './sensor/SensorZone';
import 'mapbox-gl/dist/mapbox-gl.css'; import 'mapbox-gl/dist/mapbox-gl.css';
import mapboxgl from 'mapbox-gl'; import mapboxgl from 'mapbox-gl';
import threebox from 'threebox-plugin';
import MapboxLanguage from '@mapbox/mapbox-gl-language';
// mapboxgl.accessToken = MAPBOX_TOKEN; // mapboxgl.accessToken = MAPBOX_TOKEN;
export default function MapBoxMap() { export default function MapBoxMap() {
// const mapContainer = useRef(null); // const mapContainer = useRef(null);
@ -234,7 +235,7 @@ export default function MapBoxMap() {
}; };
useEffect(() => { useEffect(() => {
NaverMapInit(); mapBoxMapInit();
}, []); }, []);
useEffect(() => { useEffect(() => {
@ -261,7 +262,7 @@ export default function MapBoxMap() {
} }
}, [mapObject]); }, [mapObject]);
let popup; let popup;
const NaverMapInit = () => { const mapBoxMapInit = () => {
mapboxgl.accessToken = MAPBOX_TOKEN; mapboxgl.accessToken = MAPBOX_TOKEN;
// const mapOptions = { // const mapOptions = {
// center: new naver.maps.LatLng(37.520357, 126.610166), // center: new naver.maps.LatLng(37.520357, 126.610166),
@ -280,12 +281,30 @@ export default function MapBoxMap() {
container: 'map', // container ID container: 'map', // container ID
style: 'mapbox://styles/mapbox/streets-v12', // style URL style: 'mapbox://styles/mapbox/streets-v12', // style URL
center: [127.85101412107547, 37.520357], // starting position [lng, lat] center: [127.85101412107547, 37.520357], // starting position [lng, lat]
zoom: 9 // starting zoom zoom: 8.5, // starting zoom
antialias: true
// pitch: 64.9,
// bearing: 172.5
}); });
const language = new MapboxLanguage();
map.addControl(language);
// const tb = (window.tb = new threebox.Threebox(
// map,
// map.getCanvas().getContext('webgl'),
// {
// defaultLights: true,
// enableSelectingObjects: true,
// enableDraggingObjects: true,
// enableRotatingObjects: true,
// enableTooltips: true
// }
// ));
map.on('load', () => { map.on('load', () => {
const layers = map.getStyle().layers; const layers = map.getStyle().layers;
map.setLayoutProperty('country-label', 'text-field', ['get', `name_kr`]);
const labelLayerId = layers.find( const labelLayerId = layers.find(
layer => layer.type === 'symbol' && layer.layout['text-field'] layer => layer.type === 'symbol' && layer.layout['text-field']
).id; ).id;
@ -390,31 +409,62 @@ export default function MapBoxMap() {
setMapObject(map); setMapObject(map);
setMapLoaded(true); setMapLoaded(true);
}); });
map.on('mouseover', 'maine', e => { // map.on('style.load', () => {
const feature = e.features[0]; // map.addLayer({
const properties = feature.properties; // id: 'custom-threebox-model',
// type: 'custom',
// Remove the existing popup if it exists // renderingMode: '3d',
if (popup) { // onAdd: function () {
popup.remove(); // // Creative Commons License attribution: Metlife Building model by https://sketchfab.com/NanoRay
} // // https://sketchfab.com/3d-models/metlife-building-32d3a4a1810a4d64abb9547bb661f7f3
// const scale = -20;
// Create a new popup with the feature's properties // const options = {
popup = new mapboxgl.Popup() // obj: './src/components/map/mapbox/diorama/scene.gltf',
.setLngLat(e.lngLat) // // obj: 'https://docs.mapbox.com/mapbox-gl-js/assets/metlife-building.gltf',
.setHTML( // type: 'gltf',
Object.entries(properties) // units: 'meters',
.map(([key, value]) => `${key}: ${value}`) // scale: 1,
.join('<br>') // anchor: 'center',
) // rotation: { x: 90, y: 0, z: 0 }
.addTo(map); // };
});
// tb.loadObj(options, model => {
// model.setCoords([127.85101412107547, 37.520357, 1000]);
// model.setRotation({ x: 0, y: 0, z: 241 });
// tb.add(model);
// });
// },
// render: function () {
// tb.update();
// }
// });
// });
// map.on('mouseover', 'maine', e => {
// const feature = e.features[0];
// const properties = feature.properties;
// // Remove the existing popup if it exists
// if (popup) {
// popup.remove();
// }
map.on('mouseout', 'maine', () => { // // Create a new popup with the feature's properties
if (popup) { // popup = new mapboxgl.Popup()
popup.remove(); // .setLngLat(e.lngLat)
} // .setHTML(
}); // Object.entries(properties)
// .map(([key, value]) => `${key}: ${value}`)
// .join('<br>')
// )
// .addTo(map);
// });
// map.on('mouseout', 'maine', () => {
// if (popup) {
// popup.remove();
// }
// });
// airPort?.map(air => polyArea(air, map)); // airPort?.map(air => polyArea(air, map));
}; };
@ -588,7 +638,7 @@ export default function MapBoxMap() {
></div> ></div>
{isMapLoaded && mapObject ? ( {isMapLoaded && mapObject ? (
<> <>
{/* <DronMarker map={mapObject} naver={mapboxgl} /> */} <DronMarker map={mapObject} mapboxgl={mapboxgl} />
{/* <DronPlan map={mapObject} naver={naver} /> {/* <DronPlan map={mapObject} naver={naver} />
<NewDronPlan map={mapObject} naver={naver} /> <NewDronPlan map={mapObject} naver={naver} />
@ -610,7 +660,7 @@ export default function MapBoxMap() {
{/* <DronToast /> */} {/* <DronToast /> */}
<FeatureAirZone map={mapObject} naver={mapboxgl} /> <FeatureAirZone map={mapObject} mapboxgl={mapboxgl} />
{/* <NaverMapSearch map={mapObject} naver={naver} /> */} {/* <NaverMapSearch map={mapObject} naver={naver} /> */}
{/* <SensorZone map={mapObject} naver={naver} /> */} {/* <SensorZone map={mapObject} naver={naver} /> */}
</> </>

657
src/components/map/mapbox/dron/DronMarker.js

@ -0,0 +1,657 @@
import $ from 'jquery';
import { useEffect, useState } from 'react';
import { useDispatch, useSelector, shallowEqual } from 'react-redux';
import '../../../../assets/css/custom.css';
import FlightIcon from '../../../../assets/images/airplan_org.svg';
import FlightDetailIcon from '../../../../assets/images/airplan_pp.svg';
import DronIcon from '../../../../assets/images/drone-marker-icon.png';
import DronDetailIcon from '../../../../assets/images/drone-marker-icon-pulple.png';
import DronUamIcon from '../../../../assets/images/uam_icon.png';
import DronUamDetailIcon from '../../../../assets/images/uam_icon_purple.png';
import {
controlGpDtlAction,
controlGpFlightPlanAction,
controlGpCountAction
} from '../../../../modules/control/gp';
import {
objectClickAction,
objectUnClickAction
} from '../../../../modules/control/map/actions/controlMapActions';
import { JOIN_LIST } from '../../../../modules/basis/group/actions/basisGroupAction';
export const DronMarker = props => {
const dispatch = useDispatch();
const { controlGpList, controlGroupAuthInfo } = useSelector(
state => state.controlGpState
);
const { objectId, isClickObject } = useSelector(
state => state.controlMapReducer,
shallowEqual
);
// const { controlGroupAuthInfo } = useSelector(
// state => state.controlGroupAuthState
// );
const { controlGpArcrftWarnList } = useSelector(
state => state.controlGpLogState
);
const { user } = useSelector(state => state.authState);
const { joinList } = useSelector(state => state.groupState);
const [arrMarkers, setArrMarkers] = useState([]);
const [arrInfos, setArrInfos] = useState([]);
const [count, setCount] = useState({
drone: [],
flight: []
});
let mapboxgl = props.mapboxgl;
let map = props.map;
let CustomOverlay;
let infoWindow;
// const infowindowOpen = data => {
// const content = `
// <div class="dblock-box">
// <div class="dblock-ti">
// <span>${data?.id}</span>
// </div>
// <div class="dblock-txt>
// <div class="dblock-txt-list">
// <div>
// <span style="width: 250px; display: inline-block;">${
// data?.speed
// }${data?.speedType} | ${data?.elev}${data?.elevType} | ${
// data?.heading
// }</span>
// <span style="width: 250px; display: inline-block;">${(data?.coord._lat).toFixed(
// 6
// )} | ${(data?.coord._lng).toFixed(6)}</span>
// </div>
// </div>
// </div>
// </div>
// `;
// infoWindow = new naver.maps.InfoWindow({
// class: 'tooltip-dblock',
// content: content,
// maxWidth: 160,
// 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);
// };
// useLayoutEffect(() => {
// dispatch(controlGroupAuthAction.request());
// }, [controlGpList]);
useEffect(() => {
if (count.drone.length > 0 || count.flight.length > 0) {
dispatch(
controlGpCountAction.request({
count
})
);
} else {
const count = {
drone: [],
flight: []
};
dispatch(
controlGpCountAction.request({
count
})
);
}
}, [count]);
useEffect(() => {
dispatch(
JOIN_LIST.request({
cstmrSno: user?.cstmrSno
})
);
}, []);
useEffect(() => {
if (arrMarkers.length != 0) {
markerInfo(arrMarkers);
}
}, [arrMarkers]);
useEffect(() => {
markerInit();
}, [controlGpList]);
// useEffect(() => {
// let imageUrl;
// arrMarkers.map(clickMarker => {
// if (objectId === clickMarker.controlId && isClickObject) {
// // console.log(clickMarker.gps.objectId, '><><');
// imageUrl =
// // clickMarker.type === 'DRONE' ? DronUamDetailIcon : FlightDetailIcon;
// clickMarker.type === 'DRONE'
// ? clickMarker.gps.objectId.includes('UAM')
// ? DronUamDetailIcon
// : DronDetailIcon
// : FlightDetailIcon;
// clickMarker.setIcon({
// content: `<img src="${imageUrl}" alt="" style="transform: rotate(${clickMarker.gps.heading}deg)">`,
// origin: new naver.maps.Point(0, 0),
// anchor: new naver.maps.Point(15, 15)
// });
// } else {
// // imageUrl = clickMarker.type === 'DRONE' ? DronUamIcon : FlightIcon;
// imageUrl =
// clickMarker.type === 'DRONE'
// ? clickMarker.gps.objectId.includes('UAM')
// ? DronUamIcon
// : DronIcon
// : FlightIcon;
// clickMarker.setIcon({
// content: `<img src="${imageUrl}" alt="" style="transform: rotate(${clickMarker.gps.heading}deg)">`,
// origin: new naver.maps.Point(0, 0),
// anchor: new naver.maps.Point(15, 15)
// });
// }
// });
// }, [objectId, isClickObject]);
// useEffect(() => {
// arrMarkers.map(clickMarker => {
// if (objectId === clickMarker.controlId) {
// dispatch(controlGpDtlAction.request(objectId));
// props.map.setCenter(clickMarker.getPosition());
// props.map.setZoom(13, true);
// }
// });
// }, [objectId]);
//마커를 그린다.
const addMarkers = (position, id, controlId, gps) => {
const gpsCnt = {
gps: gps,
type: ''
};
const markerOption = {};
if (id.substring(0, 2) === 'PA') {
const pal = controlGroupAuthInfo?.find(
prev => prev.idntfNum === gps.objectId
);
if (pal || !pal || id.includes('NAMWON')) {
if (id.includes('UAM')) {
markerOption.url = DronUamIcon;
} else {
markerOption.url = DronIcon;
}
markerOption.type = 'DRONE';
gpsCnt.type = 'drone';
} else {
if (user?.authId === 'SUPER' || user?.authId === 'ADMIN') {
markerOption.url = FlightIcon;
markerOption.type = 'FLIGHT';
gpsCnt.type = 'flight';
} else {
const terminal = joinList?.find(prev => prev.trmnlId === gps.trmnlId);
if (
terminal?.groupAuthCd === 'MASTER' ||
terminal?.groupAuthCd === 'LEADER'
) {
markerOption.url = FlightIcon;
markerOption.type = 'FLIGHT';
gpsCnt.type = 'flight';
}
}
}
} else {
if (user?.authId === 'SUPER' || user?.authId === 'ADMIN') {
markerOption.url = FlightIcon;
markerOption.type = 'FLIGHT';
gpsCnt.type = 'flight';
} else {
const terminal = joinList?.find(prev => prev.trmnlId === gps.trmnlId);
if (
terminal?.groupAuthCd === 'MASTER' ||
terminal?.groupAuthCd === 'LEADER'
) {
markerOption.url = FlightIcon;
markerOption.type = 'FLIGHT';
gpsCnt.type = 'flight';
}
}
}
if (gpsCnt.type === 'drone') {
setCount(prev => ({
...prev,
drone: [...prev.drone, gpsCnt]
}));
} else if (gpsCnt.type === 'flight') {
setCount(prev => ({
...prev,
flight: [...prev.flight, gpsCnt]
}));
}
// if (id.substring(0, 2) === 'PA') {
// const pal = controlGroupAuthInfo?.find(
// prev => prev.idntfNum === gps.objectId
// );
// markerOption.url = pal ? DronIcon : FlightIcon;
// markerOption.type = pal ? 'DRONE' : 'FLIGHT';
// } else {
// markerOption.url = FlightIcon;
// markerOption.type = 'FLIGHT';
// }
// markerOption.origin = new naver.maps.Point(0, 0);
// markerOption.anchor = new naver.maps.Point(15, 15);
// const marker = new naver.maps.Marker({
// position: position,
// title: id,
// id: id,
// controlId: controlId,
// type: markerOption.type,
// icon: {
// content: `<img id=${id} src="${markerOption.url}" alt="" style="transform: rotate(${gps.heading}deg);">`,
// origin: markerOption.origin,
// anchor: markerOption.anchor
// },
// gps: gps
// });
// marker.setMap(props.map);
const el = document.createElement('img');
el.id = id;
el.src = markerOption.url;
el.style.transform = `rotate(${gps.heading}deg)`;
const marker = new props.mapboxgl.Marker({
element: el,
rotation: gps.heading
})
.setLngLat(position)
.addTo(props.map);
marker.id = id;
marker.title = id;
marker.controlId = controlId;
marker.type = markerOption.type;
marker.gps = gps;
marker.position = position;
marker.icon = {
content: `<img id=${id} src="${markerOption.url}" alt="" style="transform: rotate(${gps.heading}deg);">`,
origin: markerOption.origin,
anchor: markerOption.anchor
};
dispatch(controlGpFlightPlanAction.request(marker.id)); //예상경로
// dispatch(controlGpHisAction.request({ id: marker.controlId })); //진행경로;
/** drone 상세보기 */
marker.getElement().addEventListener('click', function (e) {
handlerDronClick(marker.controlId, marker.id);
});
if (markerOption.url) {
setArrMarkers(m => [...m, marker]);
}
};
const handlerDronClick = (controlId, idntfNum) => {
// get detail, history, flight-plan
dispatch(objectClickAction(controlId));
// dispatch(controlGpDtlAction.request(controlId));
// dispatch(controlGpFlightPlanAction.request(idntfNum));
};
//마커를 삭제 한다.
const removeMarkers = marker => {
// marker.setMap(null);
marker.remove();
};
const removeInfos = info => {
// info.setMap(null);
info.remove();
};
//마커에 위치를 이동한다.
const moveMarkers = (marker, position, gps) => {
const getIcon = marker.icon;
marker.setLngLat(position);
const warnList = controlGpArcrftWarnList?.filter(
i => i.cntrlId === gps.controlId
);
if (warnList?.length > 0) {
if (warnList[0].controlWarnCd) {
// marker.setIcon({
// content: `<img ${getIcon.content.substr(
// getIcon.content.indexOf('src'),
// getIcon.content.indexOf('alt') - 6
// )} alt="" style="transform: rotate(${
// gps.heading
// }deg); filter: invert(16%) sepia(79%) saturate(4975%) hue-rotate(359deg) brightness(104%) contrast(129%)" />`,
// anchor: getIcon.anchor
// });
} else {
// console.log(marker);
// marker.setIcon({
// content: `<img ${getIcon.content.substr(
// getIcon.content.indexOf('src'),
// getIcon.content.indexOf('alt') - 6
// )} alt="" style="transform: rotate(${gps.heading}deg); " />`,
// anchor: getIcon.anchor
// });
marker.setRotation(gps.heading);
}
return;
}
marker.setRotation(gps.heading);
// marker.setIcon({
// content: `<img ${getIcon.content.substr(
// getIcon.content.indexOf('src'),
// getIcon.content.indexOf('alt') - 6
// )} alt="" style="transform: rotate(${gps.heading}deg); " />`,
// anchor: getIcon.anchor
// });
};
const moveInfos = (info, position, item, idx) => {
if (info) {
info.setLngLat([position.lng, position.lat]);
// info.setPosition(position, info);
// // info._element.html(`<div class="dblock-ti"><span>${info?._id}</span>
// // <span>${item?.speed}${item?.speedType} | ${item?.elev}${item?.elevType} | ${item?.heading}</span></div>`);
// info._element.html(`
// <div class="dblock-ti">
// <span>${info?._id}</span>
// </div>
// <div class="dblock-txt">
// <div class="dblock-txt-list">
// <span>${item?.elev}M</span>
// <span>${item?.speed}km</span>
// ${
// typeof item?.lat === 'number' && typeof item?.lng === 'number'
// ? `
// <span>
// ${(item?.lat).toFixed(6)} ${(item?.lng).toFixed(6)}
// </span>`
// : ''
// }
// </div>
// </div>
// `);
}
};
//데이터가 없는 마커를 모두 삭제 한다.
const allRemoveMarkers = () => {
let isUnClick = false;
if (arrMarkers && controlGpList) {
arrMarkers.map(marker => {
const isExists = controlGpList.find(
item => item.objectId === marker.id
);
if (!isExists) {
removeMarkers(marker);
const arrData = arrMarkers.filter(item => item.id != marker.id);
const drone = count.drone.filter(d => d.gps.objectId != marker.id);
const flight = count.flight.filter(d => d.gps.objectId != marker.id);
setCount({
drone: drone,
flight: flight
});
removeArrMarkers(arrData);
if (marker.controlId === objectId) {
dispatch(objectUnClickAction());
}
}
});
arrInfos.map(info => {
const isExists = controlGpList.find(item => item.objectId === info._id);
if (!isExists) {
removeInfos(info);
const arrData = arrInfos.filter(item => item.id != info._id);
removeArrInfos(arrData);
}
});
}
return isUnClick;
};
//마커를 셋팅 한다.
const markerInit = () => {
if (controlGpList) {
allRemoveMarkers();
controlGpList.map((item, idx) => {
// let position = new naver.maps.LatLng(item.lat, item.lng);
let position = new props.mapboxgl.LngLat(item.lng, item.lat);
if (arrMarkers.length > 0) {
const isExists = arrMarkers.find(ele => ele.id === item.objectId);
const isInfos = arrInfos.find(info => info._id === item.objectId);
if (isExists) {
moveMarkers(isExists, position, item);
moveInfos(isInfos, position, item, idx);
} else {
addMarkers(position, item.objectId, item.controlId, item);
}
} else {
addMarkers(position, item.objectId, item.controlId, item);
}
});
}
};
//운항정보 창 셋팅
const infoInit = (marker, gps, idx) => {
CustomOverlay = function (options) {
this._element = $(`
<div class="dblock-box">
<div class="dblock-ti">
<span>${marker?.id}</span>
</div>
<div class="dblock-txt">
<div class="dblock-txt-list">
<span>${gps?.elev}M</span>
<span>${gps?.speed}km</span>
${
typeof gps?.lat === 'number' && typeof gps?.lng === 'number'
? `
<span>
${(gps?.lat).toFixed(6)} ${(gps?.lng).toFixed(6)}
</span>`
: ''
}
</div>
</div>
</div>
`);
// this._element = $(`
// <div class="tooltip-box" style="width: 150px;">
// <div class="tooltip-ti">
// <span>${marker?.id}</span>
// </div>
// <div class="tooltip-txt>
// <div class="tooltip-txt-list">
// <div>
// <span style="width: 120px; display: inline-block;">속도: ${gps?.speed}${gps?.speedType}</span>
// </div>
// <div>
// <span style="width: 120px; display: inline-block;">고도: ${gps?.elev}${gps?.elevType}</span>
// </div>
// <div>
// <span style="width: 120px; display: inline-block;">헤딩방향: ${gps?.heading}</span>
// </div>
// </div>
// </div>
// </div>
// `)
this.setPosition(options.position, idx);
this.setMap(options.map || null);
this.setId(options.id);
this.setIdx(idx);
this.setControlId(options.controlId);
};
CustomOverlay.prototype = new naver.maps.OverlayView();
CustomOverlay.prototype.constructor = CustomOverlay;
//메소드 재정의
//필수
CustomOverlay.prototype.onAdd = function () {
let overlayLayer = this.getPanes().overlayLayer;
this._element.appendTo(overlayLayer);
};
CustomOverlay.prototype.draw = function (idx) {
if (!this.getMap()) {
return;
}
let projection = this.getProjection(),
position = this.getPosition(),
pixelPosition = projection.fromCoordToOffset(position);
// let cnt = 0;
// let index = idx?._idx;
// cnt = index * 98;
this._element.css('left', pixelPosition.x);
this._element.css('top', pixelPosition.y);
// this._element.css('top', pixelPosition.y + -cnt)
};
CustomOverlay.prototype.onRemove = function () {
let overlayLayer = this.getPanes().overlayLayer;
this._element.remove();
this._element.off();
};
//속성
CustomOverlay.prototype.setPosition = function (position, idx) {
this._position = position;
this.draw(idx);
};
CustomOverlay.prototype.getPosition = function () {
return this._position;
};
CustomOverlay.prototype.setId = function (id) {
this._id = id;
};
CustomOverlay.prototype.getId = function () {
return this._id;
};
CustomOverlay.prototype.setIdx = function (idx) {
this._idx = idx;
};
CustomOverlay.prototype.getIdx = function () {
return this._idx;
};
CustomOverlay.prototype.setControlId = function (controlId) {
this._controlId = controlId;
};
CustomOverlay.prototype.getControlId = function () {
return this._controlId;
};
};
const removeArrMarkers = arrData => {
setArrMarkers(arrData);
};
const removeArrInfos = arrData => {
setArrInfos(arrData);
};
const markerInfo = arrMarkers => {
arrMarkers.forEach((marker, idx) => {
if (arrInfos.filter(i => i._controlId === marker.controlId).length > 0) {
return;
}
const info = new props.mapboxgl.Popup({
closeButton: false,
closeOnClick: false
})
.setLngLat([marker.position.lng, marker.position.lat])
.setHTML(
`
<div class="dblock-box">
<div class="dblock-ti">
<span>${marker?.id}</span>
</div>
<div class="dblock-txt">
<div class="dblock-txt-list">
<span>${marker.gps?.elev}M</span>
<span>${marker.gps?.speed}km</span>
${
typeof marker.gps?.lat === 'number' &&
typeof marker.gps?.lng === 'number'
? `
<span>
${(marker.gps?.lat).toFixed(
6
)} ${(marker.gps?.lng).toFixed(6)}
</span>`
: ''
}
</div>
</div>
</div>
`
)
.addTo(props.map);
// infoInit(marker, controlGpList[idx], idx);
info._id = marker.id;
info.gps = marker.gps;
// if (controlGpList.length != 0) {
// const info = new CustomOverlay({
// position: new naver.maps.LatLng(
// controlGpList[idx]?.lat,
// controlGpList[idx]?.lng
// ),
// // map: map,
// id: marker.id,
// idx: idx,
// controlId: marker.controlId
// });
// info.setMap(map);
setArrInfos(m => [...m, info]);
// }
});
};
return null;
};

207
src/components/map/mapbox/feature/FeatureAirZone.js

@ -5,6 +5,7 @@ import geoJson from '../../../../components/map/geojson/airArea.json';
import gimPo from '../../../../components/map/geojson/airportAirArea.json'; import gimPo from '../../../../components/map/geojson/airportAirArea.json';
import '../../../../assets/css/custom.css'; import '../../../../assets/css/custom.css';
// 격자 공역 Source
const airPort = [ const airPort = [
{ {
title: '김포공항', title: '김포공항',
@ -34,34 +35,13 @@ const airPort = [
export const FeatureAirZone = props => { export const FeatureAirZone = props => {
const mapControl = useSelector(state => state.controlMapReducer); const mapControl = useSelector(state => state.controlMapReducer);
let popup;
let infoWindow; let infoWindow;
useEffect(() => { useEffect(() => {
featureAirZoneInit(); featureAirZoneInit();
// featureAirEvent();
}, [mapControl]); }, [mapControl]);
// useEffect(() => {
// const addLayers = () => {
// props.poly.forEach((layer, idx) => {
// // console.log(layer);
// props.map.addSource(`line${idx}`, {
// type: 'geojson',
// data: {
// layer
// }
// });
// props.map.addLayer(layer);
// });
// };
// addLayers();
// // return () => {
// // props.map.remove();
// // };
// }, [props.poly]);
const infowindowOpen = data => { const infowindowOpen = data => {
const content = const content =
'<div class="tooltip-box">' + '<div class="tooltip-box">' +
@ -72,48 +52,99 @@ export const FeatureAirZone = props => {
'</div>' + '</div>' +
'<div class="tooltip-txt">' + '<div class="tooltip-txt">' +
'<div class="tooltip-txt-list">' + '<div class="tooltip-txt-list">' +
// '<span class="ti">설명</span>' +
'<span>' + '<span>' +
data.description + data.description +
'</span>' + '</span>' +
'</div>' + '</div>' +
// '<div class="tooltip-txt-list">' +
// '<span class="ti">좌표정보</span>' +
// '<span>'+data.coord+'</span>' +
// '</div>' +
'</div>' + '</div>' +
// '<span class="arrow"></span>' +
'</div>'; '</div>';
infoWindow = new props.naver.maps.InfoWindow({ if (popup) {
class: 'tooltip-test', popup.remove();
content: content, }
maxWidth: 200,
backgroundColor: '#283046', //박스안쪽영역 컬러 // Create a popup element
// borderColor: '#333', //테두리컬러 popup = new props.mapboxgl.Popup({
// borderWidth: 3, //테두리 굵기 offset: [20, -20],
anchorSize: new props.naver.maps.Size(30, -10), closeButton: false,
anchorSkew: false, closeOnClick: false,
anchorColor: '#283046', closeOnMove: true
})
pixelOffset: new props.naver.maps.Point(20, -20) .setLngLat(data.coord)
.setHTML(content)
.addTo(props.map);
};
const featureAirEvent = markers => {
markers.forEach(marker => {
marker.getElement().addEventListener('mouseover', e => {
const data = {};
data.coord = marker.getLngLat();
data.title = marker.properties.name;
data.description = marker.properties.description;
infowindowOpen(data);
});
marker.getElement().addEventListener('mouseout', () => {
if (popup) {
popup.remove();
}
});
});
props.map.on('mouseover', 'maine', e => {
props.map.getCanvas().style.cursor = 'pointer';
const feature = e.features[0];
const data = feature.properties;
data.coord = e.lngLat;
data.title = feature.properties.name;
infowindowOpen(data);
});
props.map.on('mouseout', 'maine', () => {
props.map.getCanvas().style.cursor = '';
if (popup) {
popup.remove();
}
}); });
infoWindow.open(props.map, data.coord); props.map.on('click', e => {
// 클릭한 지점의 피처들을 얻어옵니다.
const features = props.map.queryRenderedFeatures(e.point, {
layers: ['add-3d-buildings'] // 빌딩 레이어의 ID를 지정합니다.
});
// 빌딩 피처가 있는 경우
if (features.length > 0) {
// 첫 번째 빌딩 피처의 높이 값을 얻어옵니다.
const height = features[0].properties.height;
// 팝업을 생성하고 지도에 추가합니다.
new props.mapboxgl.Popup()
.setLngLat(e.lngLat)
.setHTML(`Building height: ${height}m`)
.addTo(props.map);
}
});
}; };
// 공역 생성 함수
const featureAirZoneInit = () => { const featureAirZoneInit = () => {
let arrGeoJson = []; let arrGeoJson = [];
// props.map.data.removeGeoJson(props.geoJson);
// let geoJson = originGeoJson;
const useGeoJson = { const useGeoJson = {
...geoJson, ...geoJson,
features: [...geoJson.features, ...gimPo.features] features: [...geoJson.features, ...gimPo.features]
}; };
// props.map.data.removeGeoJson(useGeoJson); // props.map.data.removeGeoJson(useGeoJson);
// props.map.removeLayer('maine'); if (props.map.getLayer('maine')) {
props.map.removeLayer('maine');
props.map.removeSource('maine');
}
// 공역 색상 및 공역 표출 정보에 따른 노출
useGeoJson.features.map(item => { useGeoJson.features.map(item => {
if (item.properties.type === '0001' && mapControl.area0001) { if (item.properties.type === '0001' && mapControl.area0001) {
arrGeoJson.push({ arrGeoJson.push({
@ -149,6 +180,7 @@ export const FeatureAirZone = props => {
}); });
useGeoJson.features = arrGeoJson; useGeoJson.features = arrGeoJson;
// 공역 생성 start
props.map.addSource('maine', { props.map.addSource('maine', {
type: 'geojson', type: 'geojson',
data: { data: {
@ -158,81 +190,33 @@ export const FeatureAirZone = props => {
props.map.addLayer({ props.map.addLayer({
id: 'maine', id: 'maine',
type: 'fill', type: 'fill',
source: 'maine', // reference the data source source: 'maine',
layout: {}, layout: {},
paint: { paint: {
'fill-color': ['get', 'color'], 'fill-color': ['get', 'color'],
'fill-opacity': 0.5 'fill-opacity': 0.5
} }
}); });
// 공역 생성 end
airPort.map(air => polyArea(air));
// 비행장 마커 생성
// useGeoJson.features = arrGeoJson; const markers = useGeoJson.features
// props.map.data.addGeoJson(useGeoJson); .filter(i => i.geometry.type === 'Point')
.map(i => {
// props.map.data.setStyle(feature => { const marker = new props.mapboxgl.Marker()
// var color; .setLngLat(i.geometry.coordinates)
.addTo(props.map);
// //0001 비행금지구역 #FF3648 marker.properties = i.properties;
// //0002 비행제한구역 #FFA1AA return marker;
// //0003 관제권(공항) #FFA800
// //0004 비행장(군사) #A16B00
// //0005 이착륙장(RC비행장) #AB40FF
// //0006 초경량비행장치 #009cad
// // 공역 색상 변경
// const type = feature.getProperty('type');
// if (type === '0001') {
// color = '#FF3648';
// } else if (type === '0002') {
// color = '#FFA1AA';
// } else if (type === '0003') {
// color = '#FFA800';
// } else if (type === '0004') {
// color = '#A16B00';
// } else if (type === '0005') {
// color = '#AB40FF';
// } else if (type === '0006') {
// color = '#009cad';
// }
// return {
// fillColor: color,
// strokeColor: color,
// strokeWeight: 0.7,
// icon: null
// };
// });
};
const featureAirEvent = () => {
props.map.data.addListener('click', function (e) {
// e.feature.setProperty('isColorful', true);
});
props.map.data.addListener('mouseover', function (e) {
const data = {};
data.coord = e.coord;
data.title = e.feature.property_name;
data.description = e.feature.property_description;
props.map.data.overrideStyle(e.feature, {
strokeWeight: 3
// icon: HOME_PATH +'/img/example/pin_spot.png'
}); });
infowindowOpen(data); // 격자 공역 생성
}); airPort.map(air => polyArea(air));
// 마우스 오버 이벤트 생성
props.map.data.addListener('mouseout', function (e) { featureAirEvent(markers);
props.map.data.revertStyle();
if (infoWindow) {
infoWindow.close();
}
});
}; };
// 격자 공역 셋팅 함수
const polyArea = air => { const polyArea = air => {
const polyArr = []; const polyArr = [];
const radius = air.buffer; const radius = air.buffer;
@ -374,7 +358,10 @@ export const FeatureAirZone = props => {
}; };
polyArr.push(EW); polyArr.push(EW);
if (props.map.getLayer(air.title)) {
props.map.removeLayer(air.title);
props.map.removeSource(air.title);
}
props.map.addSource(air.title, { props.map.addSource(air.title, {
type: 'geojson', type: 'geojson',
data: { data: {

12
test/pav-warning.js

@ -2,18 +2,20 @@ const { getConnection, writeData } = require('./pav-client');
const { getCoordsFormBetweenCoord, dumyData } = require('./pav-utils'); const { getCoordsFormBetweenCoord, dumyData } = require('./pav-utils');
// const host = "192.168.0.24" // const host = "192.168.0.24"
const host = 'localhost'; // const host = 'localhost';
// const host = '192.168.0.34'; // const host = '192.168.0.34';
// const port = 8082;
const host = '211.253.38.218';
const port = 8082; const port = 8082;
// 기본정보 // 기본정보
const prefix = 'PA'; const prefix = '';
const terminalId = 'SANDBOX-001'; const terminalId = '';
const pathSampleCoord = [ const pathSampleCoord = [
[37.5215, 126.605], [37.5215, 126.605],
[37.5215, 126.61], //비정상, 날릴 것 // [37.5215, 126.61], //비정상, 날릴 것
// [37.5215, 126.6082], 계획서 [37.5215, 126.6082], //계획서
[37.521, 126.6082], [37.521, 126.6082],
[37.521, 126.6057], [37.521, 126.6057],
[37.5205, 126.6057], [37.5205, 126.6057],

Loading…
Cancel
Save