json 배열 특정 키 및 데이터 삭제
JSON 배열을 일종의 목록이라고 보고 특정 열 전체를 삭제하고 싶을 때 아래와 같이 간단하게 처리 가능
const arr = [ { XXX: "2", YYY: "3", ZZZ: "4" }, { XXX: "5", YYY: "6", ZZZ: "7" }, { XXX: "1", YYY: "2", ZZZ: "3" } ] // destructure 'YYY' and return the other props only const newArray = arr.map(({YYY, ...rest}) => rest) console.log(newArray)
[참고]
https://stackoverflow.com/questions/24770887/remove-key-value-pair-from-json-object
[네이버 지도] 마커 표시 변경
전에 올린 마커 클러스터링 문서와 이어지는 내용
마커 목록에서 마커를 선택했을 경우 지도 상에 표시된 해당 마커의 디자인을 변경해서 표시
[CSS 추가]
//-------------------------------------- // CSS 추가 //-------------------------------------- // 마커용 css .list > ol > li { display: flex; align-items: center; } .list > ol > li:hover { background-color: rgba(3, 133, 255, 0.5); } .list > ol > li > input { margin-right: 5px; } .cm { display: flex; font-weight: bold; align-items: center; text-align: center; } .cm > div:nth-child(1) { width: 32px; height: 32px; } .cm > div:nth-child(2) { position: absolute; background-color: #2f96fc; width: 32px; height: 32px; border-radius: 28px; line-height: 32px; margin-bottom: 8px; z-index: 9; } .cm > div:nth-child(3) { position: absolute; background-color: #ffffff; width: 24px; height: 24px; border-radius: 24px; line-height: 24px; margin-left: 4px; margin-bottom: 8px; z-index: 10; }
[마커 설정]
//-------------------------------------- // 마커 설정 //-------------------------------------- var markers = []; for (var i = 0, ii = options.length; i < ii; i++) { markers.push(new naver.maps.Marker({ position: new naver.maps.LatLng(options[i].pos[0], options[i].pos[1]), zIndex: 100, icon: { content: [ '<div>', ' <div><img src="marker.png" /></div>', '</div>', ].join(''), anchor: new naver.maps.Point(11, 33), } })); }
[마커 표시]
//-------------------------------------- // 마커 표시 //-------------------------------------- // 마커 info 속성 표시 function showMarkerInfo(marker) { var img = $(marker.getIcon().content).find('img'); var chk = img.attr('choose'); var json = attr2json(img.attr('info')); var li = $('마커 : code = '+ json.code +', name = '+ json.name +''); $('#list').append(li); //체크박스 change 이벤트 설정 li.on('change', chooseMarker.bind(this, json.code, marker)); }
[선택한 마커 아이콘 변경]
//-------------------------------------- // 선택한 마커 아이콘 변경 //-------------------------------------- var _cCount = 0; //체크한 마커 아이콘 변경 function chooseMarker(c, marker) { var img = $(marker.getIcon().content).find('img'); if ($('#cb'+ c).prop('checked')) { _cCount++; var icon = { content: [ '<div class="cm">', ' <div><img src="marker.png" /></div>', ' <div> </div>', ' <div>'+ _cCount +'</div>', '</div>', ].join(''), anchor: new naver.maps.Point(16, 33), }; } else { _cCount--; var icon = { content: [ '<div>', ' <div><img src="marker.png" /></div>', '</div>', ].join(''), anchor: new naver.maps.Point(11, 33), }; } marker.setIcon(icon); }
'기타' 카테고리의 다른 글
[네이버 지도] 행정구역 표시(오픈API 이용) (0) | 2021.05.12 |
---|---|
[CSS] 버튼 클릭 시 테두리 및 효과 삭제 (0) | 2021.04.13 |
[네이버 지도] 마커 클러스터링 (0) | 2021.01.14 |
[네이버 지도] 사용자 정의 오버레이 (0) | 2021.01.13 |
[네이버 지도] 행정구역 표시(shp -> geojson) (0) | 2021.01.07 |
[네이버 지도] 마커 클러스터링
네이버 지도에서 마커를 표시할 때 지도가 축소되면 마커를 묶어서 표시
네이버에서는 마커를 묶어서 표시하기 위해 예제를 제공하고 있다.(아래 참고)
그 예제를 약간 수정하여 마커 클러스터링을 구현한 소스
준비물: jquery-3.5.1.min.js, MarkerClustering.js
[지도 html]
//-------------------------------------- // 지도 html //-------------------------------------- <html> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>마커 클러스터링</title> <script type="text/javascript" src="jquery-3.5.1.min.js"></script> <script type="text/javascript" src="marker-clustering-custom.js"></script> <style type="text/css"> body { font-size: 12px; font-family: dotum; } input { height: 22px; background-color: #efefef; border: 1px solid #333333; border-radius: 4px; } .div_map { display:flex; flex-direction: row; } .map { width: 1000px; height: 600px; border: 1px solid #c0c0c0; border-radius: 4px; } .div_list { height: 600px; } .list_title { height: 30px; line-height: 30px; background-color: #efefef; border: 1px solid #c0c0c0; border-radius: 4px; margin: 0 0 5px 5px; font-weight: bold; padding-left: 10px; } .list { width: 320px; height: 563px; border: 1px solid #c0c0c0; border-radius: 4px; margin-left: 5px; overflow-y: auto; } .list > ol { line-height: 1.7em; } .ctl { display: flex; flex-direction: row; justify-content: space-between; width:1000px; margin-top: 5px; } .pos { display: flex; flex-direction: row; justify-content: space-between; } .ctl input { text-align: center; } .pos button { height: 26px; border: 1px solid #333333; border-radius: 4px; } .pos > div:nth-child(2) { margin-left: 6px; } </style> </head> <body> <div> <div class="div_map"> <div id="map" class="map"> </div> <div class="div_list"> <div class="list_title">마커 목록</div> <div class="list"> </div> </div> </div> <div class="ctl"> <div><input id="info" readonly="readonly" size="40" type="text" value="" /></div> <div class="pos"> <div> <input id="lat" readonly="readonly" size="20" type="text" value="" /> <input id="lng" readonly="readonly" size="20" type="text" value="" /> </div> <div> <button type="button">좌표 복사</button> <button type="button">원위치</button> </div> </div> </div> </div> </body> </html>
[지도 및 이벤트 설정]
//----------------------------------------------- // 지도 및 이벤트 설정 //----------------------------------------------- var _BASE = new naver.maps.LatLng(37.566605, 126.9783931); // 서울시청 var _ZOOM = 16; // 지도 표시 레벨 var _list = []; // 현재 화면에 표시된 마커 목록 var marker1 = null; // 좌표 조회용 마커 // 지도 옵션 var mapOptions = { center: _BASE, zoom: _ZOOM, zoomControl: true, // 확대,축소 zoomControlOptions: { position : naver.maps.Position.TOP_RIGHT }, //logoControlOptions: { position : naver.maps.Position.BOTTOM_RIGHT }, // 네이버로고 scaleControl: true, // 축척 scaleControlOptions: { position : naver.maps.Position.BOTTOM_RIGHT }, mapDataControl: false, // 저작권 }; // 지도 표시 var map = new naver.maps.Map('map', mapOptions); // 지도 이벤트 설정 naver.maps.Event.addListener(map, 'zoom_changed', function(e) { if (e > 15) { marker1.setMap(map); // 마커1 표시 } else { marker1.setMap(null); // 마커1 삭제 } }); // 마커 목록 삭제 function clearList() { $('#list').empty(); } // 마커 목록 표시 function showList() { _list.forEach(function(item) { showMarkerInfo(item); }); _list = []; } // 현재 위치 표시 showPosition(_BASE); // 위도 경도 표시 function showPosition(latlng) { $('#lat').val(latlng.lat()); $('#lng').val(latlng.lng()); } // 원위치 버튼 클릭 function resetPosition() { map.setCenter(_BASE); map.setZoom(_ZOOM); if (marker1) { marker1.setPosition(_BASE); } showPosition(_BASE); $('#info').val(null); } // 좌표를 클립보드에 복사 function copyPosition() { var info = $('#info'); info.val($('#lat').val() +', '+ $('#lng').val()); info.select(); document.execCommand('copy'); } // 주소 변경 function changeAddr(code) { if (code == '') { map.setCenter(_BASE); } else { showArea(code); } } // 마커1(기본 마커) marker1 = new naver.maps.Marker({ position: _BASE, map: map, zIndex: 200, draggable: true, // 마커1 드래그 허용 }); // 마커1 드래그 허용 //marker1.setDraggable(true); // 마커1 드래그 이벤트 설정 naver.maps.Event.addListener(marker1, 'drag', function(e) { showPosition(e.coord); });
[마커 데이터]
//----------------------------------------------- // 마커 데이터 //----------------------------------------------- var options = [ { pos: [ 37.5675575, 126.9778996 ], info: "code: '1001', name: '1001 사무실'", type: '사무실' }, { pos: [ 37.5674628, 126.9777064 ], info: "code: '1002', name: '1002 사무실'", type: '사무실' }, { pos: [ 37.56749, 126.9779417 ], info: "code: '1003', name: '1003 사무실'", type: '사무실' }, { pos: [ 37.5673746, 126.9778567 ], info: "code: '1004', name: '1004 사무실'", type: '사무실' }, { pos: [ 37.5671748, 126.9780283 ], info: "code: '1005', name: '1005 사무실'", type: '사무실' }, { pos: [ 37.5679912, 126.9779639 ], info: "code: '1006', name: '1006 사무실'", type: '사무실' }, { pos: [ 37.567515, 126.9781677 ], info: "code: '1007', name: '1007 사무실'", type: '사무실' }, { pos: [ 37.5696834, 126.980453 ], info: "code: '1011', name: '1011 사무실'", type: '사무실' }, { pos: [ 37.5698195, 126.9811396 ], info: "code: '1012', name: '1012 사무실'", type: '사무실' }, { pos: [ 37.5693093, 126.9813327 ], info: "code: '1013', name: '1013 사무실'", type: '사무실' }, { pos: [ 37.5698535, 126.9739299 ], info: "code: '1021', name: '1021 공실'", type: '공실' }, { pos: [ 37.56976, 126.9731896 ], info: "code: '1022', name: '1022 공실'", type: '공실' }, { pos: [ 37.5683143, 126.9765907 ], info: "code: '1031', name: '1031 호텔'", type: '호텔' }, { pos: [ 37.5685609, 126.9760328 ], info: "code: '1032', name: '1032 호텔'", type: '호텔' }, { pos: [ 37.5686204, 126.9764405 ], info: "code: '1033', name: '1033 호텔'", type: '호텔' }, { pos: [ 37.5680676, 126.9758611 ], info: "code: '1034', name: '1034 호텔'", type: '호텔' }, { pos: [ 37.5679315, 126.9765048 ], info: "code: '1035', name: '1035 호텔'", type: '호텔' }, { pos: [ 37.5670727, 126.9817405 ], info: "code: '1041', name: '1041 맛집'", type: '맛집' }, { pos: [ 37.5677275, 126.9823842 ], info: "code: '1042', name: '1042 맛집'", type: '맛집' }, { pos: [ 37.5678721, 126.9819122 ], info: "code: '1043', name: '1043 맛집'", type: '맛집' }, { pos: [ 37.5643939, 126.9755392 ], info: "code: '1051', name: '1051 공공기관'", type: '공공기관' }, { pos: [ 37.5643939, 126.9750028 ], info: "code: '1052', name: '1052 공공기관'", type: '공공기관' }, { pos: [ 37.5649382, 126.9818692 ], info: "code: '1061', name: '1061 쇼핑'", type: '쇼핑' }, { pos: [ 37.5647001, 126.9830279 ], info: "code: '1062', name: '1062 쇼핑'", type: '쇼핑' }, { pos: [ 37.5647001, 126.9838862 ], info: "code: '1063', name: '1063 쇼핑'", type: '쇼핑' }, { pos: [ 37.5651763, 126.9813972 ], info: "code: '1064', name: '1064 쇼핑'", type: '쇼핑' }, { pos: [ 37.5651678, 126.983146 ], info: "code: '1065', name: '1065 쇼핑'", type: '쇼핑' }, { pos: [ 37.5653294, 126.9837575 ], info: "code: '1066', name: '1066 쇼핑'", type: '쇼핑' }, { pos: [ 37.5657886, 126.9713335 ], info: "code: '1071', name: '1071 학교'", type: '학교' }, { pos: [ 37.5661118, 126.9706469 ], info: "code: '1072', name: '1072 학교'", type: '학교' }, { pos: [ 37.5656355, 126.9718056 ], info: "code: '1073', name: '1073 학교'", type: '학교' }, { pos: [ 37.5694623, 126.9856243 ], info: "code: '1081', name: '1081 은행'", type: '은행' }, { pos: [ 37.5693178, 126.9850128 ], info: "code: '1082', name: '1082 은행'", type: '은행' }, { pos: [ 37.5695133, 126.9862465 ], info: "code: '1083', name: '1083 은행'", type: '은행' }, { pos: [ 37.568782, 126.9859676 ], info: "code: '1084', name: '1084 은행'", type: '은행' }, ];
[마커 등록 및 이벤트 설정]
//----------------------------------------------- // 마커 등록 및 이벤트 설정 //----------------------------------------------- var markers = []; for (var i = 0, ii = options.length; i < ii; i++) { // info, text 속성을 넣기 위해 HTML 마커 사용 markers.push(new naver.maps.Marker({ position: new naver.maps.LatLng(options[i].pos[0], options[i].pos[1]), zIndex: 100, icon: { content: '', anchor: new naver.maps.Point(11, 33), } })); } // 마커 클릭 이벤트 설정 for (var i = 0, ii = markers.length; i < ii; i++) { naver.maps.Event.addListener(markers[i], 'click', getClickHandler(i)); } // 마커 클릭 이벤트 function getClickHandler(seq) { return function(e) { clearList(); showMarkerInfo(markers[seq]); } } // html 속성값을 json 변환 function attr2json(attr) { var json = {}; var s = attr.trim().split(','); for (var i = 0, ii = s.length; i < ii; i++) { var a = s[i].split(':'); json[a[0].trim()] = a[1].trim().replace(/''/g,''); } return json; }
[클러스터 마커 생성, 변경]
//----------------------------------------------- // 클러스터 마커 생성, 변경 //----------------------------------------------- // 클러스터 마커 생성(HTML 마커) function newMarker(radius, count, name) { var cvs = document.createElement('canvas'); return changeMarker(cvs, radius, count, name); } // 클러스터 마커 변경(HTML 마커) function changeMarker(cvs, radius, count, name) { cvs.width = radius * 2; cvs.height = radius * 2; var ctx = cvs.getContext('2d'); // 원 표시 ctx.beginPath(); ctx.arc(radius, radius, radius, 0, Math.PI * 2); ctx.fillStyle = 'rgba(3, 133, 255, 0.5)'; //#0385ff //ctx.fillStyle = hex2rgba(fillColor, fillOpacity); ctx.fill(); ctx.closePath(); // 텍스트 표시 ctx.textAlign = 'center'; ctx.fillStyle = 'white'; // text color if (name != null) { ctx.font = '16px dotum bold'; ctx.fillText(name, radius, radius - 4); y = radius + 20 - 4; } else { ctx.textBaseline = 'middle'; // 텍스트가 1줄일 경우 사용 y = radius; } if (count != null) { ctx.font = '20px dotum bold'; ctx.fillText(count, radius, y); } return { content: cvs, anchor: naver.maps.Point(radius, radius), } }
[클러스터 마커 설정]
//----------------------------------------------- // 클러스터 마커 설정 //----------------------------------------------- var cMarker1 = newMarker(50, 'm1', 0); var cMarker2 = newMarker(50, 'm2', 0); var cMarker3 = newMarker(50, 'm3', 0); // 마커 클러스터링 var markerClustering = new MarkerClustering({ minClusterSize: 2, // 클러스터 마커를 표시할 최소 마커 개수 maxZoom: 17, // 최대 지도 확대 레벨(maxZoom > map zoom, 클러스터 마커 표시) map: map, // 클러스터 마커 표시할 지도 markers: markers, // 클러스터 마커에서 사용할 마커 목록 disableClickZoom: true, // 클러스터 마커 클릭 시 지도 확대여부 //averageCenter: true, // 마커들의 중간 좌표를 계산하여 클러스터 마커 표시여부 gridSize: 100, // 클러스터 마커 그리드 크기(단위: 픽셀) icons: [cMarker1, cMarker2, cMarker3], // 클러스터 마커용 아이콘 indexGenerator: [10, 50, 100], // 아이콘 표시용 마커 개수 설정 stylingFunction: function(clusterMarker, count, name) { // 클러스터 마커 갱신 시 호출 _list = _list.concat(members); var radius = getRadius(count); // 클러스터 마커 표시 clusterMarker.setIcon(newMarker(radius, count, name)); // 클러스터 마커 이벤트 설정 naver.maps.Event.addListener(clusterMarker, 'mouseover', function(e) { var cvs = clusterMarker.getIcon().content; clusterMarker.setIcon(changeMarker(cvs, radius + 15, count, name)); }); naver.maps.Event.addListener(clusterMarker, 'mouseout', function(e) { var cvs = clusterMarker.getIcon().content; clusterMarker.setIcon(changeMarker(cvs, radius, count, name)); }); naver.maps.Event.addListener(clusterMarker, 'click', function(e) { clearList(); members.forEach(function(item) { showMarkerInfo(item); }); }); } }); // 마커 개수에 따라 반지름 변경 function getRadius(c) { var r = 50; switch (true) { case (c < 3): r = 30; break; case (c < 5): r = 40; break; case (c < 10): r = 50; break; case (c < 20): r = 60; break; case (c < 50): r = 70; break; case (c <100): r = 80; break; } return r; } // 마커 info 속성 표시 function showMarkerInfo(marker) { var info = $(marker.getIcon().content).attr('info'); var json = attr2json(info); $('#list').append('마커 : code = '+ json.code +', name = '+ json.name +''); }
[MarkerClustering.js 수정 부분]
//----------------------------------------------- // MarkerClustering.js 수정 부분 //----------------------------------------------- /** * 클러스터의 아이콘, 텍스트를 갱신합니다. * @private */ _updateClusters: function() { var clusters = this._clusters; clearList(); //추가 for (var i = 0, ii = clusters.length; i < ii; i++) { clusters[i].updateCluster(); } showList(); //추가 }, /** * 클러스터를 구성하는 마커 수를 갱신합니다. */ updateCount: function() { var stylingFunction = this._markerClusterer.getStylingFunction(); //추가 var name = null; if (this._clusterMember.length > 0) { var cZoom = this._markerClusterer.getMaxZoom(); var mZoom = this._markerClusterer.getMap().getZoom(); //지도의 줌 레벨이 클러스터 마커 표시 최대 레벨일 때만 명칭 표시 if (cZoom - 1 == mZoom) { //첫번째 HTML 마커의 text 속성 조회 //문제점: 마커의 명칭이 여러 종류일 경우 명칭 표기에 혼선 name = $(this._clusterMember[0].getIcon().content).attr('text'); } } //추가 stylingFunction && stylingFunction(this._clusterMarker, this.getCount(), name, this._clusterMember); //추가 },
[참고]
'기타' 카테고리의 다른 글
[CSS] 버튼 클릭 시 테두리 및 효과 삭제 (0) | 2021.04.13 |
---|---|
[네이버 지도] 마커 표시 변경 (0) | 2021.01.29 |
[네이버 지도] 사용자 정의 오버레이 (0) | 2021.01.13 |
[네이버 지도] 행정구역 표시(shp -> geojson) (0) | 2021.01.07 |
티스토리 SyntaxHighlighter 3.0.8.3 사용법 (0) | 2018.10.25 |
[네이버 지도] 사용자 정의 오버레이
네이버 지도 마커에 원 도형과 텍스트를 함께 표시하기 위해 사용자 정의 오버레이를 사용해보자.
[사용자 정의 오버레이 설정]
//-------------------------------------- // 사용자 정의 오버레이 설정 //-------------------------------------- // 사용자 정의 오버레이 var CustomOverlay = function(options) { this._element = $(''); this._code = options.code || null; this._position = options.position; this._radius = options.radius || 50; this._fillColor = options.fillColor || '#0385ff'; this._fillOpacity = options.fillOpacity || 0.6; this._strokeColor = options.strokeColor || '#0385ff'; this._strokeOpacity = options.strokeOpacity || 0.6; this._strokeWeight = 1; this._textColor = options.textColor || 'white'; }; // CustomOverlay는 OverlayView를 상속받습니다. CustomOverlay.prototype = new naver.maps.OverlayView(); CustomOverlay.prototype.constructor = CustomOverlay;
[필수 메소드 재정의] onAdd(), onRemove(), draw()
//-------------------------------------- // 필수 메소드 재정의 //-------------------------------------- CustomOverlay.prototype.onAdd = function() { // 오버레이 표시 레이어(floatPane(정보 레이어, 상단)/overlayImage(마커 레이어, 중단)/overlayLayer(도형 레이어, 하단) var overlayLayer = this.getPanes().floatPane; this._element.appendTo(overlayLayer); }; CustomOverlay.prototype.draw = function() { // 지도 객체가 설정되지 않았으면 draw 기능을 하지 않습니다. if (!this.getMap()) { return; } // projection 객체를 통해 LatLng 좌표를 화면 좌표로 변경합니다. var projection = this.getProjection(); var position = this.getPosition(); var pixelPosition = projection.fromCoordToOffset(position); var radius = this._radius; this._element.css('left', pixelPosition.x - radius); this._element.css('top', pixelPosition.y - radius); var cvs = this._element[0]; cvs.width = radius * 2; cvs.height = radius * 2; var ctx = cvs.getContext('2d'); // 원 그리기 ctx.beginPath(); ctx.arc(radius, radius, radius - this._strokeWeight, 0, Math.PI * 2); // 반지름 = radius - this._strokeWeight ctx.fillStyle = hex2rgba(this._fillColor, this._fillOpacity); //rgba(3, 133, 255, 0.5) #0385ff ctx.fill(); ctx.lineWidth = this._strokeWeight; // 기본값: lineWidth = 1 ctx.strokeStyle = hex2rgba(this._strokeColor, this._strokeOpacity); //기본값: strokeStyle = '#000000' ctx.stroke(); ctx.closePath(); // 원 내부에 텍스트 표시 ctx.textAlign = 'center'; //ctx.textBaseline = 'middle'; // 텍스트가 1줄일 경우 사용 ctx.fillStyle = hex2rgba(this._textColor, null); // text color ctx.font = '14px dotum bold'; ctx.fillText(this._code.name, radius, radius - 4); // 글꼴의 크기에 따라 세로 출력 위치 조정 ctx.font = '20px dotum bold'; ctx.fillText(this._code.count, radius, radius + 20 - 4); // 글꼴의 크기에 따라 세로 출력 위치 조정 }; CustomOverlay.prototype.onRemove = function() { this._element.remove(); // 이벤트 핸들러를 설정했다면 정리합니다. this._element.off(); };
[속성 메소드 정의]
//-------------------------------------- // 속성 메소드 정의 //-------------------------------------- CustomOverlay.prototype.getCode = function() { return this._code; }; CustomOverlay.prototype.setCode = function(code) { this._code = code; }; CustomOverlay.prototype.getPosition = function() { return this._position; }; CustomOverlay.prototype.setPosition = function(position) { this._position = position; }; CustomOverlay.prototype.getRadius = function() { return this._radius; }; CustomOverlay.prototype.setRadius = function(radius) { this._radius = radius; }; CustomOverlay.prototype.getFillColor = function() { return this._fillColor; }; CustomOverlay.prototype.setFillColor = function(color) { this._fillColor = color; };
[hex to rgb, colorname to hex]
//-------------------------------------- // hex to rgb, colorname to hex //-------------------------------------- // 색깔코드를 rgba로 변경(color, opacity) function hex2rgba(c, o) { if (c.charAt(0) == '#') { c = c.substr(1); } else { return colorName2Hex(c); //색깔명 사용할 경우 opacity 무시 } if (o == null || o > 1.0 || o < 0) o = 1.0; if (c.length == 3) { c = c.substr(0,1) + c.substr(0,1) + c.substr(1,2) + c.substr(1,2) + c.substr(2,3) + c.substr(2,3); } var r = c.charAt(0) + '' + c.charAt(1); r = parseInt(r, 16); var g = c.charAt(2) + '' + c.charAt(3); g = parseInt(g, 16); var b = c.charAt(4) + '' + c.charAt(5); b = parseInt(b, 16); return 'rgba(' + r + ',' + g + ',' + b + ','+ o +')'; } // 색깔명을 색깔코드로 변경 function colorName2Hex(color) { var colors = {"aliceblue":"#f0f8ff","antiquewhite":"#faebd7","aqua":"#00ffff","aquamarine":"#7fffd4","azure":"#f0ffff", "beige":"#f5f5dc","bisque":"#ffe4c4","black":"#000000","blanchedalmond":"#ffebcd","blue":"#0000ff","blueviolet":"#8a2be2","brown":"#a52a2a","burlywood":"#deb887", "cadetblue":"#5f9ea0","chartreuse":"#7fff00","chocolate":"#d2691e","coral":"#ff7f50","cornflowerblue":"#6495ed","cornsilk":"#fff8dc","crimson":"#dc143c","cyan":"#00ffff", "darkblue":"#00008b","darkcyan":"#008b8b","darkgoldenrod":"#b8860b","darkgray":"#a9a9a9","darkgreen":"#006400","darkkhaki":"#bdb76b","darkmagenta":"#8b008b","darkolivegreen":"#556b2f", "darkorange":"#ff8c00","darkorchid":"#9932cc","darkred":"#8b0000","darksalmon":"#e9967a","darkseagreen":"#8fbc8f","darkslateblue":"#483d8b","darkslategray":"#2f4f4f","darkturquoise":"#00ced1", "darkviolet":"#9400d3","deeppink":"#ff1493","deepskyblue":"#00bfff","dimgray":"#696969","dodgerblue":"#1e90ff", "firebrick":"#b22222","floralwhite":"#fffaf0","forestgreen":"#228b22","fuchsia":"#ff00ff", "gainsboro":"#dcdcdc","ghostwhite":"#f8f8ff","gold":"#ffd700","goldenrod":"#daa520","gray":"#808080","green":"#008000","greenyellow":"#adff2f", "honeydew":"#f0fff0","hotpink":"#ff69b4", "indianred ":"#cd5c5c","indigo":"#4b0082","ivory":"#fffff0","khaki":"#f0e68c", "lavender":"#e6e6fa","lavenderblush":"#fff0f5","lawngreen":"#7cfc00","lemonchiffon":"#fffacd","lightblue":"#add8e6","lightcoral":"#f08080","lightcyan":"#e0ffff","lightgoldenrodyellow":"#fafad2", "lightgrey":"#d3d3d3","lightgreen":"#90ee90","lightpink":"#ffb6c1","lightsalmon":"#ffa07a","lightseagreen":"#20b2aa","lightskyblue":"#87cefa","lightslategray":"#778899","lightsteelblue":"#b0c4de", "lightyellow":"#ffffe0","lime":"#00ff00","limegreen":"#32cd32","linen":"#faf0e6", "magenta":"#ff00ff","maroon":"#800000","mediumaquamarine":"#66cdaa","mediumblue":"#0000cd","mediumorchid":"#ba55d3","mediumpurple":"#9370d8","mediumseagreen":"#3cb371","mediumslateblue":"#7b68ee", "mediumspringgreen":"#00fa9a","mediumturquoise":"#48d1cc","mediumvioletred":"#c71585","midnightblue":"#191970","mintcream":"#f5fffa","mistyrose":"#ffe4e1","moccasin":"#ffe4b5", "navajowhite":"#ffdead","navy":"#000080", "oldlace":"#fdf5e6","olive":"#808000","olivedrab":"#6b8e23","orange":"#ffa500","orangered":"#ff4500","orchid":"#da70d6", "palegoldenrod":"#eee8aa","palegreen":"#98fb98","paleturquoise":"#afeeee","palevioletred":"#d87093","papayawhip":"#ffefd5","peachpuff":"#ffdab9","peru":"#cd853f","pink":"#ffc0cb","plum":"#dda0dd","powderblue":"#b0e0e6","purple":"#800080", "rebeccapurple":"#663399","red":"#ff0000","rosybrown":"#bc8f8f","royalblue":"#4169e1", "saddlebrown":"#8b4513","salmon":"#fa8072","sandybrown":"#f4a460","seagreen":"#2e8b57","seashell":"#fff5ee","sienna":"#a0522d","silver":"#c0c0c0","skyblue":"#87ceeb","slateblue":"#6a5acd","slategray":"#708090","snow":"#fffafa","springgreen":"#00ff7f","steelblue":"#4682b4", "tan":"#d2b48c","teal":"#008080","thistle":"#d8bfd8","tomato":"#ff6347","turquoise":"#40e0d0", "violet":"#ee82ee", "wheat":"#f5deb3","white":"#ffffff","whitesmoke":"#f5f5f5", "yellow":"#ffff00","yellowgreen":"#9acd32"}; if (typeof colors[color.toLowerCase()] != 'undefined') return colors[color.toLowerCase()]; return false; }
[오버레이 표시 및 이벤트 설정]
//-------------------------------------- // 오버레이 표시 및 이벤트 설정 //-------------------------------------- var options = [ { position: TEST1, radius: 50, code: { name: '숙소', count: '5', city: '11', sig: '11290', emd: '11200104', text: '테스트1' } }, { position: TEST2, radius: 50, code: { name: '사무실', count: '99', city: '11', sig: '11290', emd: '11200104', text: '테스트2' } }, { position: TEST3, radius: 50, code: { name: '맛집', count: '3', city: '11', sig: '11290', emd: '11200104', text: '테스트3' } }, ]; var markers = []; // 오버레이 생성 for (var idx in options) { markers.push(new CustomOverlay(options[idx])); } // 오버레이 표시, 이벤트 설정 for (var idx in markers) { markers[idx].setMap(map); markers[idx]._element.on('mouseover', changeRadius(idx, 100)); markers[idx]._element.on('mouseout', changeRadius(idx, 50)); markers[idx]._element.on('click', clickMarker(idx)); } function changeRadius(idx, r) { return function(e) { var marker = markers[idx]; marker.setRadius(r); marker.draw(); } } function clickMarker(idx) { return function(e) { console.log(markers[idx].getCode()); } }
[참고]
https://navermaps.github.io/maps.js.ncp/docs/naver.maps.OverlayView.html
https://navermaps.github.io/maps.js.ncp/docs/tutorial-6-CustomOverlay.html
https://navermaps.github.io/maps.js.ncp/docs/tutorial-custom-overlay.example.html
'기타' 카테고리의 다른 글
[네이버 지도] 마커 표시 변경 (0) | 2021.01.29 |
---|---|
[네이버 지도] 마커 클러스터링 (0) | 2021.01.14 |
[네이버 지도] 행정구역 표시(shp -> geojson) (0) | 2021.01.07 |
티스토리 SyntaxHighlighter 3.0.8.3 사용법 (0) | 2018.10.25 |
택배 조회 URL (0) | 2018.09.18 |
[네이버 지도] 행정구역 표시(shp -> geojson)
준비물: 시도 shp, 시군구 shp, 읍면동 shp
프로그램: mapshaper, QGIS, python 3.9.1
국내 행정구역 shp 파일은 용량도 크고 너무 세밀하게 표현된 부분이 많아서
웹에 단순한 행정구역을 표시할 때 용량과 속도 등에서 제약사항이 발생한다.
국내 행정구역 shp 파일에서 사용된 좌표계는 GRS80 (EPSG: 5179) 이므로
네이버 지도에서 사용하는 위도와 경도 좌표계 WGS84 (EPSG: 4326)로 변환해야 한다.
변환 과정 요약
1. mapshaper 등의 프로그램으로 simplify 과정을 거쳐 단순화(shp ▶ shp)
2. QGIS 등의 프로그램을 이용하여 WGS 84 좌표로 변환(shp ▶ json(geojson))
3. python 등을 이용해 전체 geojson 파일에서 필요한 행정구역 파일로 분할 저장(json ▶ json(geojson))
[시군구 geojson 분할 저장] python 3.9.1
//-------------------------------------- // 시군구 geojson 분할 저장 //-------------------------------------- #python 3.9.1 import json #json 파일 읽기 with open('d:\\sig_202005_wgs84.geojson', 'r', encoding='UTF8') as rf: geojson = json.load(rf) #시군구 반복 for item in geojson['features']: code = item['properties']['SIG_CD'] #행정구역코드 name = item['properties']['SIG_KOR_NM'] #행정구역명 item['id'] = code; #네이버 지도용 id 설정 #json 파일 저장 경로 path = 'd:\\sig\\'+ code +'.json' print(path +' '+ name) #json 객체 생성 geo = dict() geo['type'] = 'FeatureCollection' geo['features'] = [] #features는 배열 geo['features'].append(item) #json 파일 저장 with open(path, 'w', encoding='UTF8') as wf: json.dump(geo, wf, ensure_ascii=False) #한글 유니코드 저장 방지
[행정구역 json 파일 로드]
//-------------------------------------- // 행정구역 json 파일 로드 //-------------------------------------- var HOME_PATH = window.HOME_PATH || '.', urlPrefix = HOME_PATH +'/data/region', urlSuffix = '.json', regionGeoJson = [], loadCount = 0; // 행정구역 json 파일 로드 naver.maps.Event.once(map, 'init_stylemap', function () { for (var i = 1; i < 18; i++) { var keyword = i +''; if (keyword.length === 1) { keyword = '0'+ keyword; } $.ajax({ url: urlPrefix + keyword + urlSuffix, success: function(idx) { return function(geojson) { regionGeoJson[idx] = geojson; loadCount++; if (loadCount === 17) { startDataLayer(); } } }(i - 1) }); } });
[Geojson 파일 형태]
//-------------------------------------- // Geojson 파일 형태 //-------------------------------------- // 툴팁 설정 var tooltip = $('<div style="position: absolute; z-index: 1000; padding: 5px 10px; background-color: #fff; border: solid 2px #000; font-size: 14px; pointer-events: none; display: none;"> </div>'); tooltip.appendTo(map.getPanes().floatPane); // 로드된 행정구역은 아래와 같은 형태 regionGeoJson.push({ "type": "FeatureCollection", "features": [{ "id": "11140", "type": "Feature", "properties": {"SIG_CD": "11140", "SIG_ENG_NM": "Jung-gu", "SIG_KOR_NM": "중구"}, "geometry": { "type": "MultiPolygon", "coordinates": [[[ [127.0233653, 37.5719143], [127.0233917, 37.5719073], [127.0235305, 37.5671585], [127.0235359, 37.5669135], [127.0235319, 37.5668462], [127.0235326, 37.5668336], [127.0217938, 37.5575103], [127.0217328, 37.5575278], [127.0195773, 37.5574955], [127.0196807, 37.5572629], [127.0180939, 37.5568746], [127.0178901, 37.5567028], [127.0162301, 37.5528015], [127.0159829, 37.552589], [127.015938, 37.5525498], [127.015858, 37.552471], [127.0089881, 37.5441349], [127.0050173, 37.5461716], [127.0061278, 37.5481932], [127.0046885, 37.5486851], [127.0045604, 37.5498499], [127.0043733, 37.5501537], [127.0043557, 37.5501974], [127.0043362, 37.5502112], [127.0042094, 37.5501507], [127.0034213, 37.5500195], [127.0028642, 37.5496416], [127.0016841, 37.5500597], [126.9983251, 37.5496954], [126.9944593, 37.547488], [126.9787954, 37.5540872], [126.9724082, 37.5548773], [126.96571, 37.5541518], [126.963376, 37.552259], [126.962778, 37.551848], [126.9626113, 37.5517331], [126.9623428, 37.5515489], [126.9623691, 37.5516032], [126.962376, 37.5516286], [126.9624048, 37.5516477], [126.9623107, 37.55277], [126.9620066, 37.5540349], [126.9619314, 37.554448], [126.9617737, 37.5547951], [126.9617773, 37.554982], [126.9619781, 37.5551268], [126.9621418, 37.5555309], [126.9624769, 37.5559106], [126.9627196, 37.5559726], [126.9631727, 37.5565488], [126.9633575, 37.5566854], [126.9634369, 37.5568535], [126.9634273, 37.5569479], [126.9634093, 37.5569943], [126.963052, 37.5574148], [126.9630411, 37.5580298], [126.9620761, 37.5584566], [126.9615951, 37.5584184], [126.9617358, 37.5588129], [126.961711, 37.5589526], [126.9616892, 37.5589824], [126.9616726, 37.5590258], [126.962956, 37.5591763], [126.9632096, 37.5591958], [126.9633065, 37.5592155], [126.9668376, 37.561274], [126.9674439, 37.5615089], [126.9681526, 37.5616215], [126.969265, 37.5619273], [126.9694319, 37.5619679], [126.9694641, 37.5619758], [126.9693301, 37.5622305], [126.9689586, 37.5629149], [126.967562, 37.5648787], [126.9666982, 37.56582], [126.9668651, 37.5659861], [126.9668874, 37.5660078], [126.9966167, 37.5686865], [126.9968368, 37.5687099], [126.997025, 37.5687315], [127.0007881, 37.5693806], [127.0013078, 37.5694769], [127.014613, 37.5697183], [127.0147018, 37.5697206], [127.0176066, 37.5702101], [127.0177723, 37.5702912], [127.0233653, 37.5719143] ]]] } }] });
[행정구역 표시]
//-------------------------------------- // 행정구역 표시 //-------------------------------------- function startDataLayer() { map.data.setStyle(function(feature) { var styleOptions = { fillColor: '#ff0000', fillOpacity: 0.0001, strokeColor: '#ff0000', strokeWeight: 4, strokeOpacity: 0.4 }; if (feature.getProperty('focus')) { styleOptions.fillOpacity = 0.6; styleOptions.fillColor = '#0f0'; styleOptions.strokeColor = '#0f0'; styleOptions.strokeWeight = 4; styleOptions.strokeOpacity = 1; } return styleOptions; }); regionGeoJson.forEach(function(geojson) { map.data.addGeoJson(geojson); }); map.data.addListener('click', function(e) { var feature = e.feature; if (feature.getProperty('focus') !== true) { feature.setProperty('focus', true); } else { feature.setProperty('focus', false); } }); map.data.addListener('mouseover', function(e) { var feature = e.feature; var regionName = feature.getProperty('SIG_KOR_NM'); tooltip.css({ display: '', left: e.offset.x, top: e.offset.y }).text(regionName); map.data.overrideStyle(feature, { fillOpacity: 0.6, strokeWeight: 4, strokeOpacity: 1 }); }); map.data.addListener('mouseout', function(e) { tooltip.hide().empty(); map.data.revertStyle(); }); } startDataLayer();
참고
'기타' 카테고리의 다른 글
[네이버 지도] 마커 클러스터링 (0) | 2021.01.14 |
---|---|
[네이버 지도] 사용자 정의 오버레이 (0) | 2021.01.13 |
티스토리 SyntaxHighlighter 3.0.8.3 사용법 (0) | 2018.10.25 |
택배 조회 URL (0) | 2018.09.18 |
CSS 이미지 위에 텍스트 표시 (0) | 2018.08.20 |
티스토리 SyntaxHighlighter 3.0.8.3 사용법
아래의 파일을 업로드
~/styles 폴더의 shCore.css 및 테마(shTheme*.css) 파일~/scripts 폴더의 shCore.js 및 브러시(shBrush*.js) 파일
HTML head 태그 부분에 아래의 문장 추가
<head> ... //테마 ... </head>
사용법
html 편집모드에서<pre class="brush:언어별 브러시명"> ... 코드 ... </pre>
언어별 브러시명 및 사용 js 파일은 아래의 페이지를 참조
언어별 브러시'기타' 카테고리의 다른 글
[네이버 지도] 사용자 정의 오버레이 (0) | 2021.01.13 |
---|---|
[네이버 지도] 행정구역 표시(shp -> geojson) (0) | 2021.01.07 |
택배 조회 URL (0) | 2018.09.18 |
CSS 이미지 위에 텍스트 표시 (0) | 2018.08.20 |
[마이플랫폼] Base64 문자열을 이미지 컴포넌트에 표시하기 (0) | 2018.04.26 |
날짜 관련 유틸리티
/** * 지정한 시간(min) 뒤의 시각 반환 * @param min * @return */ public static Date addMin(Integer min) { Calendar c = Calendar.getInstance(); c.add(Calendar.MINUTE, min); return c.getTime(); } /** * 오늘 23:59:59 시각 반환 * @return */ public static Date getTodayMidnight() { Calendar c = Calendar.getInstance(); c.set(c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DATE), 23, 59, 59); return c.getTime(); }
'Java' 카테고리의 다른 글
[POI 3.17] 이름 정의 및 데이터 유효성 검사 추가(드롭다운 구현) (0) | 2021.11.05 |
---|---|
List 다중 컬럼 정렬 (0) | 2021.05.21 |
JDK 8 인스톨 없이 설치하기 (0) | 2018.10.20 |
사진 이미지 크기 변경 후 Base64 문자열 변환 (0) | 2018.04.26 |
POI, Excel 셀 생성 (0) | 2015.06.30 |
JDK 8 인스톨 없이 설치하기
윈도우 운영체제에 독립 이클립스 개발환경을 구축하려면 JDK를 인스톨해야 한다.
하지만 윈도우 운영체제에 JDK를 인스톨 없이 이용하고자 한다면 아래와 같이 해보자.
1. 오라클 사이트에서 윈도우용 JDK 8u191 버전을 다운로드 한다.
jdk-8u191-windows-x64.exe
2. 7zip 과 같은 압축 해제 유틸리티로 다운받은 파일을 설치하지 않고 압축을 해제한다.
3. ~/.rsrc/1033/JAVA_CAB10 폴더 안의 111 파일을 오른쪽 버튼을 눌러
'여기에 압축 풀기'를 선택하면 tools.zip 파일이 생긴다.
3.1. tools.zip 파일 압축을 풀어 폴더명을 jdk-8u191-x64 같이 바꿔준다.
3.2. 명령 프롬프트를 실행하여 압축을 푼 폴더로 가서 아래와 같은 명령을 실행한다.
for /r %i in (*.pack) do .\bin\unpack200.exe %i %~pi%~ni.jar
4. ~/.rsrc/1033/JAVA_CAB9 폴더 안의 110 파일을 오른쪽 버튼을 눌러
'여기에 압축 풀기'를 선택하면 src.zip 파일이 생긴다. 3.1.에서 만든 폴더에 넣어준다.
5. ~/.rsrc/1033/JAVA_CAB11 폴더 안의 112 파일을 오른쪽 버튼을 눌러
'여기에 압축 풀기'를 선택하면 COPYRIGHT 파일이 생긴다. 3.1.에서 만든 폴더에 넣어준다.
6. 이 폴더를 이클립스 환경설정에서 사용하면 된다.
'Java' 카테고리의 다른 글
List 다중 컬럼 정렬 (0) | 2021.05.21 |
---|---|
날짜 관련 유틸리티 (0) | 2018.10.23 |
사진 이미지 크기 변경 후 Base64 문자열 변환 (0) | 2018.04.26 |
POI, Excel 셀 생성 (0) | 2015.06.30 |
POI, Excel 숫자 셀 생성 (0) | 2015.06.30 |
아래의 택배 배송 조회 URL은
다음 배송조회 화면을 통해서 현재(2018.09.18) 확인된 URL 입니다.
아래 URL은 택배사의 사정에 따라 언제든지 변경될 수 있으니 확인하고 사용하세요.
CJ 대한통운
https://www.doortodoor.co.kr/parcel/doortodoor.do?fsp_action=PARC_ACT_002&fsp_cmd=retrieveInvNoACT&invc_no=운송장번호
우체국택배
https://service.epost.go.kr/trace.RetrieveEmsRigiTraceList.comm?POST_CODE=운송장번호
롯데택배https://www.lotteglogis.com/personalService/tracking/06/tracking_goods_result.jsp?InvNo=운송장번호
로젠택배
http://www.ilogen.com/iLOGEN.Web.New/TRACE/TraceView.aspx?gubun=slipno&slipno=운송장번호
한진택배
http://www.hanjin.co.kr/Delivery_html/inquiry/result_waybill.jsp?wbl_num=운송장번호
드림택배(구KG로지스)
http://www.idreamlogis.com/delivery/delivery_result.jsp?item_no=운송장번호
'기타' 카테고리의 다른 글
[네이버 지도] 행정구역 표시(shp -> geojson) (0) | 2021.01.07 |
---|---|
티스토리 SyntaxHighlighter 3.0.8.3 사용법 (0) | 2018.10.25 |
CSS 이미지 위에 텍스트 표시 (0) | 2018.08.20 |
[마이플랫폼] Base64 문자열을 이미지 컴포넌트에 표시하기 (0) | 2018.04.26 |
Web API CORS 관련 문제 해결(개발 시) (0) | 2017.12.22 |
Angular 5 이미지 Base64 문자열 변환(primeng fileupload 컴포넌트 사용)
uploadImage(event, fu: FileUpload) { // file.name, file.size, file.type, file.objectURL const file: File = event.files[0]; const reader: FileReader = new FileReader(); reader.onloadend = (e) => { this.image = reader.result as string; // Base64 문자열 이미지 데이터 저장 fu.clear(); // 다시 업로드 가능하게 초기화 }; if (file) { reader.readAsDataURL(file); // Base64 문자열 변환 } }
'Angular' 카테고리의 다른 글
[Angular] video.js(v7.21.6) 설정 (0) | 2024.06.17 |
---|---|
[Angular] 동적 파이프(Dynamic Pipe) (0) | 2023.03.02 |
[Angular] 테이블 tr 태그에 포커스 (0) | 2021.10.22 |
[Angular] 문자열 표시 파이프(V2) (0) | 2021.05.24 |
[Angular] 숫자형식 표시 파이프(v3) (0) | 2021.05.20 |