123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878 |
- let _size = [48, 48, 48, 48, 40, 32, 24, 22, 20, 18, 18];
- let _AtrdData = [];
- let _AtrdMap = new Map();
- let selectIncidentId = null;
- //시설물 유형
- const _FacilityArray = ['cctv', 'vms', 'intersection', 'incident', 'traffic', 'parking', 'intersectionCamera'];
- 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 이미지 표출 시간
- let _MapHandler; //카카오 맵 핸들러
- let _Level = 6; //현재 줌레벨
- 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();
- // 시설물 유형 정보로 flag 값 세팅
- if (_type) {
- _MapHandler[_type + 'Flag'] = true;
- _MapHandler[_type + 'ListFlag'] = 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 = type + 'Camera';
- }
- if (type === 'traffic') {
- subType = 'atrd';
- getVertex();
- }
- else {
- if (_MapHandler[type] && _MapHandler[type].length <= 0) {
- _methodMap.get(type)();
- }
- }
- let toggle = 'hide';
- let classToggle = 'removeClass';
- if (isShow === true) {
- toggle = 'show';
- classToggle = 'addClass';
- }
- legendIcon[classToggle]('active');
- target[classToggle]('active');
- _MapHandler[toggle](type);
- if (subType) {
- _MapHandler[toggle](subType);
- }
- })
- /**
- * 범례 호버 색 변환
- * */
- $('.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');
- }
- }
- });
- let _MarkerArr = [];
- $('.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 searchType = $('.tab-title > div.active').text();
- const searchText = $(this).val();
- if (searchType === '리스트') {
- const $list = $('.list-content.list > li');
- if (!$list.length) return;
- 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 = $('.list-content.list > li').eq(ii).text().toLowerCase();
- if (text.includes(searchText.toLowerCase())) {
- li.css('display', 'block');
- }
- else {
- li.css('display', 'none');
- }
- }
- }
- }
- else {
- if (_MarkerArr.length > 0) {
- _MarkerArr.forEach((obj)=>{
- obj.setMap(null);
- });
- _MarkerArr = [];
- }
- $('.list-content.spot').html("");
- if (!searchText || !searchText.trim()) return;
- $.ajax({
- url: 'https://dapi.kakao.com/v2/local/search/address.json',
- headers: { 'Authorization': 'KakaoAK 4896b94398b96949d349881d004835cf'},
- data :{
- query : searchText,
- },
- type: 'GET'
- }).done(function(data) {
- if (data && data.documents.length > 0) {
- let str = "";
- const setMap = new Map();
- const bounds = new kakao.maps.LatLngBounds();
- let minX;
- let minY;
- let maxX;
- let maxY;
- let idx = 0;
- data.documents.forEach((obj)=>{
- if (!setMap.get(obj.address_name) && obj.address_name.includes("경북 포항시")) {
- 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.map.setBounds(bounds);
- $('.list-content.spot').html(str);
- getVertex();
- }
- }
- });
- }
- })
- });
- /**
- * 간선도로 마커 레벨별 이미지 보이기 감추기
- */
- function atrdMarkerResize() {
- let level = _Level;
- let atrdArr = _MapHandler['atrd'];
- atrdArr.forEach((atrd)=>{
- setMarkerImage(atrd, atrd.obj.drct_cd, true);
- });
- if (level === 3) {
- level = 4;
- }
- if (level >= 8) {
- level = 7;
- }
- else if (level >= 6) {
- level = 6;
- }
- const atrdInfo = _AtrdMap.get(level.toString());
- if (atrdInfo) {
- _AtrdData = [];
- let upHillArr = [];
- let downHillArr = [];
- const $selectedLi = $(".left-list-area .list-content.list > li.click");
- let id;
- let idArr;
- if ($selectedLi[0]) {
- id = $selectedLi.attr('id');
- }
- if (id) {
- idArr = id.split("_");
- }
- atrdInfo.forEach((atrd)=>{
- if (atrd.atrd_id.toString() === idArr[1] || atrd.atrd_id.toString() === idArr[2]) {
- _AtrdData.push(atrd);
- if (atrd.atrd_id.toString() === idArr[1]) {
- upHillArr.push(atrd);
- }
- else {
- downHillArr.push(atrd);
- }
- }
- });
- if (upHillArr[0]) {
- let upHillX = upHillArr[0].x_crdn_arr.split(',')[0];
- let upHillY = upHillArr[0].y_crdn_arr.split(',')[0];
- atrdArr[0].marker.setPosition(getKakaoPosition(upHillY, upHillX));
- }
- if (downHillArr[0]) {
- let downHillX = downHillArr[0].x_crdn_arr.split(',')[0];
- let downHillY = downHillArr[0].y_crdn_arr.split(',')[0];
- atrdArr[1].marker.setPosition(getKakaoPosition(downHillY, downHillX));
- }
- }
- }
- /**
- * 스마트교차로 카메라 레벨별 이미지 보이기 감추기
- */
- function intersectionCameraChangeWidthZoomLevel() {
- const level = _Level;
- const size = [48, 48, 48]
- const levelSize = size[level];
- const type = 'intersectionCamera';
- const markerArr = _MapHandler[type];
- const map = _MapHandler.map;
- if (markerArr.length > 0) {
- markerArr.forEach((obj) => {
- const content = $('<div title='+obj.NAME+'>');
- content.css(
- {
- width: levelSize+ 'px',
- height: levelSize+ 'px',
- backgroundImage:'url(/images/icon/intersection-cctv.png)',
- backgroundSize : levelSize+'px '+levelSize+'px',
- backgroundRepeat: 'no-repeat',
- backgroundPosition : 'center',
- transform : 'rotate(' + obj.obj.cmra_angn +'deg)',
- cursor : 'pointer'
- });
- obj.marker.setContent(content[0]);
- content.on('click', ()=> {
- _MapHandler.click(type, obj.ID);
- });
- if (level <= 2 && _MapHandler['intersectionFlag']) {
- obj.marker.setMap(map);
- obj.polyline.setMap(map);
- } else {
- obj.marker.setMap(null);
- obj.polyline.setMap(null);
- }
- })
- }
- }
- /**
- * 스마트교차로 레벨별 이미지 보이기 감추기
- */
- function intersectionMarkerChangeWithZoomLevel() {
- const level = _Level;
- if (_MapHandler['intersection'].length > 0) {
- _MapHandler['intersection'].forEach((obj)=>{
- setMarkerImage(obj, "", false);
- if (level > 2 && _MapHandler['intersectionFlag']) {
- obj.marker.setVisible(true);
- }
- else {
- obj.marker.setVisible(false);
- }
- })
- }
- }
- /**
- * 맵 레벨별 이미지 변환
- * @param array
- */
- function markerSizeChangeWithZoomLevel(array) {
- if (array && array.length > 0) {
- array.forEach((obj)=>{
- if (obj.isClick) {
- setMarkerImage(obj, 2, false)
- }
- else {
- setMarkerImage(obj, 1, false);
- }
- });
- }
- }
- /**
- * 지점 클릭 위치 이동
- * @param xCoordinate x좌표
- * @param yCoordinate y좌표
- * @param listIndex 지점 선택 인덱스
- */
- function moveLocation(xCoordinate, yCoordinate, listIndex) {
- const position = getKakaoPosition(yCoordinate, xCoordinate);
- _MapHandler.map.setCenter(position);
- _MapHandler.map.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, (jsonData)=>{
- if (jsonData && jsonData.length > 0) {
- receiveFacilityData(jsonData, TbCCtvObj,'cctv');
- }
- }, 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');
- }
- }, null);
- }
- /**
- * 돌발정보
- */
- function getIncident () {
- getDataAsync('/api/traffic/incident-list', 'POST', null, null, (jsonData)=>{
- if (jsonData && jsonData.length > 0) {
- receiveFacilityData(jsonData, TbIncdObj, 'incident');
- if (selectIncidentId) {
- _MapHandler.click('incident', selectIncidentId);
- }
- }
- }, 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);
- }
- })
- receiveFacilityData(data, IntersectionObj, 'intersection');
- }
- }, null);
- }
- /**
- * 주차정보
- */
- function getParking() {
- getDataAsync('/api/traffic/parking-list', 'POST', null, null, (jsonData)=>{
- if (jsonData && jsonData.length > 0) {
- receiveFacilityData(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)=>{
- _AtrdMap.set(obj.level, obj.list);
- });
- }
- }, null);
- getDataAsync('/api/traffic/atrd-list', 'POST', null, null, (jsonData)=>{
- if (jsonData) {
- let listStr = "";
- let mobileStr = "";
- let atrdData = [];
- for (let key in jsonData){
- atrdData.push({
- name : key,
- list : jsonData[key]
- });
- }
- atrdData.sort((a,b)=>{
- return a.name > b.name ? 1 : a.name < b.name ? -1 : 0;
- });
- atrdData.forEach((obj)=>{
- let upHillId = null;
- let downHillId = null;
- const list = obj.list;
- if (list && list.length === 2) {
- upHillId = list[0].atrd_id;
- downHillId = list[1].atrd_id;
- if (list[0].drct_cd === "1") {
- upHillId = list[1].atrd_id;
- downHillId = list[0].atrd_id;
- }
- }
- listStr += `<li id="atrd_${upHillId}_${downHillId}" onclick="atrdClickEvent('${upHillId}', '${downHillId}')">${obj.name}</li>`
- mobileStr += `<option value="${upHillId}_${downHillId}">${obj.name}</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 {
- const array = _MapHandler['atrd'];
- if (array.length > 0) {
- array.forEach((atrd)=>{
- atrd.close();
- })
- _MapHandler['atrd'] = [];
- getVertex();
- }
- }
- })
- const listSection = $('.left-list-area .list-content.list');
- listSection.empty();
- listSection.html(listStr);
- }
- });
- getVertex();
- }
- /**
- * 소통정보 가져오기
- */
- function getVertex() {
- const array = _MapHandler['traffic'];
- if (array.length > 0) {
- array.forEach((obj) => {
- obj.setVisibleMarker(false);
- if (obj.infoWindow) {
- obj.infoWindow.setMap(null);
- }
- })
- _MapHandler['traffic'] = [];
- }
- let level = _MapHandler.map.getLevel();
- const bounds = _MapHandler.map.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(),
- }
- if (_MapHandler.atrd && _MapHandler.atrd.length > 0) {
- _MapHandler.atrd.forEach((atrd)=>{
- atrd.cnt = 0;
- atrd.trvl_hh = 0;
- atrd.sped = 0;
- })
- }
- getDataAsync('/api/traffic/vertex-list', 'POST', data, null, (jsonData)=>{
- if (jsonData && jsonData.length > 0) {
- jsonData.forEach((obj)=>{
- const trafficObj = new TrafficObj(obj);
- if (_AtrdData.length > 0) {
- _AtrdData.forEach((atrd)=>{
- if (atrd.road_id.toString() === trafficObj.ID.toString()) {
- let sped = Number(obj.sped);
- let trvl_hh = Number(obj.trvl_hh);
- const atrdObj = _MapHandler.getSelectObj(_MapHandler['atrd'], atrd.atrd_id);
- if (!isNaN(sped)) {
- atrdObj.sped += sped;
- }
- if (!isNaN(trvl_hh)) {
- atrdObj.trvl_hh += trvl_hh;
- }
- atrdObj.cnt += 1;
- trafficObj.polyBackLine.setOptions({
- strokeColor : 'black',
- });
- }
- })
- }
- _MapHandler['traffic'].push(trafficObj);
- })
- }
- });
- }
- /**
- * 간선도로 클릭 이벤트
- * @param AupHillId 상행 ID
- * @param AdownHillId 하행 ID
- */
- function atrdClickEvent(AupHillId, AdownHillId) {
- let atrdArr = _MapHandler['atrd'];
- if (atrdArr.length > 0) {
- atrdArr.forEach((atrd)=>{
- atrd.close();
- });
- _MapHandler['atrd'] = [];
- }
- const selectedObj = _MapHandler.selectedObj;
- if (selectedObj) {
- _MapHandler.close(selectedObj.type, selectedObj.ID);
- }
- _AtrdData = [];
- const $selectedLi = $('.left-list-area .list-content.list > li.click');
- if ($selectedLi) {
- $selectedLi.removeClass('click');
- }
- const $selectLi = $('#atrd_' + AupHillId + "_" + AdownHillId);
- $selectLi.addClass('click');
- $selectLi.focus();
- //상행, 하행 ID 가 있다면 실행
- if (AupHillId && AdownHillId) {
- const upHillArr = [];
- const downHillArr = [];
- const bounds = new kakao.maps.LatLngBounds();
- //전체 간선도로 목록을 담은 Map 에서 기준값을 5레벨로 잡아 포커스 좌표를 설정
- if (_AtrdMap.get("5")) {
- const basicAtrd = _AtrdMap.get("5");
- for (let idx in basicAtrd) {
- const obj = basicAtrd[idx];
- if (obj.atrd_id.toString() === AupHillId || obj.atrd_id.toString() === AdownHillId) {
- bounds.extend(new kakao.maps.LatLng(obj.y_crdn_min, obj.x_crdn_min));
- bounds.extend(new kakao.maps.LatLng(obj.y_crdn_max, obj.x_crdn_max));
- }
- }
- _MapHandler.map.setBounds(bounds);
- //전체 레벨이 다있는게 아니므로 로드 레벨은 재설정
- let level = _Level;
- if (level >= 8) {
- level = 7;
- }
- else if (level >= 6) {
- level = 6;
- }
- /**
- * 범위를 포커스 하게 되면 레벨이 변경되므로 변경 된 레벨의 간선도로 목록에서
- * 상행, 하행 ID가 포함된 데이터 갖고오며 상행, 하행 데이터 따로 구분
- */
- const atrdInfo = _AtrdMap.get(level.toString());
- if (atrdInfo) {
- atrdInfo.forEach((atrd)=>{
- if (atrd.atrd_id.toString() === AupHillId.toString() || atrd.atrd_id.toString() === AdownHillId.toString()) {
- _AtrdData.push(atrd);
- if (atrd.atrd_id === AupHillId) {
- upHillArr.push(atrd);
- }
- else {
- downHillArr.push(atrd);
- }
- }
- })
- }
- //레벨이 변경됐으므로 다시한번 버텍스를 초기화해준다
- getVertex();
- //각 상행 하행의 첫번째 좌표를 가지고 상행, 하행 아이콘을 생성 하며 객체는 array에 보관해둠
- if (upHillArr[0]) {
- const upHillObj = new TbAtrdObj(upHillArr[0]);
- _MapHandler['atrd'].push(upHillObj);
- }
- if (downHillArr[0]) {
- const downHillObj = new TbAtrdObj(downHillArr[0]);
- _MapHandler['atrd'].push(downHillObj);
- }
- }
- }
- }
- /**
- * 간선도로 상,하행 마커 그리기
- * @param src 상, 하행 코드
- * @param lat X 좌표
- * @param lng Y 좌표
- * @param name 명칭
- * @returns {daum.maps.Marker} 생성 마커
- */
- function drawAtrdMakrer(src, lng, lat, name) {
- let imageSize;
- let imageOption;
- let imageSrc = '/images/icon/atrd' + src + '.png';
- //레벨별 사이즈를 다르게 표출
- const level = _Level;
- let size = 48;
- if (level >= 7) {
- size = 24;
- }
- imageSize = new kakao.maps.Size(size, size);
- imageOption = {
- offset: new kakao.maps.Point(size/2, size),
- };
- let markerImage = new kakao.maps.MarkerImage(imageSrc, imageSize, imageOption);
- let markerPosition = new kakao.maps.LatLng(lng, lat);
- let atrdSideMarker = new kakao.maps.Marker({
- position: markerPosition,
- image: markerImage,
- zIndex: 5,
- title: name,
- });
- return atrdSideMarker;
- }
- /**
- * 소통정보 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.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;
- }
- 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(_MapHandler['trafficFlag']);
- 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: 4
- });
- });
- 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 {
- constructor(obj) {
- this.ID = obj.atrd_id;
- this.NAME = obj.atrd_nm;
- this.X_CRDN = null;
- this.Y_CRDN = null;
- this.obj = obj;
- this.marker = null;
- this.imgSrc = '/images/icon/atrd';
- this.isClick = false;
- this.sped = 0;
- this.trvl_hh = 0;
- this.cnt = 0;
- this.infoWindow = null;
- this.init();
- }
- init() {
- if (this.obj.x_crdn_arr) {
- this.X_CRDN = this.obj.x_crdn_arr.split(",")[0];
- }
- if (this.obj.y_crdn_arr) {
- this.Y_CRDN = this.obj.y_crdn_arr.split(",")[0];
- }
- const name = this.NAME + " [" + this.obj.drct_nm + "]";
- this.marker = drawAtrdMakrer(this.obj.drct_cd, this.Y_CRDN, this.X_CRDN, name);
- this.click();
- // let _self = this;
- // new kakao.maps.event.addListener(this.marker, 'mouseover', function (event) {
- // let position = getKakaoPosition(_self.Y_CRDN, _self.X_CRDN);
- // const iwContent =
- // `<div class="trafficPop">
- // <div>
- // <span class="traffic-name">${_self.NAME}</span>
- // <span>[${_self.obj.drct_nm}]</span>
- // </div>
- // <div class="traffic-info">
- // <span>평균속도 : ${Math.round(_self.sped/_self.cnt)} km/h</span><br>
- // <span>통행시간 : ${textFormat(Math.round(_self.trvl_hh/_self.trvl_hh))}분 </span>
- // </div>
- // </div>`;
- // _self.infoWindow = new kakao.maps.CustomOverlay({
- // map: _MapHandler.map,
- // clickable: true,
- // position: position,
- // content: iwContent,
- // xAnchor: -0.1,
- // yAnchor: 1.1,
- // zIndex: 4
- // });
- // });
- // new kakao.maps.event.addListener(this.marker, 'mouseout', function (event) {
- // _self.infoWindow.setMap(null);
- // })
- }
- click() {
- this.setVisibleMarker(true);
- }
- setVisibleMarker(isVisible) {
- let visible = isVisible ? _MapHandler.map : null;
- this.marker.setMap(visible);
- this.isClick = isVisible;
- }
- close() {
- this.setVisibleMarker(false);
- }
- }
- /**
- * CCTV Object
- */
- class TbCCtvObj {
- constructor(obj) {
- this.ID = obj.cctv_mngm_nmbr;
- this.NAME = obj.istl_lctn_nm;
- this.X_CRDN = obj.x_crdn;
- this.Y_CRDN = obj.y_crdn;
- this.URL = obj.strm_http_addr;
- this.type = 'cctv';
- this.obj = obj;
- this.marker = null;
- this.infoWindow = null;
- this.iwContent = null;
- this.isClick = false;
- this.imgSrc = '/images/icon/cctv';
- this.timer = null;
- }
- init() {
- this.marker = createMarker(this, 'cctv');
- this.iwContent = `<div class="cctv-info-window">
- <div class="title">
- <div class="cctv-name-${this.ID}">${this.NAME}</div>
- <div onclick="infoWindowEvent('cctv', '${this.ID}', 'close')">X</div>
- </div>
- <div class="content">
- <div>
- <video id="video-${this.ID}" class="video-js" playsinline style="width: 100%; height: 100%;"></video>
- </div>
- <div>
- <div>※ CCTV영상은 30초간 제공됩니다.</div>
- <div class="continue-play">계속재생</div>
- </div>
- </div>
- </div>`;
- }
- setVisibleMarker(isVisible) {
- this.marker.setVisible(isVisible);
- }
- }
- /**
- * Parking Object
- */
- class TbParkingObj {
- constructor(obj) {
- this.ID = obj.parking_id;
- this.NAME = obj.parking_nm;
- this.X_CRDN = obj.x_crdn;
- this.Y_CRDN = obj.y_crdn;
- this.obj = obj;
- this.marker = null;
- this.infoWindow = null;
- this.iwContent = null;
- this.isClick = false;
- this.imgSrc = '/images/icon/parking';
- this.timer = null;
- this.type = 'parking';
- }
- init() {
- this.marker = createMarker(this, 'parking');
- this.iwContent = `<div class="parking-info-window">
- <div class="title">
- <div class="parking-name-${this.ID}">${this.NAME}</div>
- <div onclick="infoWindowEvent('parking', '${this.ID}', 'close')"></div>
- </div>
- <div class="content">
- <div class="row">
- <div>주차면수</div>
- <div title="주차면수 : ${this.obj.parking_num} 대">${this.obj.parking_num} 대</div>
- </div>
- <div class="row">
- <div>구분</div>
- <div title="구분 : ${this.obj.parking_type_desc}">${this.obj.parking_type_desc}</div>
- </div>
- <div class="row">
- <div>기본요금</div>
- <div title="기본요금 : ${this.obj.parking_fee_type_desc}">${this.obj.parking_fee_type_desc}</div>
- </div>
- <div class="row">
- <div>주소</div>
- <div title="주소 : ${this.obj.parking_addr}">${this.obj.parking_addr}</div>
- </div>
- </div>
- </div>`;
- }
- setVisibleMarker(isVisible) {
- this.marker.setVisible(isVisible);
- }
- }
- /**
- * VMS Object
- */
- class TbVmsObj {
- constructor(obj) {
- this.ID = obj.vms_ctlr_nmbr;
- this.NAME = obj.vms_nm;
- this.X_CRDN = obj.x_crdn;
- this.Y_CRDN = obj.y_crdn;
- this.obj = obj;
- this.marker = null;
- this.infoWindow = null;
- this.iwContent = null;
- this.isClick = false;
- this.imgSrc = '/images/icon/vms';
- this.timer = null;
- this.phaseArray = [];
- this.type = 'vms';
- }
- init() {
- this.marker = createMarker(this, 'vms');
- this.phaseArray = [];
- let width;
- let height;
- let isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
- switch (this.obj.vms_type_cd) {
- case 'VMC1':
- width = 400;
- height = 64;
- break;
- case 'VMC2':
- width = 384;
- height = 64;
- break;
- case 'VMC3':
- width = 288;
- height = 160;
- break;
- case 'VMC4':
- width = 256;
- height = 192;
- break;
- }
- const windowHeight = $(window).height();
- if (isMobile || windowHeight < 900) {
- width = width/2;
- height = height/2;
- }
- width = width +'px';
- height = height + 'px';
- const msg = this.obj.msg;
- if (!msg || msg.length === 0) {
- width = '256px';
- height = '50px';
- }
- let iwContent =
- `<div class="vms-info-window" style="width: calc(${width} + 10px); height: calc(${height} + 50px);">
- <div class="title">
- <div class="vms-name-${this.ID}">${this.NAME}</div>
- <div onclick="infoWindowEvent('vms', ${this.ID}, 'close')">X</div>
- </div>
- <div class="content" style="width: ${width}; height: ${height};">`;
- if (msg && msg.length > 0) {
- for (let idx in msg) {
- let msgObj = msg[idx];
- let className = '';
- if (idx === "0") {
- className = 'active'
- }
- iwContent += `<img id="phase-${msgObj.phase}" class="${className}" style="width: ${width}; height: ${height};" src="/api/traffic/vms-dspl-image/${this.ID}/${msgObj.phase}">`;
- this.phaseArray.push(msgObj.phase);
- }
- }
- else {
- iwContent += '표출 이미지 데이터가 없습니다.';
- }
- iwContent += `</div></div>`;
- this.iwContent = iwContent;
- }
- setVisibleMarker(isVisible) {
- this.marker.setVisible(isVisible);
- }
- }
- /**
- * 돌발정보 Object
- */
- class TbIncdObj {
- constructor(obj) {
- this.ID = obj.incd_ocrr_id;
- this.NAME = obj.incd_titl;
- this.X_CRDN = obj.x_crdn;
- this.Y_CRDN = obj.y_crdn;
- this.obj = obj;
- this.marker = null;
- this.infoWindow = null;
- this.isClick = false;
- this.imgSrc = '/images/icon/incd';
- this.iwContent = null;
- this.type = 'incident';
- }
- init() {
- this.marker = createMarker(this, 'incident');
- this.iwContent = `<div class="incident-info-window">
- <div class="title">
- <div class="incident-name-${this.ID}">${this.NAME}</div>
- <div onclick="infoWindowEvent('incident', '${this.ID}', 'close')">X</div>
- </div>
- <div class="content">
- <div>
- 위치 : ${this.obj.road_nm}
- </div>
- <div>
- 설명 : ${this.obj.incd_expl}
- </div>
- <div>
- 기간 : ${this.obj.incd_strt_dt} ~ ${this.obj.incd_end_prar_dt}
- </div>
- </div>
- </div>`;
- }
- setVisibleMarker(isVisible) {
- this.marker.setVisible(isVisible);
- }
- }
- /**
- * 스마트 교차로 Object
- */
- class IntersectionObj {
- constructor(obj) {
- this.ID = obj.ixr_id;
- this.NAME = obj.ixr_nm;
- this.X_CRDN = obj.x_crdn;
- this.Y_CRDN = obj.y_crdn;
- this.obj = obj;
- this.marker = null;
- this.infoWindow = null;
- this.isClick = false;
- this.imgSrc = '/images/icon/intersection';
- this.detail = [];
- this.type = 'intersection';
- }
- init() {
- let imageSrc = this.imgSrc + '.png', // 마커이미지의 주소입니다
- size = _size[_Level],
- imageSize = new kakao.maps.Size(size, size), // 마커이미지의 크기입니다
- imageOption = {
- offset: new kakao.maps.Point(size/2, size/2),
- alt: this.NAME,
- };
- // 마커의 이미지정보를 가지고 있는 마커이미지를 생성합니다
- let markerImage = new kakao.maps.MarkerImage(imageSrc, imageSize, imageOption),
- markerPosition = getKakaoPosition(this.Y_CRDN, this.X_CRDN); // 마커가 표시될 위치입니다
- this.marker = new kakao.maps.Marker(
- {map: _MapHandler.map, position: markerPosition, image: markerImage, zindex: 10, clickable: true, title : this.NAME}
- );
- const level = _Level;
- const isVisible = (level > 2 && _MapHandler['intersectionFlag']);
- this.marker.setVisible(isVisible);
- let _self = this;
- new kakao.maps.event.addListener(this.marker, 'click', ()=> _MapHandler.click('intersection', _self.ID));
- }
- setVisibleMarker(isVisible) {
- if (_Level <= 2) isVisible = false;
- this.marker.setVisible(isVisible);
- }
- }
- /**
- * 스마트교차로 카메라 Object
- */
- class IntersectionCameraObj {
- constructor(obj) {
- this.ID = obj.cmra_id + '_' + obj.drct_dvsn_cd;
- this.NAME = obj.drct_lctn;
- this.X_CRDN = obj.cmra_x_crdn;
- this.Y_CRDN = obj.cmra_y_crdn;
- this.URL = obj.hmpg_cmra_url;
- this.obj = obj;
- this.marker = null;
- this.infoWindow = null;
- this.iwContent = null;
- this.isClick = false;
- this.timer = null;
- this.polyline = null;
- this.type = 'intersectionCamera';
- }
- init() {
- this.marker = createIntersectionCameraMarker(this);
- this.iwContent =
- `<div class="cctv-info-window">
- <div class="title">
- <div class="intersectionCamera-name-${this.ID}">${this.NAME}</div>
- <div class="close-window" onclick="infoWindowEvent('intersectionCamera', '${this.ID}', 'close')">X</div>
- </div>
- <div class="content">
- <div>
- <video id="video-${this.ID}" class="video-js" style="width: 100%; height: 100%;"></video>
- </div>
- <div>
- <div>※ CCTV영상은 30초간 제공됩니다.</div>
- <div class="continue-play">계속재생</div>
- </div>
- </div>
- </div>`;
- }
- setVisibleMarker(isVisible) {
- const visible = isVisible && _Level <= 2 ? _MapHandler.map : null;
- this.marker.setMap(visible);
- this.polyline.setMap(visible);
- }
- }
- /**
- * 인포윈도우 이벤트
- * @param type 시설물 유형
- * @param id 요소 ID
- * @param event 이벤트 종류 (click, close)
- */
- function infoWindowEvent(type, id, event) {
- _MapHandler[event](type, id);
- }
- let isHide = false
- /**
- * 좌측 목록 토글 이벤트
- */
- function toggleEvent() {
- const $listArea = $('.left-list-area');
- const $toggleButton = $('.toggle-button');
- if (!isHide) {
- $toggleButton.animate({
- left: 0
- }, 'slow');
- $listArea .animate({
- left: -$listArea.width()
- }, 'slow');
- $toggleButton.text('>');
- }
- else {
- $toggleButton.animate({
- left: $listArea.width()
- }, 'slow');
- $listArea .animate({
- left: 0
- }, 'slow');
- $toggleButton.text('<');
- }
- isHide = !isHide;
- }
- window.addEventListener('resize', function(event) {
- if ($(this).width() > 450) {
- const $toggleButton = $('.toggle-button');
- const $listArea = $('.left-list-area');
- const left = $toggleButton.offset().left;
- const listLeft = $listArea.offset().left;
- if ($(this).width() >= 920) {
- if (left > 0 && left < 400) {
- $toggleButton.css('left', 400);
- }
- if (listLeft > -400 && listLeft < 0) {
- $listArea.css('left', -400);
- }
- }
- else {
- if (left > 0 && left > 275) {
- $toggleButton.css('left', 275);
- }
- if (listLeft < -273) {
- $listArea.css('left', -273);
- }
- }
- }
- })
- /**
- * 시설물 마커 초기화
- * @param obj 시설물 객체
- * @returns {kakao.maps.Marker}
- */
- function createMarker(obj, type) {
- let map = _MapHandler.map;
- let imageSrc = obj.imgSrc + '1.png', // 마커이미지의 주소입니다
- size = _size[map.getLevel()],
- imageSize = new kakao.maps.Size(size, size), // 마커이미지의 크기입니다
- imageOption = {
- offset: new kakao.maps.Point(size/2, size/2),
- alt: obj.NAME,
- };
- // 마커의 이미지정보를 가지고 있는 마커이미지를 생성합니다
- let markerImage = new kakao.maps.MarkerImage(imageSrc, imageSize, imageOption),
- markerPosition = getKakaoPosition(obj.Y_CRDN, obj.X_CRDN); // 마커가 표시될 위치입니다
- let marker = new kakao.maps.Marker(
- {map: map, position: markerPosition, image: markerImage, zindex: 10, clickable: true, title : obj.NAME}
- );
- let flag = _MapHandler[type+'Flag'];
- marker.setVisible(flag);
- kakao.maps.event.addListener(marker, 'mouseover', function () {
- if (!obj.isClick) {
- setMarkerImage(obj, 2, false);
- }
- });
- kakao.maps.event.addListener(marker, 'mouseout', function () {
- if (!obj.isClick) {
- setMarkerImage(obj, 1, false)
- }
- });
- kakao.maps.event.addListener(marker, 'click', ()=> _MapHandler.click(type, obj.ID));
- return marker;
- }
- /**
- * 스마트 교차로 카메라 마커 초기화
- * @param obj 스마트 교차로 카메라 객체
- * @returns {kakao.maps.Marker}
- */
- function createIntersectionCameraMarker(obj) {
- const position = getKakaoPosition(obj.Y_CRDN, obj.X_CRDN);
- const content = $('<div id="camera_'+obj.ID+'" title="'+obj.NAME+'">');
- const angle = Number(obj.obj.cmra_angn);
- content.css(
- {
- width: '38.45px',
- height: '38.45px',
- backgroundImage:'url(/images/icon/intersection-cctv.png)',
- backgroundSize : '38.45px 38.45px',
- backgroundRepeat: 'no-repeat',
- backgroundPosition : 'center',
- transform : 'rotate(' + angle +'deg)'
- });
- const marker = new kakao.maps.CustomOverlay({
- content: content[0],
- position: position,
- zindex: 15,
- });
- const linePath1 = [obj.obj.start_x, obj.obj.start_y]
- const linePath2 = [obj.obj.end_x, obj.obj.end_y];
- const color = ['#888888', '#15B337', '#15B337', '#15B337', '#FFAA00', '#FFAA00', '#EB260C', '#EB260C', '#EB260C'];
- obj.polyline = new kakao.maps.Polyline({
- path: [
- getKakaoPosition(linePath1[1], linePath1[0]),
- getKakaoPosition(linePath2[1], linePath2[0]),
- ],
- strokeWeight: 10,
- strokeColor: color[obj.obj.acrd_los],
- strokeOpacity: 1,
- strokeStyle: 'solid',
- endArrow: true,
- name : obj.NAME,
- });
- if (_Level <= 2 && _MapHandler['intersectionFlag']){
- marker.setMap(_MapHandler.map);
- obj.polyline.setMap(_MapHandler.map);
- }
- content.on('click', ()=> {
- obj.click();
- });
- return marker;
- }
- /**
- * 시설물 이미지 유형 변경 이벤트
- * @param obj 시설물 객체
- * @param type 시설물 이미지 유형
- */
- function setMarkerImage(obj, type, isAtrd) {
- const currentLevel = _Level;
- let size = _size[currentLevel];
- let point1 = size/2;
- let point2 = size/2;
- if (isAtrd) {
- size = ( currentLevel >= 7 ) ? 24 : 48;
- point1 = size/2;
- point2 = size;
- }
- const imageSize = new kakao.maps.Size(size, size);
- const imageSrc = obj.imgSrc + type +'.png';
- const imageOption = {
- offset: new kakao.maps.Point(point1, point2),
- alt: obj.NAME
- };
- const markerImage = new kakao.maps.MarkerImage(imageSrc, imageSize, imageOption);
- obj.marker.setImage(markerImage);
- }
- /**
- * 선택 리스트 스크롤 높이 반환 이벤트
- * @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 수신 데이터
- * @param array 시설물 Object Array List
- * @param facilityClass 시설물 Object Class
- * @param listFlag 시설물 리스트 목록 표출 플래그
- * @param type 시설물 유형
- * @returns {*[]} 시설물 Object Array List
- */
- function receiveFacilityData(jsonData, facilityClass, type) {
- if (_MapHandler[type].length > 0) {
- _MapHandler[type].forEach((obj)=>{
- if (obj.marker) {
- obj.marker.setMap(null);
- }
- if (obj.polyline) {
- obj.polyline.setMap(null);
- }
- });
- _MapHandler[type] = [];
- }
- let listStr = "";
- let mobileStr = "";
- if (jsonData && jsonData.length > 0) {
- jsonData.forEach((obj)=>{
- const marker = new facilityClass(obj);
- marker.init();
- if (type === 'intersection') {
- if (obj.detail && obj.detail.length > 0) {
- obj.detail.forEach((cameraObj)=>{
- const camera = new IntersectionCameraObj(cameraObj);
- camera.init();
- _MapHandler[type + 'Camera'].push(camera);
- })
- }
- }
- listStr += `<li id="${type}-${marker.ID}" onclick="infoWindowEvent('${type}', '${marker.ID}' , 'click')">${marker.NAME}</li>`
- mobileStr += `<option value="${marker.ID}">${marker.NAME}</option>`;
- _MapHandler[type].push(marker);
- });
- if (_MapHandler[type + 'Flag']) {
- _MapHandler.show(type);
- }
- }
- if (_MapHandler[type + 'ListFlag'] === true) {
- 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');
- }
- })
- }
- }
- /**
- * 맵 중앙 아이콘 위 위치 좌표
- * @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;
- return [top, left];
- }
- /**
- * 맵 드래그 적용
- */
- function setInfoWindowPositionWidthDraggable(markerObj, type) {
- const {infoWindow, ID} = markerObj;
- const position = getInfoWidowPosition(infoWindow);
- let top = position[0];
- let left = position[1];
- infoWindow.css({
- top : top + 'px',
- left : left + 'px',
- position : 'absolute',
- zIndex : 999,
- });
- infoWindow.draggable({containment : 'body', handle: '.'+ type + '-name-' + ID});
- }
- /**
- * 카카오 포지션 지정
- */
- function getKakaoPosition(yCoordinate, xCoordinate) {
- return new kakao.maps.LatLng(Number(yCoordinate), Number(xCoordinate));
- }
- /**
- * videoJs 객체 생성
- */
- function createVideoJs(id, url) {
- 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', ()=>{
- if (video.error().code === 4) {
- video.pause();
- video.dispose();
- const $errorBox = $('.content > div:nth-child(1)');
- $errorBox.append($('<img src="/images/icon/error.png" alt="스트리밍 오류 이미지">'));
- $errorBox.css({
- display : 'flex',
- alignItems : 'center',
- justifyContent : 'center',
- });
- video = null;
- }
- });
- return video;
- }
- class MapHandler {
- constructor(id) {
- this.selectedObj = null;
- this.map = null;
- this.mapElement = id;
- this.atrd = [];
- }
- init () {
- //시설물별 배열, 토글 플래그, 리스트 플래그 생성
- _FacilityArray.forEach((type)=>{
- this[type] = [];
- this[type + 'Flag'] = false;
- this[type + 'ListFlag'] = false;
- });
- 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);
- const handler = this;
- /**
- * 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 markerArr = handler[type];
- const markerFlag = handler[type + 'Flag'];
- markerSizeChangeWithZoomLevel(markerArr, markerFlag);
- });
- intersectionMarkerChangeWithZoomLevel();
- intersectionCameraChangeWidthZoomLevel();
- if (handler['atrd'].length > 0) {
- atrdMarkerResize();
- }
- getVertex();
- });
- /**
- * 좌표 데이터가의 양이 많으므로 이동 할때마다 영역별 소통정보를 새로 그려줌
- */
- kakao.maps.event.addListener(this.map, 'dragend', function() {
- getVertex();
- });
- }
- //마커 클릭 이벤트
- click(type, id) {
- const markerArr = this[type]; // 시설물 배열
- const markerFlag = this[ type + 'Flag']; // 시설물 토글 플래그
- const markerListFlag = this[ type + 'ListFlag']; // 시설물 토글 플래그
- const atrdArr = this['atrd'];
- if (atrdArr && atrdArr.length > 0) {
- atrdArr.forEach((atrd)=>{
- atrd.close();
- });
- this['atrd'] = [];
- _AtrdData = [];
- const $selectedLi = $('.left-list-area .list-content.list > li.click');
- if ($selectedLi) {
- $selectedLi.removeClass('click');
- }
- }
- let selectObj = this.selectedObj; // 이전 클릭 객체
- let clickObj = this.getSelectObj(markerArr, id); // 현재 클릭 객체
- if (selectObj) {
- if (selectObj === clickObj && type !== 'intersection') {
- return;
- }
- _MapHandler.close(selectObj.type, selectObj.ID);
- }
- const coordinates = getKakaoPosition(clickObj.Y_CRDN, clickObj.X_CRDN);
- this.selectedObj = clickObj;
- const selectedLi = $('#'+type+'-' + clickObj.ID);
- selectedLi.addClass('click');
- selectedLi.focus();
- this.map.setCenter(coordinates);
- if (this['trafficFlag']) {
- getVertex();
- }
- if (clickObj.iwContent) { // 인포 윈도우가 있을때만 실행
- clickObj.infoWindow = $(clickObj.iwContent);
- $('body').append(clickObj.infoWindow);
- setInfoWindowPositionWidthDraggable(clickObj, type);
- }
- if (clickObj.URL) { // Url 유무로 영상 이벤트 실행
- this.videoEvent(clickObj);
- }
- if (type === 'vms') { // vms 일 경우 이미지 표출실행
- this.vmsEvent(clickObj);
- }
- if (type === 'intersection') { // 스마트 교차로는 줌레벨 2로 변경
- this.map.setLevel(2);
- }
- else if (clickObj.imgSrc) { // img src 값이 있는 객체만 클릭 이미지 변경
- setMarkerImage(clickObj, 2, false);
- }
- clickObj.isClick = true;
- if (markerListFlag) {
- moveToScroll(markerFlag, markerArr, clickObj.ID); // 클릭 시 리스트 이동
- }
- }
- //마커 이벤트 종료
- close(type, id) {
- const markerArr = this[type];
- const listFlag = this[type + 'ListFlag'];
- const closeObj = this.getSelectObj(markerArr, id);
- if (closeObj) {
- closeObj.isClick = false;
- this.selectedObj = null;
- if (!type.includes('intersection')) { // 스마트교차로 아닌 화면은 이미지를 원래대로 돌린다.
- setMarkerImage(closeObj, 1, false);
- }
- let oldPlayer = document.getElementById("video-" + closeObj.ID);
- let selectedLi = $("#" + type + "-" + closeObj.ID);
- if (selectedLi.hasClass('click')) { // 선택 리스트가 있는지 여부
- selectedLi.removeClass('click');
- }
- if (listFlag) { // 리스트 플래그 있는지 여부
- $('.mobile-select').val("-");
- }
- if (oldPlayer) { // 켜져있던 영상이 있는지 여부
- videojs(oldPlayer).dispose();
- }
- if (closeObj.infoWindow) { // 인포 윈도우를 화면에 올려놨는지
- closeObj.infoWindow.remove();
- closeObj.infoWindow = null;
- }
- if (closeObj.timer) { // 인터벌 된 객체가 있는지
- clearTimeout(closeObj.timer);
- }
- }
- }
- //선택 객체 찾기
- getSelectObj(array, id) {
- let idx = array.findIndex(obj => obj.ID.toString() === id.toString());
- return array[idx];
- }
- // 마커 보이기
- show(type) {
- this[type].forEach(obj => obj.setVisibleMarker(true));
- this[type + 'Flag'] = true;
- }
- // 마커 숨기기
- hide(type) {
- this[type].forEach(obj => {
- obj.setVisibleMarker(false);
- if (obj.isClick === true) {
- _MapHandler.close(type, obj.ID);
- }
- });
- this[type + 'Flag'] = false;
- }
- //영상 이벤트
- videoEvent(obj) {
- let video = createVideoJs(obj.ID, obj.URL);
- obj.timer = setTimeout(()=>{
- if (video) {
- video.pause();
- }
- }, CCTV_DISPLAY_TIME);
- $('.continue-play').on('click', ()=>{
- if (obj.timer) {
- setTimeout(obj.timer);
- }
- if (video) {
- video.play();
- obj.timer = setTimeout(()=>{
- video.pause();
- }, CCTV_DISPLAY_TIME);
- }
- });
- }
- //vms 이미지 표출 이벤트
- vmsEvent(obj) {
- let cnt = 1;
- if (obj.phaseArray.length > 0) {
- obj.timer = setInterval(()=>{
- if (cnt === obj.phaseArray.length) {
- cnt = 0;
- }
- const activeImage = $('.vms-info-window .content img.active');
- if (activeImage[0]) {
- activeImage.removeClass('active');
- }
- $("#phase-" + obj.phaseArray[cnt]).addClass('active');
- cnt++;
- }, VMS_DISPLAY_TIME);
- }
- }
- }
|