|
|
@@ -0,0 +1,2204 @@
|
|
|
+let _size = [48, 48, 48, 48, 40, 32, 24, 22, 20, 18, 18];
|
|
|
+let _AtrdMap = new Map();
|
|
|
+let selectIncidentId = null;
|
|
|
+let _MarkerArr = [];
|
|
|
+
|
|
|
+const vmsWHMap = new Map();
|
|
|
+vmsWHMap.set('VMC1', {width: 400, height: 64});
|
|
|
+vmsWHMap.set('VMC2', {width: 384, height: 64});
|
|
|
+vmsWHMap.set('VMC3', {width: 288, height: 160});
|
|
|
+vmsWHMap.set('VMC4', {width: 256, height: 192});
|
|
|
+
|
|
|
+//시설물 유형
|
|
|
+// const _FacilityArray = ['cctv', 'vms', 'intersection', 'incident', 'traffic', 'parking', 'intersectionCamera', 'atrd'];
|
|
|
+const _FacilityArray = ['cctv', 'vms', 'incident', 'traffic', 'parking', 'atrd'];
|
|
|
+
|
|
|
+const g_color = new Map();
|
|
|
+g_color.set('LTC0', '#888888;');
|
|
|
+g_color.set('LTC1', '#2fba2c;');
|
|
|
+g_color.set('LTC2', '#ffc500;');
|
|
|
+g_color.set('LTC3', '#ee0000;');
|
|
|
+
|
|
|
+const CCTV_DISPLAY_TIME = 30 * 1000; // 영상 표출 시간
|
|
|
+const VMS_DISPLAY_TIME = 4 * 1000; // VMS 이미지 표출 시간
|
|
|
+const _TrafficListMap = new Map();
|
|
|
+let _MapHandler; //카카오 맵 핸들러
|
|
|
+let _Level = 6; //현재 줌레벨
|
|
|
+let _MarkerHandle;
|
|
|
+
|
|
|
+let _methodMap = new Map();
|
|
|
+_methodMap.set('cctv', getCctv);
|
|
|
+_methodMap.set('vms', getVms);
|
|
|
+_methodMap.set('incident', getIncident);
|
|
|
+// _methodMap.set('intersection', getIntersection);
|
|
|
+_methodMap.set('traffic', getAtrd);
|
|
|
+_methodMap.set('parking', getParking);
|
|
|
+
|
|
|
+$(()=>{
|
|
|
+ // Map 요소 ID로 생성
|
|
|
+ _MapHandler = new MapHandler('map');
|
|
|
+ _MapHandler.init();
|
|
|
+ _MarkerHandle = new MarkerManager([..._FacilityArray]);
|
|
|
+ _MarkerHandle.init();
|
|
|
+
|
|
|
+ // 시설물 유형 정보로 flag 값 세팅
|
|
|
+ if (_type) {
|
|
|
+ _MarkerHandle.setIsDraw(_type, true);
|
|
|
+ _MarkerHandle.setIsDrawList(_type, true);
|
|
|
+ _methodMap.get(_type)();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 범례 클릭 이벤트 및 색 변환
|
|
|
+ * */
|
|
|
+ $('.legend-bottom button').on('click', function (){
|
|
|
+ const target = $(this);
|
|
|
+ const legendIcon = target.children().eq(0);
|
|
|
+ const isShow = !legendIcon.hasClass('active');
|
|
|
+
|
|
|
+ const id = target.attr('id');
|
|
|
+ const type = id.replace('-legend', '');
|
|
|
+
|
|
|
+ let subType = null;
|
|
|
+ //
|
|
|
+ // if (type === 'intersection') {
|
|
|
+ // subType = 'intersectionCamera';
|
|
|
+ // }
|
|
|
+
|
|
|
+ if (type === 'traffic') {
|
|
|
+ subType = 'atrd';
|
|
|
+ getVertex();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ const markerArr = _MarkerHandle.findMarkerArr(type);
|
|
|
+ if (markerArr && markerArr.length <= 0){
|
|
|
+ _methodMap.get(type)();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ let classToggle = 'removeClass';
|
|
|
+ if (isShow === true) {
|
|
|
+ classToggle = 'addClass';
|
|
|
+ }
|
|
|
+
|
|
|
+ legendIcon[classToggle]('active');
|
|
|
+ target[classToggle]('active');
|
|
|
+ _MarkerHandle.showHideMarker(type, isShow);
|
|
|
+ if (subType) {
|
|
|
+ _MarkerHandle.showHideMarker(subType, isShow);
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 범례 호버 색 변환
|
|
|
+ * */
|
|
|
+ $('.legend-bottom ul li').hover((event)=>{
|
|
|
+ const iconDiv = $(event.currentTarget).children().eq(0);
|
|
|
+ const childDiv = iconDiv.children().eq(0);
|
|
|
+ if (!iconDiv.hasClass('active')) {
|
|
|
+ childDiv.addClass('hover');
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if (childDiv.hasClass('hover')) {
|
|
|
+ childDiv.removeClass('hover');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ (event)=>{
|
|
|
+ const iconDiv = $(event.currentTarget).children().eq(0);
|
|
|
+ const childDiv = iconDiv.children().eq(0);
|
|
|
+
|
|
|
+ if (!iconDiv.hasClass('active')) {
|
|
|
+ childDiv.removeClass('hover');
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if (childDiv.hasClass('hover')) {
|
|
|
+ childDiv.removeClass('hover');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 탭 호버 색 변환
|
|
|
+ * */
|
|
|
+ $('.left-list-area .list-tab > li').hover((event)=>{
|
|
|
+ const iconDiv = $(event.currentTarget);
|
|
|
+ const childDiv = iconDiv.children().eq(0);
|
|
|
+ if (!iconDiv.hasClass('active')) {
|
|
|
+ childDiv.addClass('hover');
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if (childDiv.hasClass('hover')) {
|
|
|
+ childDiv.removeClass('hover');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ (event)=>{
|
|
|
+ const iconDiv = $(event.currentTarget);
|
|
|
+ const childDiv = iconDiv.children().eq(0);
|
|
|
+ if (!iconDiv.hasClass('active')) {
|
|
|
+ childDiv.removeClass('hover');
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if (childDiv.hasClass('hover')) {
|
|
|
+ childDiv.removeClass('hover');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ //
|
|
|
+ // $('.tab-title > div').on('click', function(){
|
|
|
+ // const $spot = $('.list-content.spot');
|
|
|
+ // const $list = $('.list-content.list');
|
|
|
+ // let searchType = $('.tab-title > div.active').text();
|
|
|
+ // if (searchType === $(this).text()) return;
|
|
|
+ // $('.tab-title > div').toggleClass("active");
|
|
|
+ // searchType = $(this).text();
|
|
|
+ // let list;
|
|
|
+ // let spot;
|
|
|
+ // if (searchType === '지점 검색') {
|
|
|
+ // list = 'none';
|
|
|
+ // spot = 'block';
|
|
|
+ // $spot.html("");
|
|
|
+ // }
|
|
|
+ // else {
|
|
|
+ // list = 'block';
|
|
|
+ // spot = 'none';
|
|
|
+ // $('.list-content.list > li').css('display', 'block');
|
|
|
+ // }
|
|
|
+ //
|
|
|
+ // $('#search-box').val("");
|
|
|
+ // $list.css('display', list);
|
|
|
+ // $spot.css('display', spot);
|
|
|
+ // if (_MarkerArr.length > 0) {
|
|
|
+ // _MarkerArr.forEach((obj)=>{
|
|
|
+ // obj.setMap(null);
|
|
|
+ // });
|
|
|
+ // _MarkerArr = [];
|
|
|
+ // }
|
|
|
+ // })
|
|
|
+
|
|
|
+ //좌측 리스트 검색 이벤트 (리스트 명칭 또는 주소와 비교)
|
|
|
+ $('#search-box').on('keyup', function () {
|
|
|
+ const searchText = $(this).val();
|
|
|
+ const $list = $('.list-content.list > li');
|
|
|
+ if (!$list.length) return;
|
|
|
+ const $activeTab = $('.list-tab .active');
|
|
|
+ const id = $activeTab.attr('id');
|
|
|
+ let type = id.replace("-tab", "");
|
|
|
+ // if (type === 'intersection') type = 'intersectionCamera';
|
|
|
+
|
|
|
+ const markerArr = _MarkerHandle.findMarkerArr(type);
|
|
|
+ let showIdArr = [];
|
|
|
+ if (markerArr.length) {
|
|
|
+ showIdArr = markerArr.map((item)=>{
|
|
|
+ if (item.ADDR && item.ADDR.includes(searchText)) {
|
|
|
+ // if (type === 'intersectionCamera') {
|
|
|
+ // return 'intersection-' + item.prop.ixr_id;
|
|
|
+ // }
|
|
|
+ return type + '-' + item.ID;
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ for (let ii = 0; ii < $list.length; ii++) {
|
|
|
+ const li = $list.eq(ii);
|
|
|
+ if ($(this).val().length === 0) {
|
|
|
+ li.css('display', 'block');
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ let text = li.text().toLowerCase();
|
|
|
+ const liId = li.attr('id');
|
|
|
+ if (showIdArr.includes(liId)){
|
|
|
+ li.css('display', 'block');
|
|
|
+ }
|
|
|
+ else if (text.includes(searchText.toLowerCase())) {
|
|
|
+ li.css('display', 'block');
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ li.css('display', 'none');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+});
|
|
|
+
|
|
|
+/**
|
|
|
+ * 지점찾기 이벤트
|
|
|
+ * @param event
|
|
|
+ */
|
|
|
+function searchLocation(event) {
|
|
|
+ if (event && event.key !== 'Enter') {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (_MarkerHandle.selectedMarker) {
|
|
|
+ _MarkerHandle.selectedMarker.close();
|
|
|
+ }
|
|
|
+ $('.list-content.spot').empty();
|
|
|
+ const $search = $('.location-box input');
|
|
|
+ if (_MarkerArr.length > 0) {
|
|
|
+ _MarkerArr.forEach((obj)=>{
|
|
|
+ obj.setMap(null);
|
|
|
+ });
|
|
|
+ _MarkerArr = [];
|
|
|
+ }
|
|
|
+ const searchText = $search.val();
|
|
|
+ if (!searchText || !searchText.trim()) return;
|
|
|
+ const geoCoder = new kakao.maps.services.Geocoder();
|
|
|
+ geoCoder.addressSearch('경북 포항시 '+searchText, function(result, status){
|
|
|
+ if (status === 'OK' && result && result.length > 0) {
|
|
|
+ let str = "";
|
|
|
+ const setMap = new Map();
|
|
|
+
|
|
|
+ const bounds = new kakao.maps.LatLngBounds();
|
|
|
+ let minX;
|
|
|
+ let minY;
|
|
|
+ let maxX;
|
|
|
+ let maxY;
|
|
|
+
|
|
|
+ result.forEach((obj, idx)=>{
|
|
|
+ let addr = obj.address_name;
|
|
|
+ if (obj.x && obj.y) {
|
|
|
+ const position = getKakaoPosition(obj.y, obj.x);
|
|
|
+ let marker = new kakao.maps.Marker({
|
|
|
+ position : position,
|
|
|
+ title : addr ,
|
|
|
+ content : addr
|
|
|
+ });
|
|
|
+
|
|
|
+ new kakao.maps.event.addListener(marker, 'click', function() {
|
|
|
+ moveLocation(obj.x, obj.y, idx);
|
|
|
+ })
|
|
|
+ if (!minX) {
|
|
|
+ minX = obj.x;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!maxX) {
|
|
|
+ maxX = obj.x;
|
|
|
+ }
|
|
|
+ if (!minY) {
|
|
|
+ minY = obj.y;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!maxY) {
|
|
|
+ maxY = obj.y;
|
|
|
+ }
|
|
|
+
|
|
|
+ minX = minX <= obj.x ? minX : obj.x;
|
|
|
+ maxX = maxX >= obj.x ? maxX : obj.x;
|
|
|
+ minY = minY <= obj.y ? minY : obj.y;
|
|
|
+ maxY = maxY >= obj.y ? maxY : obj.y;
|
|
|
+
|
|
|
+ marker.setMap(_MapHandler.map);
|
|
|
+ _MarkerArr.push(marker);
|
|
|
+ setMap.set(addr, obj);
|
|
|
+
|
|
|
+ str+= `<li id="spot-${idx}" onclick="moveLocation(${obj.x}, ${obj.y}, ${idx})">
|
|
|
+ ${obj.address_name}
|
|
|
+ </li>`;
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (minX && minY && maxX && maxY) {
|
|
|
+ bounds.extend(new kakao.maps.LatLng(minY, minX));
|
|
|
+ bounds.extend(new kakao.maps.LatLng(maxY, maxX));
|
|
|
+ _MapHandler.setBounds(bounds);
|
|
|
+ $('.list-content.spot').html(str);
|
|
|
+ getVertex();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, {page : 1, size: 30});
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 지점 클릭 위치 이동
|
|
|
+ * @param xCoordinate x좌표
|
|
|
+ * @param yCoordinate y좌표
|
|
|
+ * @param listIndex 지점 선택 인덱스
|
|
|
+ */
|
|
|
+function moveLocation(xCoordinate, yCoordinate, listIndex) {
|
|
|
+ if (_MarkerHandle.selectedMarker) {
|
|
|
+ _MarkerHandle.selectedMarker.close();
|
|
|
+ }
|
|
|
+ const position = getKakaoPosition(yCoordinate, xCoordinate);
|
|
|
+ _MapHandler.setCenter(position);
|
|
|
+ _MapHandler.setLevel(3);
|
|
|
+ $('.list-content.spot > li.click').removeClass('click');
|
|
|
+ $('#spot-' +listIndex).addClass('click');
|
|
|
+ getVertex();
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * cctv 데이터 가져오기
|
|
|
+ */
|
|
|
+function getCctv() {
|
|
|
+ getDataAsync('/api/traffic/cctv-list', 'POST', null, null, (cctvData)=>{
|
|
|
+ getDataAsync('/api/itcs/detail-list', 'POST', null, null, (itcsData)=> {
|
|
|
+ console.log(cctvData.length);
|
|
|
+ let cctvTotalData = [...cctvData];
|
|
|
+ console.log(itcsData.length);
|
|
|
+ if (itcsData && itcsData.length > 0) {
|
|
|
+ itcsData.forEach((itcs)=>{
|
|
|
+ let obj = intersectionCameraTransferToCctv(itcs);
|
|
|
+ cctvTotalData.push(obj);
|
|
|
+ })
|
|
|
+ }
|
|
|
+ receiveMarkerData(cctvTotalData, TbCCtvObj, 'cctv');
|
|
|
+ })
|
|
|
+ }, null);
|
|
|
+}
|
|
|
+
|
|
|
+function intersectionCameraTransferToCctv(itcs) {
|
|
|
+ return {
|
|
|
+ cctv_mngm_nmbr: itcs.cmra_id + '_' + itcs.drct_dvsn_cd,
|
|
|
+ cctv_ctlr_id: itcs.cmra_id + '_' + itcs.drct_dvsn_cd,
|
|
|
+ cctv_ctlr_ip: null,
|
|
|
+ cctv_ctlr_port: null,
|
|
|
+ cctv_capt_ip: null,
|
|
|
+ cctv_capt_port: null,
|
|
|
+ cctv_fibr_ip: null,
|
|
|
+ cctv_encd_ip: null,
|
|
|
+ strm_svr_ip: null,
|
|
|
+ strm_svr_port: null,
|
|
|
+ strm_sesn_nm: null,
|
|
|
+ x_crdn: itcs.cmra_x_crdn,
|
|
|
+ y_crdn: itcs.cmra_y_crdn,
|
|
|
+ istl_lctn_nm: itcs.drct_lctn,
|
|
|
+ istl_lctn_addr: itcs.istl_lctn_addr,
|
|
|
+ cctv_chnl: 0,
|
|
|
+ del_yn: "N",
|
|
|
+ frst_regr_nmbr: null,
|
|
|
+ frst_rgst_dt: null,
|
|
|
+ last_crpr_nmbr: null,
|
|
|
+ last_crct_dt: null,
|
|
|
+ link_id: null,
|
|
|
+ node_id: null,
|
|
|
+ cctv_id: null,
|
|
|
+ rely_port: null,
|
|
|
+ strm_rtsp_addr: null,
|
|
|
+ strm_rtmp_addr: null,
|
|
|
+ strm_http_addr: itcs.hmpg_cmra_url,
|
|
|
+ strm_stor_addr: null,
|
|
|
+ area_cd: null,
|
|
|
+ cctv_type: null,
|
|
|
+ cctv_sbst_imgn: null,
|
|
|
+ cctv_sbst_dspl_yn: null,
|
|
|
+ cctv_lc: null,
|
|
|
+ cmra_id: null,
|
|
|
+ cmra_pswd: null,
|
|
|
+ cmra_chnl: null,
|
|
|
+ cmra_modl: null,
|
|
|
+ full_strm_sesn_nm: null,
|
|
|
+ cmra_port: null,
|
|
|
+ hmpg_dspl_en: 1,
|
|
|
+ mac_addr: null,
|
|
|
+ serial_no: null,
|
|
|
+ tta_cnfn_yn: null
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * vms 데이터 가져오기
|
|
|
+ */
|
|
|
+function getVms() {
|
|
|
+ getDataAsync('/api/traffic/vms-list', 'POST', null, null, (jsonData)=>{
|
|
|
+ if (jsonData && jsonData.length > 0) {
|
|
|
+ jsonData.sort((a, b)=>{
|
|
|
+ return a.vms_nm > b.vms_nm ? 1 : a.vms_nm < b.vms_nm ? -1 : 0;
|
|
|
+ })
|
|
|
+ // receiveFacilityData(jsonData, TbVmsObj,'vms');
|
|
|
+ }
|
|
|
+ receiveMarkerData(jsonData, TbVmsObj, 'vms');
|
|
|
+ }, null);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 돌발정보
|
|
|
+ */
|
|
|
+function getIncident () {
|
|
|
+ getDataAsync('/api/traffic/incident-list', 'POST', null, null, (jsonData)=>{
|
|
|
+ receiveMarkerData(jsonData, TbIncdObj, 'incident');
|
|
|
+ }, null);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 스마트교차로
|
|
|
+ */
|
|
|
+function getIntersection() {
|
|
|
+ getDataAsync('/api/itcs/list', 'POST', null, null, (jsonData)=>{
|
|
|
+ if (jsonData && jsonData.length > 0) {
|
|
|
+ jsonData.sort((a, b)=>{
|
|
|
+ return a.ixr_nm > b.ixr_nm ? 1 : a.ixr_nm < b.ixr_nm ? -1 : 0;
|
|
|
+ });
|
|
|
+ let data = [];
|
|
|
+ jsonData.forEach((obj)=>{
|
|
|
+ if (obj.detail.length > 0) {
|
|
|
+ data.push(obj);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ receiveMarkerData(data, IntersectionObj, 'intersection');
|
|
|
+ }
|
|
|
+ }, null);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 주차정보
|
|
|
+ */
|
|
|
+function getParking() {
|
|
|
+ getDataAsync('/api/traffic/parking-list', 'POST', null, null, (jsonData)=>{
|
|
|
+ receiveMarkerData(jsonData, TbParkingObj, 'parking');
|
|
|
+ }, null);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 간선도로 정보
|
|
|
+ */
|
|
|
+function getAtrd() {
|
|
|
+ getDataAsync("/api/traffic/atrd-vertex-all", "POST", null, null, (jsonData)=>{
|
|
|
+ if (jsonData && jsonData.length > 0) {
|
|
|
+ _AtrdMap = new Map();
|
|
|
+ jsonData.forEach((obj)=>{
|
|
|
+ _TrafficListMap.set(obj.level, obj.list);
|
|
|
+ obj.list.forEach((atrd)=>{
|
|
|
+ const key = atrd.atrd_id +'_' + atrd.drct_cd +'_' + obj.level;
|
|
|
+ let atrdArr = _AtrdMap.get(key);
|
|
|
+ if (!atrdArr) {
|
|
|
+ _AtrdMap.set(key, []);
|
|
|
+ let atrdTemp = {...atrd};
|
|
|
+ atrdTemp.ID = key;
|
|
|
+ const atrdObj = new TbAtrdObj(atrdTemp);
|
|
|
+ atrdObj.init();
|
|
|
+ _MarkerHandle.markerMaps.get('atrd').markers.push(atrdObj);
|
|
|
+ }
|
|
|
+ _AtrdMap.get(key).push(atrd);
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ getVertex();
|
|
|
+ }
|
|
|
+ }, null);
|
|
|
+
|
|
|
+ getDataAsync('/api/traffic/atrd-list', 'POST', null, null, (jsonData)=>{
|
|
|
+ let emptyStr = '<div class="empty">소통정보 리스트가 없습니다.</div>'
|
|
|
+ let listStr = "";
|
|
|
+ let mobileStr = "";
|
|
|
+
|
|
|
+ if (jsonData) {
|
|
|
+ const atrdList = Object.keys(jsonData).sort().reduce(
|
|
|
+ (newObj,key) => {
|
|
|
+ newObj[key] = jsonData[key];
|
|
|
+ return newObj;
|
|
|
+ },
|
|
|
+ {}
|
|
|
+ );
|
|
|
+
|
|
|
+ for (let key in atrdList){
|
|
|
+ let list = jsonData[key];
|
|
|
+ if (list && list.length === 2) {
|
|
|
+ const upHill = list[list.findIndex(obj => obj.drct_cd === '0')];
|
|
|
+ const downHill = list[list.findIndex(obj => obj.drct_cd === '1')];
|
|
|
+ const upHillId = upHill.atrd_id;
|
|
|
+ const downHillId = downHill.atrd_id;
|
|
|
+
|
|
|
+ listStr += `<li id="atrd_${upHillId}_${downHillId}" onclick="atrdClickEvent('${upHillId}', '${downHillId}')">
|
|
|
+ ${key}
|
|
|
+ </li><ul id="${upHillId}_${downHillId}"></ul>`
|
|
|
+ mobileStr += `<option value="${upHillId}_${downHillId}">${key}</option>`
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const $mobileSelect = $('.mobile-select');
|
|
|
+ $mobileSelect.append($(mobileStr));
|
|
|
+ $mobileSelect.on('change', function(){
|
|
|
+ const ids = $(this).val();
|
|
|
+ if (ids && ids !== '-') {
|
|
|
+ const idArr = ids.split('_');
|
|
|
+ atrdClickEvent(idArr[0], idArr[1]);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ let array = _MarkerHandle.selectedAtrd;
|
|
|
+ if (array.length > 0) {
|
|
|
+ array.forEach((atrdId)=>{
|
|
|
+ const atrdObj = _MarkerHandle.findMarkerObj('atrd', atrdId);
|
|
|
+ if (atrdObj) {
|
|
|
+ atrdObj.marker.setMap(null);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ _MarkerHandle.selectedAtrd = [];
|
|
|
+ // getVertex();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ listStr = emptyStr;
|
|
|
+ }
|
|
|
+ const listSection = $('.left-list-area .list-content.list');
|
|
|
+ listSection.empty();
|
|
|
+ listSection.html(listStr);
|
|
|
+ });
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 소통정보 가져오기
|
|
|
+ */
|
|
|
+function getVertex() {
|
|
|
+ let level = _MapHandler.getLevel();
|
|
|
+ const bounds = _MapHandler.getBounds();
|
|
|
+ const swLatLng = bounds.getSouthWest();
|
|
|
+ const neLatLng = bounds.getNorthEast();
|
|
|
+ const data = {
|
|
|
+ levl : level,
|
|
|
+ swLat : swLatLng.getLat(),
|
|
|
+ neLat : neLatLng.getLat(),
|
|
|
+ swLng : swLatLng.getLng(),
|
|
|
+ neLng : neLatLng.getLng(),
|
|
|
+ }
|
|
|
+
|
|
|
+ getDataAsync('/api/traffic/vertex-list', 'POST', data, null, (jsonData)=>{
|
|
|
+ let markerArr = _MarkerHandle.findMarkerArr('traffic');
|
|
|
+ if (markerArr.length > 0) {
|
|
|
+ markerArr.forEach((obj) => {
|
|
|
+ obj.setVisibleMarker(false);
|
|
|
+ if (obj.infoWindow) {
|
|
|
+ obj.infoWindow.setMap(null);
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ _MarkerHandle.findMarkerArr('traffic').markers = [];
|
|
|
+ }
|
|
|
+ if (jsonData && jsonData.length > 0) {
|
|
|
+ let upHill = null;
|
|
|
+ let dowHill = null;
|
|
|
+ let upHillId = null;
|
|
|
+ let downHillId = null;
|
|
|
+ let roadIdArr = [];
|
|
|
+ let uRoadIdArr = [];
|
|
|
+ let dRoadIdArr = [];
|
|
|
+ if (_MarkerHandle.selectedAtrd.length > 0 && _MarkerHandle.isDraw('traffic')) {
|
|
|
+ const selectedAtrd = _MarkerHandle.selectedAtrd;
|
|
|
+ upHill = _MarkerHandle.findMarkerObj('atrd', selectedAtrd[0]);
|
|
|
+ dowHill = _MarkerHandle.findMarkerObj('atrd', selectedAtrd[1]);
|
|
|
+ upHill.setImage(0);
|
|
|
+ dowHill.setImage(1);
|
|
|
+ upHill.marker.setMap(_MapHandler.map);
|
|
|
+ dowHill.marker.setMap(_MapHandler.map);
|
|
|
+ const upHillArr = _AtrdMap.get(selectedAtrd[0]);
|
|
|
+ const downHillArr = _AtrdMap.get(selectedAtrd[1]);
|
|
|
+ const roadArr = [...upHillArr, ...downHillArr];
|
|
|
+ upHillId = selectedAtrd[0].substring(0, selectedAtrd[0].indexOf('_'));
|
|
|
+ downHillId = selectedAtrd[1].substring(0, selectedAtrd[1].indexOf('_'));
|
|
|
+ roadArr.forEach((obj)=>{
|
|
|
+ if (obj.atrd_id === upHillId) {
|
|
|
+ uRoadIdArr.push(obj);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ dRoadIdArr.push(obj);
|
|
|
+ }
|
|
|
+ roadIdArr.push(obj.road_id.toString());
|
|
|
+ });
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ const $ul = $(`#${upHillId}_${downHillId}`);
|
|
|
+
|
|
|
+ const trafficArr = [];
|
|
|
+ jsonData.forEach((obj)=>{
|
|
|
+ const trafficObj = new TrafficObj(obj);
|
|
|
+ if (roadIdArr.length > 0) {
|
|
|
+ if (roadIdArr.includes(trafficObj.ID.toString())) {
|
|
|
+ trafficObj.polyBackLine.setOptions({
|
|
|
+ strokeColor : 'black',
|
|
|
+ });
|
|
|
+ trafficArr.push(obj);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ _MarkerHandle.markerMaps.get('traffic').markers.push(trafficObj);
|
|
|
+ })
|
|
|
+ if ($ul[0]) {
|
|
|
+ $ul.empty();
|
|
|
+ let uRoadObjArr = [];
|
|
|
+ let dRoadObjArr = [];
|
|
|
+ let upStr = '';
|
|
|
+ let downStr = '';
|
|
|
+ for (let ii= uRoadIdArr.length - 1; ii >= 0; ii--) {
|
|
|
+ const idx = trafficArr.findIndex(obj=> obj.roadway_id === uRoadIdArr[ii].road_id.toString());
|
|
|
+ if (idx >= 0) {
|
|
|
+ uRoadObjArr.push(trafficArr[idx])
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ uRoadObjArr.forEach((obj, idx)=>{
|
|
|
+ const {cmtr_grad_cd, strt_nm_node, end_nm_node, sped, trvl_hh, roadway_id} = obj;
|
|
|
+ const isEnd = (uRoadObjArr.length - 1) === idx;
|
|
|
+ let addClass = "";
|
|
|
+ if (_MarkerHandle.trafficObj && roadway_id === _MarkerHandle.trafficObj) {
|
|
|
+ addClass = "on";
|
|
|
+ }
|
|
|
+ //upStr +=`<div class="traffic-list" onmouseover="showSelectLine('${roadway_id}', true, ${isEnd})" onmouseleave="showSelectLine('${roadway_id}', false, ${isEnd})">
|
|
|
+ upStr +=`<div class="traffic-list ${addClass}" onclick="selectRoadPoint('${roadway_id}')">
|
|
|
+ <div>
|
|
|
+ <div class="up arrow ${cmtr_grad_cd}"></div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <div>${end_nm_node}</div>
|
|
|
+ <div>${sped}km/h 약 ${trvl_hh}분</div>
|
|
|
+ </div>
|
|
|
+ </div>`
|
|
|
+ if (isEnd) {
|
|
|
+ upStr+= `<div style="margin-left: 35px; padding-top: 10px; padding-bottom: 10px;">${strt_nm_node}</div>`;
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ for (let ii= 0; ii < dRoadIdArr.length; ii++) {
|
|
|
+ const idx = trafficArr.findIndex(obj=> obj.roadway_id === dRoadIdArr[ii].road_id.toString());
|
|
|
+ if (idx >= 0) {
|
|
|
+ dRoadObjArr.push(trafficArr[idx]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ dRoadObjArr.forEach((obj, idx)=>{
|
|
|
+ const {sped, trvl_hh, cmtr_grad_cd, strt_nm_node, end_nm_node, roadway_id} = obj;
|
|
|
+ let isStart = idx === 0;
|
|
|
+ // downStr +=`<div class="traffic-list" onmouseover="showSelectLine('${roadway_id}', true, ${isStart})" onmouseleave="showSelectLine('${roadway_id}', false, ${isStart})">
|
|
|
+ let addClass = "";
|
|
|
+ if (_MarkerHandle.trafficObj && roadway_id === _MarkerHandle.trafficObj) {
|
|
|
+ addClass = "on";
|
|
|
+ }
|
|
|
+ downStr +=`<div class="traffic-list ${addClass}" onclick="selectRoadPoint('${roadway_id}')">
|
|
|
+ <div>
|
|
|
+ <div class="down arrow ${cmtr_grad_cd}"></div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <div>${strt_nm_node}</div>
|
|
|
+ <div>${sped}km/h 약 ${trvl_hh}분</div>
|
|
|
+ </div>
|
|
|
+ </div>`
|
|
|
+ if (dRoadObjArr.length - 1 === idx) {
|
|
|
+ downStr += `<div style="margin-left: 35px; padding-top: 10px; padding-bottom: 10px;">${end_nm_node}</div>`
|
|
|
+ }
|
|
|
+ })
|
|
|
+ let str = `<li>
|
|
|
+ <div>
|
|
|
+ <div>
|
|
|
+ ${upStr}
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ ${downStr}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </li>`;
|
|
|
+
|
|
|
+ $ul.html(str);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+let timer = null;
|
|
|
+let infoWindow = null;
|
|
|
+function selectRoadPoint(id) {
|
|
|
+ if (timer) {
|
|
|
+ clearTimeout(timer);
|
|
|
+ if (infoWindow) {
|
|
|
+ infoWindow.setMap(null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const trafficObj = _MarkerHandle.findMarkerObj('traffic', id);
|
|
|
+ _MarkerHandle.trafficObj = id;
|
|
|
+
|
|
|
+ const xCoordinateArr = trafficObj.obj.x_crdn.split(',');
|
|
|
+ const yCoordinateArr = trafficObj.obj.y_crdn.split(',');
|
|
|
+ const x = xCoordinateArr[Math.round(xCoordinateArr.length / 2)];
|
|
|
+ const y = yCoordinateArr[Math.round(yCoordinateArr.length / 2)];
|
|
|
+ let position = getKakaoPosition(y, x);
|
|
|
+
|
|
|
+ _MapHandler.map.setCenter(position);
|
|
|
+ getVertex();
|
|
|
+
|
|
|
+ trafficObj.polyBackLine.setOptions({
|
|
|
+ strokeColor : '#FF00FF',
|
|
|
+ });
|
|
|
+
|
|
|
+
|
|
|
+ const imageSize = new kakao.maps.Size(19, 27);
|
|
|
+ const imageOffset = new kakao.maps.Point(8.5, 27);
|
|
|
+ const imageOption = {
|
|
|
+ offset: imageOffset,
|
|
|
+ alt : trafficObj.NAME,
|
|
|
+ };
|
|
|
+
|
|
|
+ let markerImage = new kakao.maps.MarkerImage('/images/icon/select_position.png', imageSize, imageOption);
|
|
|
+ infoWindow = new kakao.maps.Marker({
|
|
|
+ position: position,
|
|
|
+ image: markerImage,
|
|
|
+ zIndex: 99999,
|
|
|
+ });
|
|
|
+ infoWindow.setMap(_MapHandler.map);
|
|
|
+ timer = setTimeout(()=>{
|
|
|
+ infoWindow.setMap(null);
|
|
|
+ }, 2000);
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+function showSelectLine(id, isShow, isEnd) {
|
|
|
+ const trafficObj = _MarkerHandle.findMarkerObj('traffic', id);
|
|
|
+ if (trafficObj.infoWindow) trafficObj.infoWindow.setMap(null);
|
|
|
+ if (isShow) {
|
|
|
+ const xCoordinateArr = trafficObj.obj.x_crdn.split(',');
|
|
|
+ const yCoordinateArr = trafficObj.obj.y_crdn.split(',');
|
|
|
+ let position = getKakaoPosition(yCoordinateArr[0], xCoordinateArr[0]);
|
|
|
+ if (isEnd) {
|
|
|
+ const lastYIdx = yCoordinateArr.length - 1;
|
|
|
+ const lastXIdx = xCoordinateArr.length - 1;
|
|
|
+ position = getKakaoPosition(yCoordinateArr[lastYIdx], xCoordinateArr[lastXIdx])
|
|
|
+ }
|
|
|
+ const {cmtr_grad_cd, grad_nm, strt_nm_node, end_nm_node, trvl_hh, sped} = trafficObj.obj;
|
|
|
+ const iwContent =
|
|
|
+ `<div class="trafficPop">
|
|
|
+ <div class="traffic-speed ${cmtr_grad_cd}">
|
|
|
+ <span class="traffic-name">${trafficObj.NAME}</span>
|
|
|
+ <span class="traffic-speed-info border-back ${cmtr_grad_cd}">${grad_nm}</span>
|
|
|
+ </div>
|
|
|
+ <div class="traffic-info">
|
|
|
+ <span>${strt_nm_node} → ${end_nm_node}</span>
|
|
|
+ <br>
|
|
|
+ <span>소요시간 : </span>
|
|
|
+ <span class="${cmtr_grad_cd}">약 ${textFormat(trvl_hh)}분 </span>
|
|
|
+ <span> 속도 : </span>
|
|
|
+ <span class="${cmtr_grad_cd}">약 ${textFormat(sped)}km/h</span>
|
|
|
+ </div>
|
|
|
+ </div>`;
|
|
|
+ trafficObj.infoWindow = new kakao.maps.CustomOverlay({
|
|
|
+ clickable: true,
|
|
|
+ position: position,
|
|
|
+ content: iwContent,
|
|
|
+ xAnchor: -0.05,
|
|
|
+ yAnchor: 1.1,
|
|
|
+ zIndex: 999
|
|
|
+ });
|
|
|
+
|
|
|
+ trafficObj.polyLine.setOptions({strokeColor: '#0000FF'});
|
|
|
+ trafficObj.infoWindow.setMap(_MapHandler.map);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ trafficObj.polyLine.setOptions({strokeColor: g_color.get(trafficObj.obj.cmtr_grad_cd)});
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 간선도로 클릭 이벤트
|
|
|
+ * @param AupHillId 상행 ID
|
|
|
+ * @param AdownHillId 하행 ID
|
|
|
+ */
|
|
|
+function atrdClickEvent(AupHillId, AdownHillId) {
|
|
|
+ if (_MarkerHandle.trafficObj) {
|
|
|
+ _MarkerHandle.trafficObj = null;
|
|
|
+ }
|
|
|
+ if (! _MarkerHandle.findMarkerArr('atrd').length) {
|
|
|
+ return alert('도로정보를 불러오는 중입니다.');
|
|
|
+ }
|
|
|
+
|
|
|
+ if (_MarkerHandle.selectedAtrd.length > 0) {
|
|
|
+ _MarkerHandle.selectedAtrd.forEach((atrdId)=>{
|
|
|
+ _MarkerHandle.findMarkerObj('atrd', atrdId).marker.setMap(null);
|
|
|
+ })
|
|
|
+ }
|
|
|
+ _MarkerHandle.selectedAtrd = [];
|
|
|
+ const isDrawList = _MarkerHandle.isDrawList('traffic');
|
|
|
+ const $selectedLi = $('.left-list-area .list-content.list > li.click');
|
|
|
+ if (isDrawList && $selectedLi) {
|
|
|
+ $selectedLi.removeClass('click');
|
|
|
+ }
|
|
|
+
|
|
|
+ //상행, 하행 ID 가 있다면 실행
|
|
|
+ if (AupHillId && AdownHillId) {
|
|
|
+ const $selectLi = $('#atrd_' + AupHillId + "_" + AdownHillId);
|
|
|
+ $selectLi.addClass('click');
|
|
|
+ $selectLi.focus();
|
|
|
+ let level = getAtrdLevel(_Level);
|
|
|
+ let upHill = _MarkerHandle.findMarkerObj('atrd', AupHillId + '_0_' + level);
|
|
|
+ let downHill = _MarkerHandle.findMarkerObj('atrd', AdownHillId + '_1_' + level);
|
|
|
+
|
|
|
+ const bounds = new kakao.maps.LatLngBounds();
|
|
|
+ bounds.extend(new kakao.maps.LatLng(upHill.prop.y_crdn_min, upHill.prop.x_crdn_min));
|
|
|
+ bounds.extend(new kakao.maps.LatLng(upHill.prop.y_crdn_max, upHill.prop.x_crdn_max));
|
|
|
+ bounds.extend(new kakao.maps.LatLng(downHill.prop.y_crdn_min, downHill.prop.x_crdn_min));
|
|
|
+ bounds.extend(new kakao.maps.LatLng(downHill.prop.y_crdn_max, downHill.prop.x_crdn_max));
|
|
|
+ _MapHandler.setBounds(bounds);
|
|
|
+ let boundAfterLevel = getAtrdLevel(_Level);
|
|
|
+
|
|
|
+ _MarkerHandle.selectedAtrd = [AupHillId + '_0_' + boundAfterLevel, AdownHillId + '_1_' + boundAfterLevel];
|
|
|
+ getVertex();
|
|
|
+ if ($('.list-content > ul.on')[0]) {
|
|
|
+ $('.list-content > ul.on').removeClass('on');
|
|
|
+ }
|
|
|
+ $(`#${AupHillId}_${AdownHillId}`).addClass('on');
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 간선도로 레벨 설정
|
|
|
+ * @param level 현재 레벨
|
|
|
+ * @returns {number} 데이터 레벨
|
|
|
+ */
|
|
|
+function getAtrdLevel(level) {
|
|
|
+ if (level >= 8) {
|
|
|
+ level = 7;
|
|
|
+ }
|
|
|
+ else if (level >= 6) {
|
|
|
+ level = 6;
|
|
|
+ }
|
|
|
+ return level;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 마커 객체
|
|
|
+ */
|
|
|
+class MarkerObj {
|
|
|
+ constructor({ID, NAME, X_CRDN, Y_CRDN, URL, TYPE, IMAGE, IMAGE_TYPE, DATA, ADDR}) {
|
|
|
+ this.ID = ID;
|
|
|
+ this.NAME = NAME;
|
|
|
+ this.X_CRDN = X_CRDN;
|
|
|
+ this.Y_CRDN = Y_CRDN;
|
|
|
+ this.URL = URL;
|
|
|
+ this.type = TYPE;
|
|
|
+ this.ADDR = ADDR;
|
|
|
+ this.marker = null;
|
|
|
+ this.infoWindow = null;
|
|
|
+ this.iwContent = null;
|
|
|
+ this.isClick = false;
|
|
|
+ this.image = IMAGE;
|
|
|
+ this.imageType = IMAGE_TYPE;
|
|
|
+ this.timer = null;
|
|
|
+ this.phaseArray = [];
|
|
|
+ this.prop = {...DATA};
|
|
|
+ this.size = [48, 48, 48, 48, 40, 32, 24, 22, 20, 18, 18];
|
|
|
+ this.atrdSize = [48, 48, 48, 48, 48, 48, 48, 24, 24, 24, 24];
|
|
|
+ this.imageOnOff = ['cctv', 'incident', 'vms', 'parking'];
|
|
|
+ }
|
|
|
+
|
|
|
+ //스마트교차로 카메라는 카메라 방향별로 이미지를 돌려야하므로 두개 만드는 방식이 다름
|
|
|
+ init () {
|
|
|
+ const position = getKakaoPosition(this.Y_CRDN, this.X_CRDN);
|
|
|
+ // if (this.type !== 'intersectionCamera') {
|
|
|
+ const imageLocation = this.image + this.imageType + '.png';
|
|
|
+ const { imageSize, imageOption } = this.getImageOptions();
|
|
|
+ let markerImage = new kakao.maps.MarkerImage(imageLocation, imageSize, imageOption);
|
|
|
+ this.marker = new kakao.maps.Marker({
|
|
|
+ position: position,
|
|
|
+ image: markerImage,
|
|
|
+ zIndex: 5,
|
|
|
+ title: this.NAME,
|
|
|
+ });
|
|
|
+
|
|
|
+ const _self = this;
|
|
|
+
|
|
|
+ //마커 클릭이벤트 등록
|
|
|
+ new kakao.maps.event.addListener(this.marker, 'click', function() {
|
|
|
+ _self.click();
|
|
|
+ });
|
|
|
+ // }
|
|
|
+ // else {
|
|
|
+ // const content = $('<div id="camera_'+this.ID+'" title="'+this.NAME+'">');
|
|
|
+ // const angle = Number(this.prop.cmra_angn);
|
|
|
+ // content.css(
|
|
|
+ // {
|
|
|
+ // width: '48px',
|
|
|
+ // height: '48px',
|
|
|
+ // backgroundImage:'url(/images/icon/intersection-cctv.png)',
|
|
|
+ // backgroundSize : '48px 48px',
|
|
|
+ // backgroundRepeat: 'no-repeat',
|
|
|
+ // backgroundPosition : 'center',
|
|
|
+ // transform : 'rotate(' + angle +'deg)'
|
|
|
+ // });
|
|
|
+ //
|
|
|
+ // this.marker = new kakao.maps.CustomOverlay({
|
|
|
+ // content: content[0],
|
|
|
+ // position: position,
|
|
|
+ // zindex: 15,
|
|
|
+ // });
|
|
|
+ //
|
|
|
+ // const linePath1 = [this.prop.start_x, this.prop.start_y]
|
|
|
+ // const linePath2 = [this.prop.end_x, this.prop.end_y];
|
|
|
+ // const color = ['#888888', '#15B337', '#15B337', '#15B337', '#FFAA00', '#FFAA00', '#EB260C', '#EB260C', '#EB260C'];
|
|
|
+ // this.polyLine = new kakao.maps.Polyline({
|
|
|
+ // path: [
|
|
|
+ // getKakaoPosition(linePath1[1], linePath1[0]),
|
|
|
+ // getKakaoPosition(linePath2[1], linePath2[0]),
|
|
|
+ // ],
|
|
|
+ // strokeWeight: 10,
|
|
|
+ // strokeColor: color[this.prop.acrd_los],
|
|
|
+ // strokeOpacity: 1,
|
|
|
+ // strokeStyle: 'solid',
|
|
|
+ // endArrow: true,
|
|
|
+ // name : this.NAME,
|
|
|
+ // });
|
|
|
+ //
|
|
|
+ // if (_Level <= 2 && _MarkerHandle.isDraw('intersectionCamera')){
|
|
|
+ // marker.setMap(_MapHandler.map);
|
|
|
+ // this.polyLine.setMap(_MapHandler.map);
|
|
|
+ // }
|
|
|
+ //
|
|
|
+ // content.on('click', ()=> {
|
|
|
+ // this.click();
|
|
|
+ // });
|
|
|
+ // }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ //레벨별 이미지 사이즈 변경
|
|
|
+ setImage (type) {
|
|
|
+ const imageLocation = this.image + type + '.png';
|
|
|
+ const { imageSize, imageOption } = this.getImageOptions();
|
|
|
+
|
|
|
+ let markerImage = new kakao.maps.MarkerImage(imageLocation, imageSize, imageOption);
|
|
|
+ this.marker.setImage(markerImage);
|
|
|
+ }
|
|
|
+
|
|
|
+ //현재 레벨별 이미지 Option 값
|
|
|
+ getImageOptions() {
|
|
|
+ let size = this.size[_Level];
|
|
|
+ if (this.isClick) {
|
|
|
+ size = size * 1.5;
|
|
|
+ }
|
|
|
+ let offsetX = size/2;
|
|
|
+ let offsetY = size/2;
|
|
|
+
|
|
|
+ if (this.type === 'atrd') {
|
|
|
+ size = this.atrdSize[_Level];
|
|
|
+ offsetX = size/2;
|
|
|
+ offsetY = size;
|
|
|
+ }
|
|
|
+
|
|
|
+ const imageSize = new kakao.maps.Size(size, size);
|
|
|
+ const imageOffset = new kakao.maps.Point(offsetX, offsetY);
|
|
|
+ const imageOption = {
|
|
|
+ offset: imageOffset,
|
|
|
+ alt : this.NAME,
|
|
|
+ };
|
|
|
+ return {imageSize : imageSize, imageOption : imageOption};
|
|
|
+ }
|
|
|
+
|
|
|
+ //클릭 이벤트
|
|
|
+ async click() {
|
|
|
+ const selectObj = _MarkerHandle.selectedMarker;
|
|
|
+ if (selectObj) {
|
|
|
+ if (selectObj === this) {
|
|
|
+ // if (selectObj.type !== 'intersection' || (selectObj.type === 'intersection' && _Level <= 2)) {
|
|
|
+ return;
|
|
|
+ // }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 선택 마커 종료
|
|
|
+ selectObj.close();
|
|
|
+ }
|
|
|
+
|
|
|
+ // if (this.type === 'intersectionCamera' && _MarkerHandle.isDrawList('intersection')) {
|
|
|
+ // const ixrId = this.prop.ixr_id;
|
|
|
+ // const ixrLi = $('#intersection-' + ixrId);
|
|
|
+ // ixrLi.addClass('click');
|
|
|
+ // $('.mobile-select').val(ixrId);
|
|
|
+ // moveToScroll(true, _MarkerHandle.findMarkerArr('intersection') , ixrId); // 클릭 시 리스트 이동
|
|
|
+ // }
|
|
|
+
|
|
|
+ _MarkerHandle.selectedMarker = this;
|
|
|
+
|
|
|
+ const center = getKakaoPosition(this.Y_CRDN, this.X_CRDN);
|
|
|
+ let level = _Level;
|
|
|
+ // if (this.type === 'intersection') {
|
|
|
+ // level = 2;
|
|
|
+ // }
|
|
|
+
|
|
|
+ _MapHandler.setLevel(level);
|
|
|
+ _MapHandler.setCenter(center);
|
|
|
+
|
|
|
+ if (this.iwContent) {
|
|
|
+ this.infoWindow = $(this.iwContent);
|
|
|
+ $('body').append(this.infoWindow);
|
|
|
+ if (this.type === 'parking' && this.prop.prk_plce_nmbr) {
|
|
|
+ const parkData = await $.ajax({url: '/api/traffic/parking-live-info', method: 'post', data:{nmbr: this.prop.prk_plce_nmbr}});
|
|
|
+ if (parkData.remndr_prk_cmprt_co && parkData.remndr_prk_cmprt_co >= 0) {
|
|
|
+ const remndrPrkCmprtCo = parkData.remndr_prk_cmprt_co + '대';
|
|
|
+ $('.remndr_prk_cmprt_co').attr('title', '주차가능면수 : '+ remndrPrkCmprtCo);
|
|
|
+ $('.remndr_prk_cmprt_co').html(remndrPrkCmprtCo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ let type = this.type;
|
|
|
+ // if (type === 'intersectionCamera') type = 'cctv';
|
|
|
+ setInfoWindowPositionWidthDraggable(this, type);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.URL) {
|
|
|
+ this.videoEvent();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.phaseArray) {
|
|
|
+ this.vmsEvent();
|
|
|
+ }
|
|
|
+
|
|
|
+ const selectedLi = $('#' + this.type + '-' + this.ID);
|
|
|
+
|
|
|
+ selectedLi.addClass('click');
|
|
|
+
|
|
|
+ if (_MarkerHandle.isDraw('traffic')) {
|
|
|
+ getVertex();
|
|
|
+ }
|
|
|
+
|
|
|
+ this.isClick = true;
|
|
|
+
|
|
|
+ if (this.imageOnOff.includes(this.type)) {
|
|
|
+ this.setImage('2');
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if (_MarkerHandle.isDrawList(this.type)) {
|
|
|
+ const markerArr = _MarkerHandle.findMarkerArr(this.type);
|
|
|
+ moveToScroll(true, markerArr, this.ID); // 클릭 시 리스트 이동
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ //닫기 이벤트
|
|
|
+ close() {
|
|
|
+ if (this.timer) { // 인터벌이 있는 경우
|
|
|
+ clearInterval(this.timer);
|
|
|
+ clearTimeout(this.timer);
|
|
|
+ this.timer = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.limitTimer) {
|
|
|
+ clearInterval(this.limitTimer);
|
|
|
+ this.limitTimer = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.isClick = false;
|
|
|
+ if (this.imageOnOff.includes(this.type)) {// 클릭 이미지가 있는 경우
|
|
|
+ this.setImage('1');
|
|
|
+ }
|
|
|
+
|
|
|
+ let oldPlayer = document.getElementById("video-" + this.ID);
|
|
|
+ if (oldPlayer) { // video 태그가 있는 경우
|
|
|
+
|
|
|
+ videojs(oldPlayer).dispose();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.infoWindow) { // 인포 윈도우 삭제
|
|
|
+ this.infoWindow.remove();
|
|
|
+ this.infoWindow = null;
|
|
|
+ }
|
|
|
+ const mobilSelect = $('.mobile-select');
|
|
|
+
|
|
|
+ if (mobilSelect[0] && _MarkerHandle.isDrawList(this.type)) { // 리스트가 있는 경우
|
|
|
+ mobilSelect.val("-");
|
|
|
+ let selectedLi = $("#" + this.type + "-" + this.ID);
|
|
|
+
|
|
|
+ if (selectedLi.hasClass('click')) { // 선택 리스트가 있는지 여부
|
|
|
+ selectedLi.removeClass('click');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // if (this.type === 'intersectionCamera' && _MarkerHandle.isDrawList('intersection')) {
|
|
|
+ // mobilSelect.val("-");
|
|
|
+ // let selectedId = _MarkerHandle.selectedMarker.prop.ixr_id;
|
|
|
+ // let selectedLi = $("#intersection-" + selectedId);
|
|
|
+ //
|
|
|
+ // if (selectedLi.hasClass('click')) { // 선택 리스트가 있는지 여부
|
|
|
+ // selectedLi.removeClass('click');
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+
|
|
|
+
|
|
|
+ //선택 해제
|
|
|
+ _MarkerHandle.selectedMarker = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ //영상 30초 제한 시간 보여주기
|
|
|
+ showLimitTime() {
|
|
|
+ const timer = $('.timer');
|
|
|
+ if (!this.video) {
|
|
|
+ timer.text('-');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ timer.text(30);
|
|
|
+
|
|
|
+ if (this.limitTimer) {
|
|
|
+ clearInterval(this.limitTimer)
|
|
|
+ this.limitTimer = null;
|
|
|
+ }
|
|
|
+ let cnt = 30;
|
|
|
+ this.limitTimer = setInterval(()=>{
|
|
|
+ if(cnt === 0) {
|
|
|
+ clearInterval(this.limitTimer);
|
|
|
+ this.limitTimer = null;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ $('.timer').text(--cnt);
|
|
|
+ }, 1000)
|
|
|
+ }
|
|
|
+
|
|
|
+ //CCTV 타이머
|
|
|
+ playTimer() {
|
|
|
+ if (this.timer) {
|
|
|
+ clearTimeout(this.timer);
|
|
|
+ this.timer = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.timer = setTimeout(()=>{
|
|
|
+ if (this.video) {
|
|
|
+ this.video.pause();
|
|
|
+ }
|
|
|
+ }, CCTV_DISPLAY_TIME);
|
|
|
+ }
|
|
|
+
|
|
|
+ //비디오 생성 및 플레이
|
|
|
+ videoEvent() {
|
|
|
+ this.video = createVideoJs(this.ID, this.URL, this);
|
|
|
+
|
|
|
+ this.playTimer();
|
|
|
+
|
|
|
+ this.showLimitTime();
|
|
|
+
|
|
|
+ $('.continue-play').on('click', ()=>{
|
|
|
+ this.playTimer();
|
|
|
+ this.showLimitTime();
|
|
|
+
|
|
|
+ if (this.video) {
|
|
|
+ this.video.play();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ $('#video-error').css('display', 'none');
|
|
|
+ $('.cctv-info-window .content > div:nth-child(1)').append($('<video id="video-'+this.ID+'" class="video-js" style="width: 100%; height: 100%;"></video>'))
|
|
|
+ this.videoEvent();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ //vms 이미지 표출 이벤트
|
|
|
+ vmsEvent() {
|
|
|
+ let cnt = 1;
|
|
|
+ if (this.phaseArray.length > 0) {
|
|
|
+ this.timer = setInterval(()=>{
|
|
|
+ if (cnt === this.phaseArray.length) {
|
|
|
+ cnt = 0;
|
|
|
+ }
|
|
|
+ const activeImage = $('.vms-info-window .content img.active');
|
|
|
+ if (activeImage[0]) {
|
|
|
+ activeImage.removeClass('active');
|
|
|
+ }
|
|
|
+ $("#phase-" + this.phaseArray[cnt]).addClass('active');
|
|
|
+ cnt++;
|
|
|
+ }, VMS_DISPLAY_TIME);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 소통정보 Object
|
|
|
+ */
|
|
|
+class TrafficObj {
|
|
|
+ constructor(obj) {
|
|
|
+ this.ID = obj.roadway_id;
|
|
|
+ this.NAME = obj.roadway_nm;
|
|
|
+ this.obj = obj;
|
|
|
+ this.infoWindow = null;
|
|
|
+ this.polyLine = null;
|
|
|
+ this.polyBackLine = null;
|
|
|
+ this.ADDR = obj.addr;
|
|
|
+ this.init();
|
|
|
+ }
|
|
|
+
|
|
|
+ init() {
|
|
|
+ const _self = this;
|
|
|
+ const trafficObj = this.obj;
|
|
|
+ const xArray = trafficObj.x_crdn.split(",");
|
|
|
+ const yArray = trafficObj.y_crdn.split(",");
|
|
|
+ const linePath = [];
|
|
|
+ for (let ii = 0; ii < xArray.length; ii++) {
|
|
|
+ const x_crdn = Number(xArray[ii]);
|
|
|
+ const y_crdn = Number(yArray[ii]);
|
|
|
+ const coordinates = getKakaoPosition(y_crdn, x_crdn);
|
|
|
+ linePath.push(coordinates);
|
|
|
+ }
|
|
|
+
|
|
|
+ let strokeWeight = 5;
|
|
|
+ let strokeWeightBack = 7;
|
|
|
+ const level = _Level;
|
|
|
+
|
|
|
+ if (level === 3) {
|
|
|
+ strokeWeightBack = 6;
|
|
|
+ } else if (level === 5 || level === 4) {
|
|
|
+ strokeWeight = 3;
|
|
|
+ strokeWeightBack = 5;
|
|
|
+ } else if (level >= 6) {
|
|
|
+ strokeWeight = 2;
|
|
|
+ strokeWeightBack = 4;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (_MarkerHandle.trafficObj && this.ID === _MarkerHandle.trafficObj) {
|
|
|
+ strokeWeightBack += 2
|
|
|
+ }
|
|
|
+ this.polyBackLine = new kakao.maps.Polyline({
|
|
|
+ path: linePath, // 선을 구성하는 좌표배열 입니다
|
|
|
+ strokeWeight: strokeWeightBack, // 선의 두께 입니다
|
|
|
+ strokeColor: '#eeeeee', // 선의 색깔입니다
|
|
|
+ strokeOpacity: 1, // 선의 불투명도 입니다 1에서 0 사이의 값이며 0에 가까울수록 투명합니다
|
|
|
+ strokeStyle: 'solid', // 선의 스타일입니다
|
|
|
+ zIndex: 1
|
|
|
+ });
|
|
|
+ this.polyLine = new kakao.maps.Polyline({
|
|
|
+ path: linePath, // 선을 구성하는 좌표배열 입니다
|
|
|
+ strokeWeight: strokeWeight, // 선의 두께 입니다
|
|
|
+ strokeColor: g_color.get(trafficObj.cmtr_grad_cd), // 선의 색깔입니다
|
|
|
+ strokeOpacity: 1, // 선의 불투명도 입니다 1에서 0 사이의 값이며 0에 가까울수록 투명합니다
|
|
|
+ strokeStyle: 'solid', // 선의 스타일입니다
|
|
|
+ zIndex: 2
|
|
|
+ });
|
|
|
+
|
|
|
+
|
|
|
+ this.setVisibleMarker(_MarkerHandle.isDraw('traffic'));
|
|
|
+
|
|
|
+ // new kakao.maps.event.addListener(this.polyLine, 'mouseover', function (event) {
|
|
|
+ //
|
|
|
+ // this.setOptions({strokeColor: '#0000FF'});
|
|
|
+ // const iwContent =
|
|
|
+ // `<div class="trafficPop">
|
|
|
+ // <div class="traffic-speed ${trafficObj.cmtr_grad_cd}">
|
|
|
+ // <span class="traffic-name">${_self.NAME}</span>
|
|
|
+ // <span class="traffic-speed-info border-back ${trafficObj.cmtr_grad_cd}">${trafficObj.grad_nm}</span>
|
|
|
+ // </div>
|
|
|
+ // <div class="traffic-info">
|
|
|
+ // <span>${trafficObj.strt_nm_node} → ${trafficObj.end_nm_node}</span>
|
|
|
+ // <br>
|
|
|
+ // <span>소요시간 : </span>
|
|
|
+ // <span class="${trafficObj.cmtr_grad_cd}">약 ${textFormat(trafficObj.trvl_hh)}분 </span>
|
|
|
+ // <span> 속도 : </span>
|
|
|
+ // <span class="${trafficObj.cmtr_grad_cd}">약 ${textFormat(trafficObj.sped)}km/h</span>
|
|
|
+ // </div>
|
|
|
+ // </div>`;
|
|
|
+ // _self.infoWindow = new kakao.maps.CustomOverlay({
|
|
|
+ // map: _MapHandler.map,
|
|
|
+ // clickable: true,
|
|
|
+ // position: event.latLng,
|
|
|
+ // content: iwContent,
|
|
|
+ // xAnchor: -0.1,
|
|
|
+ // yAnchor: 1.1,
|
|
|
+ // zIndex: 999
|
|
|
+ // });
|
|
|
+ //
|
|
|
+ // });
|
|
|
+ //
|
|
|
+ // daum.maps.event.addListener(this.polyLine, 'mouseout', function () {
|
|
|
+ // this.setOptions({strokeColor: g_color.get(trafficObj.cmtr_grad_cd)});
|
|
|
+ // if (_self.infoWindow != null) _self.infoWindow.setMap(null);
|
|
|
+ // });
|
|
|
+ }
|
|
|
+
|
|
|
+ setVisibleMarker(isVisible) {
|
|
|
+ const isShow = isVisible ? _MapHandler.map : null;
|
|
|
+ this.polyBackLine.setMap(isShow);
|
|
|
+ this.polyLine.setMap(isShow);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 간선도로 Object
|
|
|
+ */
|
|
|
+class TbAtrdObj extends MarkerObj{
|
|
|
+ constructor(obj) {
|
|
|
+ super({
|
|
|
+ ID : obj.ID,
|
|
|
+ NAME : obj.atrd_nm + ' ['+ obj.drct_nm + ']',
|
|
|
+ X_CRDN : obj.x_crdn_arr.split(",")[0],
|
|
|
+ Y_CRDN : obj.y_crdn_arr.split(",")[0],
|
|
|
+ URL : null,
|
|
|
+ TYPE : 'atrd',
|
|
|
+ DATA : obj,
|
|
|
+ IMAGE_TYPE : obj.drct_cd,
|
|
|
+ IMAGE : '/images/icon/atrd'
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * CCTV Object
|
|
|
+ */
|
|
|
+class TbCCtvObj extends MarkerObj{
|
|
|
+ constructor(obj) {
|
|
|
+ super({
|
|
|
+ ID : obj.cctv_mngm_nmbr,
|
|
|
+ NAME : obj.istl_lctn_nm,
|
|
|
+ X_CRDN : obj.x_crdn,
|
|
|
+ Y_CRDN : obj.y_crdn,
|
|
|
+ URL : obj.strm_http_addr,
|
|
|
+ TYPE : 'cctv',
|
|
|
+ DATA : obj,
|
|
|
+ IMAGE_TYPE : '1',
|
|
|
+ IMAGE : '/images/icon/cctv',
|
|
|
+ ADDR : obj.istl_lctn_addr,
|
|
|
+ });
|
|
|
+ this.iwContent = this.getIwContent();
|
|
|
+ }
|
|
|
+
|
|
|
+ getIwContent() {
|
|
|
+ const {ID, NAME, type} = this;
|
|
|
+ let iwContent =
|
|
|
+ `<div class="cctv-info-window">
|
|
|
+ <div class="title">
|
|
|
+ <div class="cctv-name-${ID}">${NAME}</div>
|
|
|
+ <div onclick="infoWindowEvent('${type}', '${ID}', 'close')">X</div>
|
|
|
+ </div>
|
|
|
+ <div class="content">
|
|
|
+ <div style="display: flex; align-items: center; justify-content: center;">
|
|
|
+ <video id="video-${ID}" class="video-js" style="width: 100%; height: 100%;"></video>
|
|
|
+ <img id="video-error" style="display: none;" src="/images/icon/error.png" alt="스트리밍 오류 이미지">
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <div>남은시간 : <span class="timer">30</span> 초</div>
|
|
|
+ <div class="continue-play">계속재생</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>`;
|
|
|
+//<!-- <div>※ CCTV영상은 30초간 제공됩니다.</div>-->
|
|
|
+ return iwContent;
|
|
|
+ }
|
|
|
+}
|
|
|
+/**
|
|
|
+ * Parking Object
|
|
|
+ */
|
|
|
+class TbParkingObj extends MarkerObj{
|
|
|
+ constructor(obj) {
|
|
|
+ super({
|
|
|
+ ID : obj.parking_id,
|
|
|
+ NAME : obj.parking_nm,
|
|
|
+ X_CRDN : obj.x_crdn,
|
|
|
+ Y_CRDN : obj.y_crdn,
|
|
|
+ URL : null,
|
|
|
+ TYPE : 'parking',
|
|
|
+ DATA : obj,
|
|
|
+ IMAGE_TYPE : '1',
|
|
|
+ IMAGE : '/images/icon/parking' + (obj.prk_plce_nmbr ? '1-' : '2-'),
|
|
|
+ ADDR : obj.parking_addr,
|
|
|
+ })
|
|
|
+ this.iwContent = this.getIwContent();
|
|
|
+ }
|
|
|
+
|
|
|
+ getIwContent() {
|
|
|
+ const {ID, NAME, prop, X_CRDN, Y_CRDN} = this;
|
|
|
+ let iwContent =
|
|
|
+ `<div class="parking-info-window">
|
|
|
+ <div class="title">
|
|
|
+ <div class="parking-name-${ID}">${NAME}</div>
|
|
|
+ <div onclick="infoWindowEvent('parking', '${ID}', 'close')"></div>
|
|
|
+ </div>
|
|
|
+ <div class="content">
|
|
|
+ <div class="row">
|
|
|
+ <div>주차면수</div>
|
|
|
+ <div title="주차면수 : ${prop.parking_num} 대">${prop.parking_num} 대</div>
|
|
|
+ </div>`;
|
|
|
+ if (prop.prk_plce_nmbr) {
|
|
|
+ iwContent +=`<div class="row">
|
|
|
+ <div>주차가능면수</div>
|
|
|
+ <div class="remndr_prk_cmprt_co">- 대</div>
|
|
|
+ </div>`;
|
|
|
+ }
|
|
|
+
|
|
|
+ iwContent +=`<div class="row">
|
|
|
+ <div>구분</div>
|
|
|
+ <div title="구분 : ${prop.parking_type_desc}">${prop.parking_type_desc}</div>
|
|
|
+ </div>
|
|
|
+ <div class="row">
|
|
|
+ <div>기본요금</div>
|
|
|
+ <div title="기본요금 : ${prop.parking_fee_type_desc}">${prop.parking_fee_type_desc}</div>
|
|
|
+ </div>
|
|
|
+ <div class="row">
|
|
|
+ <div>운영시간</div>
|
|
|
+ <div title="운영시간 : ${prop.parking_oper_time}">${prop.parking_oper_time}</div>
|
|
|
+ </div>
|
|
|
+ <div class="row">
|
|
|
+ <div>주소</div>
|
|
|
+ <div style="cursor:pointer;" title="주소 : ${prop.parking_addr}" onclick="openNavigationApp('${X_CRDN}','${Y_CRDN}','${prop.parking_addr}')">${prop.parking_addr}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>`;
|
|
|
+ return iwContent;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * VMS Object
|
|
|
+ */
|
|
|
+class TbVmsObj extends MarkerObj{
|
|
|
+ constructor(obj) {
|
|
|
+ super({
|
|
|
+ ID : obj.vms_ctlr_nmbr,
|
|
|
+ NAME : obj.vms_nm,
|
|
|
+ X_CRDN : obj.x_crdn,
|
|
|
+ Y_CRDN : obj.y_crdn,
|
|
|
+ URL : null,
|
|
|
+ TYPE : 'vms',
|
|
|
+ IMAGE : '/images/icon/vms',
|
|
|
+ IMAGE_TYPE : '1',
|
|
|
+ DATA : obj,
|
|
|
+ ADDR : obj.istl_lctn_addr,
|
|
|
+ });
|
|
|
+ this.iwContent = this.getIwContent();
|
|
|
+ }
|
|
|
+
|
|
|
+ getIwContent() {
|
|
|
+ const {ID, NAME, prop} = this;
|
|
|
+ this.phaseArray = [];
|
|
|
+
|
|
|
+ let isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
|
|
|
+ const WH = vmsWHMap.get(prop.vms_type_cd);
|
|
|
+ let width = 256;
|
|
|
+ let height = 50;
|
|
|
+
|
|
|
+ if (WH) {
|
|
|
+ width = WH.width;
|
|
|
+ height = WH.height
|
|
|
+ }
|
|
|
+
|
|
|
+ const msg = prop.msg;
|
|
|
+ let content = "";
|
|
|
+ if (msg && msg.length > 0) {
|
|
|
+ const windowHeight = $(window).height();
|
|
|
+ if (isMobile || windowHeight < 900) {
|
|
|
+ width = WH.width/2;
|
|
|
+ height = WH.height/2;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (let idx in msg) {
|
|
|
+ let msgObj = msg[idx];
|
|
|
+ let className = '';
|
|
|
+ if (idx === "0") {
|
|
|
+ className = 'active'
|
|
|
+ }
|
|
|
+ content += `<img id="phase-${msgObj.phase}" class="${className}" style="width: ${width}px; height: ${height}px;"
|
|
|
+ src="/api/traffic/vms-dspl-image/${ID}/${msgObj.phase}" alt="VMS 표출 이미지">`;
|
|
|
+ this.phaseArray.push(msgObj.phase);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ width = 256;
|
|
|
+ height = 50;
|
|
|
+ content += '표출 이미지 데이터가 없습니다.';
|
|
|
+ }
|
|
|
+ width = width +'px';
|
|
|
+ height = height + 'px';
|
|
|
+
|
|
|
+ let iwContent =
|
|
|
+ `<div class="vms-info-window" style="width: calc(${width} + 10px); height: calc(${height} + 50px);">
|
|
|
+ <div class="title">
|
|
|
+ <div class="vms-name-${ID}">${NAME}</div>
|
|
|
+ <div onclick="infoWindowEvent('vms', ${ID}, 'close')">X</div>
|
|
|
+ </div>
|
|
|
+ <div class="content" style="width: ${width}; height: ${height};">
|
|
|
+ ${content}
|
|
|
+ </div>
|
|
|
+ </div>`;
|
|
|
+ return iwContent;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 돌발정보 Object
|
|
|
+ */
|
|
|
+class TbIncdObj extends MarkerObj{
|
|
|
+ constructor(obj) {
|
|
|
+ super({
|
|
|
+ ID : obj.incd_ocrr_id,
|
|
|
+ NAME : obj.incd_titl,
|
|
|
+ X_CRDN : obj.x_crdn,
|
|
|
+ Y_CRDN : obj.y_crdn,
|
|
|
+ URL : null,
|
|
|
+ TYPE : 'incident',
|
|
|
+ IMAGE : '/images/icon/incd',
|
|
|
+ IMAGE_TYPE : '1',
|
|
|
+ DATA : obj,
|
|
|
+ ADDR : obj.road_nm,
|
|
|
+ });
|
|
|
+
|
|
|
+ this.iwContent = this.getIwContent();
|
|
|
+ }
|
|
|
+
|
|
|
+ getIwContent() {
|
|
|
+ const {ID, NAME, prop} = this;
|
|
|
+ let iwContent =
|
|
|
+ `<div class="incident-info-window">
|
|
|
+ <div class="title">
|
|
|
+ <div class="incident-name-${ID}">${NAME}</div>
|
|
|
+ <div onclick="infoWindowEvent('incident', '${ID}', 'close')">X</div>
|
|
|
+ </div>
|
|
|
+ <div class="content">
|
|
|
+ <div>
|
|
|
+ 위치 : ${prop.road_nm}
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ 설명 : ${prop.incd_expl}
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ 기간 : ${prop.incd_strt_dt} ~ ${prop.incd_end_prar_dt}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>`;
|
|
|
+ return iwContent;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 스마트 교차로 Object
|
|
|
+ */
|
|
|
+class IntersectionObj extends MarkerObj{
|
|
|
+ constructor(obj) {
|
|
|
+ super({
|
|
|
+ ID : obj.ixr_id,
|
|
|
+ NAME : obj.ixr_nm,
|
|
|
+ X_CRDN : obj.x_crdn,
|
|
|
+ Y_CRDN : obj.y_crdn,
|
|
|
+ URL : null,
|
|
|
+ TYPE : 'intersection',
|
|
|
+ DATA : obj,
|
|
|
+ IMAGE_TYPE : "",
|
|
|
+ IMAGE : '/images/icon/intersection'
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 스마트교차로 카메라 Object
|
|
|
+ */
|
|
|
+class IntersectionCameraObj extends MarkerObj{
|
|
|
+ constructor(obj) {
|
|
|
+ super(
|
|
|
+ {
|
|
|
+ ID : obj.cmra_id + '_' + obj.drct_dvsn_cd,
|
|
|
+ NAME : obj.drct_lctn,
|
|
|
+ X_CRDN : obj.cmra_x_crdn,
|
|
|
+ Y_CRDN : obj.cmra_y_crdn,
|
|
|
+ URL : obj.hmpg_cmra_url,
|
|
|
+ TYPE : 'intersectionCamera',
|
|
|
+ DATA : obj,
|
|
|
+ IMAGE_TYPE : "",
|
|
|
+ ADDR : obj.istl_lctn,
|
|
|
+ IMAGE : '/images/icon/intersection'
|
|
|
+ }
|
|
|
+ )
|
|
|
+ this.iwContent = this.getIwContent();
|
|
|
+ }
|
|
|
+
|
|
|
+ getIwContent() {
|
|
|
+ const {ID, NAME, type} = this;
|
|
|
+ let iwContent =
|
|
|
+ `<div class="cctv-info-window">
|
|
|
+ <div class="title">
|
|
|
+ <div class="cctv-name-${ID}">${NAME}</div>
|
|
|
+ <div onclick="infoWindowEvent('${type}', '${ID}', 'close')">X</div>
|
|
|
+ </div>
|
|
|
+ <div class="content">
|
|
|
+ <div>
|
|
|
+ <video id="video-${ID}" class="video-js" playsinline style="width: 100%; height: 100%;"></video>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <div>남은시간 : <span class="timer">30</span> 초</div>
|
|
|
+ <div class="continue-play">계속재생</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>`;
|
|
|
+
|
|
|
+ return iwContent;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 인포윈도우 이벤트
|
|
|
+ * @param type 시설물 유형
|
|
|
+ * @param id 요소 ID
|
|
|
+ * @param event 이벤트 종류 (click, close)
|
|
|
+ */
|
|
|
+function infoWindowEvent(type, id, event) {
|
|
|
+ const markerInfo = _MarkerHandle.findMarkerInfo(type); // 유형별 시설물 정보 찾기
|
|
|
+
|
|
|
+ // 시설물 마커들 중 id에 해당하는 객체 찾기
|
|
|
+ const markers = markerInfo.markers;
|
|
|
+ let idx = markers.findIndex(obj => obj.ID.toString() === id.toString());
|
|
|
+
|
|
|
+ // click, close 등 메서드로 등록한 것들도 키값으로 찾을 수 있음 obj.click() == obj['click']();
|
|
|
+ markers[idx][event]();
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+let isHide = false
|
|
|
+
|
|
|
+/**
|
|
|
+ * 좌측 목록 토글 이벤트
|
|
|
+ */
|
|
|
+function toggleEvent() {
|
|
|
+ const $listArea = $('.left-list-area');
|
|
|
+ const $toggleButton = $('.toggle-button');
|
|
|
+ const $locationButton = $('.location-btn');
|
|
|
+ const $locationBox = $('.location-box');
|
|
|
+
|
|
|
+ if (!isHide) {
|
|
|
+ $toggleButton.animate({
|
|
|
+ left: 0
|
|
|
+ }, 'slow');
|
|
|
+ $listArea.animate({
|
|
|
+ left: -$listArea.width()
|
|
|
+ }, 'slow');
|
|
|
+ $locationButton.animate({
|
|
|
+ left: 27
|
|
|
+ }, 'slow');
|
|
|
+ $locationBox.animate({
|
|
|
+ left: 27
|
|
|
+ }, 'slow');
|
|
|
+ $toggleButton.text('>');
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ $toggleButton.animate({
|
|
|
+ left: $listArea.width()
|
|
|
+ }, 'slow');
|
|
|
+ $listArea .animate({
|
|
|
+ left: 0
|
|
|
+ }, 'slow');
|
|
|
+ $locationButton.animate({
|
|
|
+ left: $listArea.width() + 27
|
|
|
+ }, 'slow')
|
|
|
+ $locationBox.animate({
|
|
|
+ left: $listArea.width() + 27
|
|
|
+ }, 'slow')
|
|
|
+ $toggleButton.text('<');
|
|
|
+ }
|
|
|
+ isHide = !isHide;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * 웹페이지 사이즈 별 위치 변경 이벤트
|
|
|
+ */
|
|
|
+window.addEventListener('resize', function(event) {
|
|
|
+ const $toggleButton = $('.toggle-button');
|
|
|
+ const $locationButton = $('.location-btn');
|
|
|
+ const $listArea = $('.left-list-area');
|
|
|
+ const $locationBox = $('.location-box');
|
|
|
+
|
|
|
+ if ($(this).width() > 450) {
|
|
|
+ const left = $toggleButton.offset().left;
|
|
|
+ const listLeft = $listArea.offset().left;
|
|
|
+
|
|
|
+ if ($(this).width() <= 795) {
|
|
|
+ $locationButton.css('display', 'none');
|
|
|
+ $locationBox.css('display', 'none');
|
|
|
+ if(_MarkerArr.length > 0) {
|
|
|
+ _MarkerArr.forEach((obj)=>{
|
|
|
+ obj.setMap(null);
|
|
|
+ });
|
|
|
+ _MarkerArr = [];
|
|
|
+ }
|
|
|
+ if ($locationButton.hasClass('on')) {
|
|
|
+ $locationButton.removeClass('on');
|
|
|
+ }
|
|
|
+ $('.list-content.spot').empty();
|
|
|
+ $('#location-text').val('');
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ $locationButton.css('display', 'flex');
|
|
|
+ }
|
|
|
+ if ($(this).width() >= 920) {
|
|
|
+ if (left > 0 && left < 400) {
|
|
|
+ $toggleButton.css('left', 400);
|
|
|
+ $locationButton.css('left', 427);
|
|
|
+ $locationBox.css('left', 427);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (listLeft > -400 && listLeft < 0) {
|
|
|
+ $listArea.css('left', -400);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if (left > 0 && left > 275) {
|
|
|
+ $toggleButton.css('left', 275);
|
|
|
+ $locationButton.css('left', 302);
|
|
|
+ $locationBox.css('left', 302);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (listLeft < -273) {
|
|
|
+ $listArea.css('left', -273);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ $locationBox.css('display', 'none');
|
|
|
+ $locationButton.removeClass('on');
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * 선택 리스트 스크롤 높이 반환 이벤트
|
|
|
+ * @param selectIndex 선택 인덱스
|
|
|
+ * @returns {number} 스크롤 높이
|
|
|
+ */
|
|
|
+function getScrollTop(selectIndex) {
|
|
|
+ let scrollTop = 0;
|
|
|
+ for (let ii=0; ii < selectIndex; ii++) {
|
|
|
+ let height = $('.left-list-area .list-content.list').children().eq(ii).css('height');
|
|
|
+ if (height) {
|
|
|
+ height = Number(height.replace('px', ''));
|
|
|
+ if (!isNaN(height)) {
|
|
|
+ scrollTop += height;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return scrollTop;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 좌측 리스트 선택 시 스크롤 변경 이벤트
|
|
|
+ * @param flag
|
|
|
+ * @param array
|
|
|
+ * @param id
|
|
|
+ */
|
|
|
+function moveToScroll(flag, array, id) {
|
|
|
+ if (flag) {
|
|
|
+ let selectIndex = array.findIndex((obj)=> obj.ID == id);
|
|
|
+ let scrollTop = getScrollTop(selectIndex);
|
|
|
+ $('.left-list-area .list-content.list').animate({
|
|
|
+ scrollTop : scrollTop + 'px'
|
|
|
+ });
|
|
|
+ $('.mobile-select').val(id);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ * @param jsonData Marker Info
|
|
|
+ * @param classType Marker Class
|
|
|
+ * @param type Marker type
|
|
|
+ */
|
|
|
+function receiveMarkerData(jsonData, classType, type) {
|
|
|
+ let listStr = "";
|
|
|
+ const title = $('.left-list-area .list-tab li.active > div:nth-child(2)').text();
|
|
|
+ let emptyStr = "<div class='empty'>" + title + " 리스트가 없습니다.</div>";
|
|
|
+ let mobileStr = "";
|
|
|
+ const { markers, isDraw, isDrawList } = _MarkerHandle.findMarkerInfo(type);
|
|
|
+ if (jsonData && jsonData.length) {
|
|
|
+ let markerArr = [];
|
|
|
+ jsonData.forEach((obj)=>{
|
|
|
+ const markerObj = new classType(obj);
|
|
|
+ markerObj.init();
|
|
|
+ listStr += `<li id="${markerObj.type}-${markerObj.ID}" onclick="infoWindowEvent('${type}', '${markerObj.ID}' , 'click')">${markerObj.NAME}</li>`
|
|
|
+ mobileStr += `<option value="${markerObj.ID}">${markerObj.NAME}</option>`;
|
|
|
+ markers.push(markerObj);
|
|
|
+ // if (type ==='intersection') {
|
|
|
+ // markerObj.prop.detail.forEach((detail)=>{
|
|
|
+ // const detailObj = new IntersectionCameraObj(detail);
|
|
|
+ // detailObj.init();
|
|
|
+ // _MarkerHandle.findMarkerInfo('intersectionCamera').markers.push(detailObj);
|
|
|
+ // });
|
|
|
+ // _MarkerHandle.setIsDraw('intersectionCamera', isDraw);
|
|
|
+ // }
|
|
|
+ markerArr.push(markerObj);
|
|
|
+ });
|
|
|
+
|
|
|
+ _MarkerHandle.setMarkers(type, markerArr);
|
|
|
+ _MarkerHandle.showHideMarker(type, isDraw);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ listStr = emptyStr;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (isDrawList) {
|
|
|
+ const listSection = $('.left-list-area .list-content.list');
|
|
|
+ listSection.empty();
|
|
|
+ listSection.html(listStr);
|
|
|
+ const $mobileSelect = $('.mobile-select');
|
|
|
+ $mobileSelect.append($(mobileStr));
|
|
|
+ $mobileSelect.on('change', function(){
|
|
|
+ const id = $(this).val();
|
|
|
+ if (id && id !== "-") {
|
|
|
+ infoWindowEvent(type, id , 'click');
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ if (selectIncidentId) {
|
|
|
+ infoWindowEvent('incident', selectIncidentId , 'click');
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * 맵 중앙 아이콘 위 위치 좌표
|
|
|
+ * @param infoWindow
|
|
|
+ * @returns {number[]}
|
|
|
+ */
|
|
|
+function getInfoWidowPosition(infoWindow) {
|
|
|
+ const map = $('#map');
|
|
|
+ let mapHalfW = map.innerWidth() / 2;
|
|
|
+ let mapHalfH = map.innerHeight() / 2;
|
|
|
+ let mapTop = map.offset().top;
|
|
|
+ let halfW = infoWindow.innerWidth() / 2;
|
|
|
+ let height = infoWindow.innerHeight();
|
|
|
+ let left = mapHalfW - halfW;
|
|
|
+ let iconH = _size[_Level];
|
|
|
+ let top = mapTop + mapHalfH - height - iconH - 10;
|
|
|
+ return [top, left];
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Marker Drag Event
|
|
|
+ * @param markerObj Drag Marker Object
|
|
|
+ * @param type Marker Type
|
|
|
+ */
|
|
|
+function setInfoWindowPositionWidthDraggable(markerObj, type) {
|
|
|
+ const { infoWindow, ID } = markerObj;
|
|
|
+ const position = getInfoWidowPosition(infoWindow); //Current Marker Position
|
|
|
+ // console.log(infoWindow.width());
|
|
|
+ let top = position[0];
|
|
|
+ let left = position[1] + (infoWindow.width() / 2) + (markerObj.atrdSize[_Level] / 2);
|
|
|
+
|
|
|
+ if (markerObj.type === 'parking') {
|
|
|
+ top = $('header').outerHeight() + $('.toggle-button').outerHeight() + 2;
|
|
|
+ left = $('.left-list-area').outerWidth();
|
|
|
+ }
|
|
|
+ infoWindow.css({
|
|
|
+ top : top + 'px',
|
|
|
+ left : left + 'px',
|
|
|
+ position : 'absolute',
|
|
|
+ zIndex : 999,
|
|
|
+ });
|
|
|
+
|
|
|
+ //containment : 이동 반경 제한, handle : Drag Element
|
|
|
+ infoWindow.draggable({containment : 'body', handle: '.'+ type + '-name-' + ID});
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * Kakao Map 좌표 지정
|
|
|
+ */
|
|
|
+function getKakaoPosition(yCoordinate, xCoordinate) {
|
|
|
+ return new kakao.maps.LatLng(Number(yCoordinate), Number(xCoordinate));
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * videoJs 객체 생성
|
|
|
+ */
|
|
|
+function createVideoJs(id, url, obj) {
|
|
|
+ let video = videojs("video-" + id, {
|
|
|
+ sources: [
|
|
|
+ {
|
|
|
+ src: url,
|
|
|
+ type: "application/x-mpegURL",
|
|
|
+ crossorigin: "anonymous",
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ responsive: false,
|
|
|
+ autoplay: true,
|
|
|
+ muted: true,
|
|
|
+ preload: "metadata",
|
|
|
+ });
|
|
|
+
|
|
|
+ //에러발생 시 대체 이미지 생성
|
|
|
+ video.on('error', function(){
|
|
|
+ if (this.error().code === 4) {
|
|
|
+ this.pause();
|
|
|
+ this.dispose();
|
|
|
+ $('#video-error').css('display', 'block');
|
|
|
+ clearInterval(obj.limitTimer);
|
|
|
+ clearTimeout(obj.timer);
|
|
|
+ $('.timer').text('-');
|
|
|
+ obj.video = null;
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ return video;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Map Handler Class
|
|
|
+ */
|
|
|
+class MapHandler {
|
|
|
+ constructor(id) {
|
|
|
+ this.selectedObj = null;
|
|
|
+ this.map = null;
|
|
|
+ this.mapElement = id;
|
|
|
+ this.atrd = [];
|
|
|
+ }
|
|
|
+
|
|
|
+ //Kakao Map 생성 및 이벤트 설정
|
|
|
+ init () {
|
|
|
+ const container = document.getElementById(this.mapElement); //지도를 담을 영역의 DOM 레퍼런스
|
|
|
+ const options = { //지도를 생성할 때 필요한 기본 옵션
|
|
|
+ center: getKakaoPosition(36.0191816, 129.3432983), //지도의 중심좌표.
|
|
|
+ level: _Level, //현재 레벨
|
|
|
+ maxLevel: 9, //최대 레벨
|
|
|
+ minLevel: 1, //최소 레벨
|
|
|
+ disableDoubleClickZoom: true, //더블 클릭 줌 방지
|
|
|
+ };
|
|
|
+ this.map = new kakao.maps.Map(container, options);
|
|
|
+ const mapTypeControl = new kakao.maps.MapTypeControl(); //지도, 스카이뷰 버튼 생성
|
|
|
+ this.map.addControl(mapTypeControl, kakao.maps.ControlPosition.TOPRIGHT); //지도, 스카이뷰 버튼 위치 설정
|
|
|
+ const zoomControl = new kakao.maps.ZoomControl(); //줌 버튼 생성
|
|
|
+ this.map.addControl(zoomControl, kakao.maps.ControlPosition.RIGHT); // 줌 버튼 위치 설정
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Map Zoom Level Change 이벤트 (이미지 사이즈, 스마트 교차로 이미지 토글, 소통정보 정보 변경)
|
|
|
+ */
|
|
|
+ kakao.maps.event.addListener(this.map, 'zoom_changed', function () {
|
|
|
+ _Level = this.getLevel();
|
|
|
+ const zoomChangeArray = ['cctv', 'vms', 'parking', 'incident'];
|
|
|
+ zoomChangeArray.forEach((type)=>{
|
|
|
+ const isDraw = _MarkerHandle.isDraw(type);
|
|
|
+
|
|
|
+ if (isDraw) {
|
|
|
+ const markers = _MarkerHandle.findMarkerArr(type);
|
|
|
+ if (markers && markers.length > 0) {
|
|
|
+ markers.forEach((obj)=>{
|
|
|
+ let imageType = "";
|
|
|
+ if (obj.imageType === '1') {
|
|
|
+ imageType = obj.isClick ? '2' :'1';
|
|
|
+ }
|
|
|
+
|
|
|
+ // if (obj.type === "intersectionCamera") {
|
|
|
+ // let isIxrCm = _Level > 2 ? null : _MapHandler.map;
|
|
|
+ // obj.marker.setMap(isIxrCm);
|
|
|
+ // obj.polyLine.setMap(isIxrCm);
|
|
|
+ // }
|
|
|
+ // else {
|
|
|
+ obj.setImage(imageType);
|
|
|
+ // }
|
|
|
+
|
|
|
+ // if (obj.type === 'intersection') {
|
|
|
+ // let isIxr = _Level <= 2 ? null : _MapHandler.map;
|
|
|
+ // obj.marker.setMap(isIxr);
|
|
|
+ // }
|
|
|
+
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (_MarkerHandle.isDraw('traffic')) {
|
|
|
+ const selectedAtrd = _MarkerHandle.selectedAtrd;
|
|
|
+ if (selectedAtrd.length > 0) {
|
|
|
+ let level = getAtrdLevel(_Level);
|
|
|
+ let array = [];
|
|
|
+ selectedAtrd.forEach((atrdId)=>{
|
|
|
+ const atrdObj = _MarkerHandle.findMarkerObj('atrd', atrdId);
|
|
|
+ if (atrdObj) {
|
|
|
+ atrdObj.marker.setMap(null);
|
|
|
+ let changeId = atrdId.slice(0, -1);
|
|
|
+ array.push(changeId + level);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ _MarkerHandle.selectedAtrd = array;
|
|
|
+ }
|
|
|
+ getVertex();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 맵 드래그 이벤트
|
|
|
+ * 좌표 데이터가의 양이 많으므로 이동 할때마다 영역별 소통정보를 새로 그려줌
|
|
|
+ */
|
|
|
+ kakao.maps.event.addListener(this.map, 'dragend', function() {
|
|
|
+ if (_MarkerHandle.isDraw('traffic')) {
|
|
|
+ getVertex();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // kakao.maps.event.addListener(this.map, 'bounds_changed', function() {
|
|
|
+ // if (_MarkerHandle.isDraw('traffic')) {
|
|
|
+ // getVertex();
|
|
|
+ // }
|
|
|
+ // });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 맵 클릭 이벤트
|
|
|
+ */
|
|
|
+ kakao.maps.event.addListener(this.map, 'click', function (mouseEvent) {
|
|
|
+ /** 클릭 이벤트 필요 시 설정 **/
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ getLevel() {
|
|
|
+ return this.map.getLevel();
|
|
|
+ }
|
|
|
+
|
|
|
+ setLevel(level) {
|
|
|
+ if (!isNaN(level)) {
|
|
|
+ this.map.setLevel(level);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ console.error("Invalid Value Error - MapHandler.setValue(), Please Check The Zoom Level Value : ", level);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ setCenter(position) {
|
|
|
+ if (position) {
|
|
|
+ this.map.setCenter(position);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ console.error("Invalid Values Error - MapHandler.setCenter, Value is Empty : ", position);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ getBounds() {
|
|
|
+ return this.map.getBounds();
|
|
|
+ }
|
|
|
+
|
|
|
+ setBounds(bounds) {
|
|
|
+ if (bounds) {
|
|
|
+ this.map.setBounds(bounds);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ console.error("Invalid Values Error - MapHandler.setBound, Value is Empty : ", bounds);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 마커 관리 Class
|
|
|
+ */
|
|
|
+class MarkerManager{
|
|
|
+ constructor(typeArr) {
|
|
|
+ this.markerMaps = new Map();
|
|
|
+ this.typeArr = typeArr;
|
|
|
+ this.selectedMarker = null;
|
|
|
+ this.selectedAtrd = [];
|
|
|
+ this.trafficObj = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ //마커 초기화
|
|
|
+ init() {
|
|
|
+ if (this.typeArr && this.typeArr.length > 0) {
|
|
|
+ for (let type of this.typeArr) {
|
|
|
+ this.markerMaps.set(type, {
|
|
|
+ isDraw : false, //마커 지도 이미지
|
|
|
+ isDrawList : false, //좌측 교통정보 리스트
|
|
|
+ markers : [], //마커 빈값 초기화
|
|
|
+ type : type, //교통정보 종류
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //마커 세팅
|
|
|
+ setMarkers(type, array) {
|
|
|
+ if (array && array.length) {
|
|
|
+ this.markerMaps.get(type).markers = [...array];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //유형별 마커 관리 객체 찾기
|
|
|
+ findMarkerInfo(type) {
|
|
|
+ return this.markerMaps.get(type);
|
|
|
+ }
|
|
|
+
|
|
|
+ //유형별 화면 표출 여부
|
|
|
+ isDraw(type) {
|
|
|
+ return this.findMarkerInfo(type).isDraw;
|
|
|
+ }
|
|
|
+
|
|
|
+ //유형별 리스트 표출 여부
|
|
|
+ isDrawList(type) {
|
|
|
+ return this.findMarkerInfo(type).isDrawList;
|
|
|
+ }
|
|
|
+
|
|
|
+ //유형별 화면 표출 여부 세팅
|
|
|
+ setIsDraw(type, isDraw) {
|
|
|
+ this.findMarkerInfo(type).isDraw = isDraw;
|
|
|
+ }
|
|
|
+
|
|
|
+ //유형별 리스트 표출 여부 세팅
|
|
|
+ setIsDrawList(type, isDraw) {
|
|
|
+ this.findMarkerInfo(type).isDrawList = isDraw;
|
|
|
+ }
|
|
|
+
|
|
|
+ //유형별 마커 Array 찾기
|
|
|
+ findMarkerArr(type) {
|
|
|
+ return this.findMarkerInfo(type).markers;
|
|
|
+ }
|
|
|
+
|
|
|
+ //유형별 개별 마커 찾기
|
|
|
+ findMarkerObj(type, id) {
|
|
|
+ const markerArr = this.findMarkerArr(type);
|
|
|
+ let markerObj = null;
|
|
|
+ if (markerArr && markerArr.length > 0) {
|
|
|
+ let idx = markerArr.findIndex(obj => obj.ID === id);
|
|
|
+ if (!isNaN(idx) && markerArr[idx]) {
|
|
|
+ markerObj = markerArr[idx];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return markerObj;
|
|
|
+ }
|
|
|
+
|
|
|
+ //유형별 마커 보이기 / 감추기
|
|
|
+ showHideMarker(type, isShow) {
|
|
|
+ const markerArr = this.findMarkerArr(type);
|
|
|
+
|
|
|
+ if (markerArr && markerArr.length > 0) {
|
|
|
+ const map = _MapHandler.map;
|
|
|
+ for (let markerObj of markerArr) {
|
|
|
+ let visible = null
|
|
|
+
|
|
|
+ //스마트 교차로의 경우 2레벨 이하일때 카메라 위치, 그 외 교차로 위치를 보여준다.
|
|
|
+ switch (type) {
|
|
|
+ // case 'intersectionCamera':
|
|
|
+ // if (isShow && _Level <= 2) visible = map;
|
|
|
+ // break;
|
|
|
+ // case 'intersection':
|
|
|
+ // if (isShow && _Level > 2) visible = map;
|
|
|
+ // break;
|
|
|
+ case 'atrd': //소통 정보 시 선택된 도로가 있는지 확인 후 진행
|
|
|
+ if (this.selectedAtrd.length > 0) {
|
|
|
+ if (this.selectedAtrd.includes(markerObj.ID.toString()) && isShow) {
|
|
|
+ visible = map;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default : //그 외 보이기 감추기
|
|
|
+ visible = isShow ? map : null;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ //마커, 폴리 라인을 맵에 보이기/감추기
|
|
|
+ if (markerObj.polyBackLine){
|
|
|
+ markerObj.polyBackLine.setMap(visible);
|
|
|
+ }
|
|
|
+ if (markerObj.polyLine) {
|
|
|
+ markerObj.polyLine.setMap(visible);
|
|
|
+ }
|
|
|
+ if (markerObj.marker) {
|
|
|
+ markerObj.marker.setMap(visible);
|
|
|
+ // if (type !== 'intersectionCamera') {
|
|
|
+ // markerObj.setImage(markerObj.imageType);
|
|
|
+ // }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //현재 보이기/감추기 상태값 설정
|
|
|
+ this.setIsDraw(type, isShow);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 지점 검색 리스트 보이기 / 감추기
|
|
|
+ */
|
|
|
+function toggleLocationBox() {
|
|
|
+ const $locationBox = $('.location-box');
|
|
|
+ if (_MarkerArr.length > 0) {
|
|
|
+ _MarkerArr.forEach((obj)=>{
|
|
|
+ obj.setMap(null);
|
|
|
+ });
|
|
|
+ _MarkerArr = [];
|
|
|
+ }
|
|
|
+ $('.location-box input').val('');
|
|
|
+ $('.list-content.spot').empty();
|
|
|
+ $locationBox.toggle();
|
|
|
+ $('.location-btn').toggleClass('on');
|
|
|
+}
|