본문 바로가기

프론트엔드/jVectorMap

jVectorMap - 한국 지도 (지역 및 지점 데이터 표시)


한반도 각 시/군/구 또는 광역시도의 데이터는 지역(Region)에 표시하고 특별한 지점(위/경도)도 표시하는 샘플..

티스토리 본문 창이 작은걸 감안하지 않고 페이지를 만들어서 범례가 짤리므로 새창으로 보는걸 추천...

시간이 없어서 복합 데이터 표출을 못한건 안자랑...
그러나 기존 유료 컴퍼넌트를 대체한건 자랑 


Result


Style

body{
	font-size: medium;
}
.jvm-legend {
	line-height: 2em;
	margin-top: 5px;
}
.jvm-legend span {
	vertical-align: middle;
}
.jvm-legend-item {
	width: 2em;
	height: 2em;
	display: inline-block;
	border-style : solid;
	border-color : black;
	border-width : 1px; 
}

.jvm-legend-item-15 {
	background: red;
}
.jvm-legend-item-10 {
	background: orange;
}
.jvm-legend-item-5 {
	background: yellow;
}
.jvm-legend-item-0 {
	background: white;
}

table .td-legend{
	padding-left: 10px
} 

Source

	function numberFormatComma(n) {
		var reg = /(^[+-]?\d+)(\d{3})/;   // 정규식
		n += '';                          // 숫자를 문자열로 변환
		while (reg.test(n)){
			n = n.replace(reg, '$1' + ',' + '$2');
		}
		return n;
	}

	var jMap = null;
	function convert(latitude, longitude) {
		// lat : 위도, long : 경도
		
		// QGIS > SVG 플러그인 속성에 적은 가로-세로
		var width = 823;
		var height = 823;

		// QGIS > SVG 플러그인 속성에서 SET 된 각 한계선
		var eastLong = 132.054062;		// 우측 한계선
		var westLong = 124.410858;		// 좌측 한계선
		var northLat = 39.686848;		// 상측 한계선
		var southLat = 32.043644;		// 하측 한계선
		
		// 경도 -> x
		var longDiff = eastLong - westLong;
		var lon = (longitude - westLong) * (width / longDiff);
		
		// 위도 -> y
		var latDiff = northLat - southLat;
		var lat = (northLat - latitude) * (height / latDiff);
		
		return [ lon, lat];
	}
	
	var sourceData = [
	                  {stnId : '105',	stnNm : '강릉',		lati : '37.75147',	lngt : '128.89098', heatWave : 10},
	                  {stnId : '295',	stnNm : '남해',		lati : '34.81663',	lngt : '127.92641', heatWave : 11},
	                  {stnId : '104',	stnNm : '북강릉',		lati : '37.80456',	lngt : '128.85535', heatWave : 11},
	                  {stnId : '255',	stnNm : '북창원',		lati : '35.2264',	lngt : '128.6725',  heatWave : 16},
	                  {stnId : '121',	stnNm : '영월',		lati : '37.18126',	lngt : '128.45743', heatWave : 18},
	                  {stnId : '211',	stnNm : '인제',		lati : '38.05987',	lngt : '128.16713', heatWave : 7},
	                  {stnId : '192',	stnNm : '진주',		lati : '35.16379',	lngt : '128.04002', heatWave : 14},
	                  {stnId : '155',	stnNm : '창원',		lati : '35.1702',	lngt : '128.57285', heatWave : 16},
	                  {stnId : '95',	stnNm : '철원',		lati : '38.14788',	lngt : '127.3042',   heatWave : 8},
	                  {stnId : '216',	stnNm : '태백',		lati : '37.17031',	lngt : '128.98928', heatWave : 1},
	                  {stnId : '162',	stnNm : '통영',		lati : '34.84546',	lngt : '128.4356',   heatWave : 3}
                  ];
	var markers = [];
	jQuery.each(sourceData, function(){
		var obj = {};
		var color = '';
		obj.coords = convert(this.lati, this.lngt);
		obj.stnNm = this.stnNm;
		obj.stnId = this.stnId;
		obj.heatWave = this.heatWave;
		obj.style = {};
		var val = Number(obj.heatWave);
		if(val >= 15){
			color = 'red';
		}
		else if(val >= 10){
			color = 'orange';
		}
		else if(val >= 5){
			color = 'yellow';
		}
		else {
			color = 'white';
		}
		
		obj.style.fill = color;
		obj.style.r = 5;
		markers.push(obj);
	});
	
	var countryData = []; 
	// 진주시
	countryData['38030'] = 339445;
	countryData['38050'] = 144017;
	countryData['38060'] = 116688;
	countryData['38070'] = 523177;
	countryData['38080'] = 110516;
	countryData['38090'] = 241711;
	countryData['38100'] = 270933;
	countryData['38310'] = 30728;
	countryData['38320'] = 70100;
	countryData['38330'] = 63766;
	countryData['38340'] = 58902;
	
	countryData['11010'] = 143089;
	countryData['11020'] = 143089;
	countryData['11030'] = 256614;
	countryData['11040'] = 307801;
	countryData['11050'] = 385874;
	countryData['11060'] = 377467;
	countryData['11070'] = 425101;
	countryData['11080'] = 492429;
	countryData['11090'] = 347817;
	countryData['11100'] = 365404;
	countryData['11110'] = 605521;
	countryData['11120'] = 506691;
	countryData['11130'] = 321183;
	countryData['11140'] = 395754;
	countryData['11150'] = 501855;
	countryData['11160'] = 574777;
	countryData['11170'] = 456694;
	countryData['11180'] = 262228;
	countryData['11190'] = 430516;
	countryData['11200'] = 414415;
	countryData['11210'] = 543477;
	countryData['11220'] = 441645;
	countryData['11230'] = 568685;
	countryData['11240'] = 686472;
	countryData['11250'] = 494186;

	$(document).ready(function() {
		width = $('#jvm_worldMap').width();

		jMap = $('#jvm_worldMap').vectorMap({
			map : 'korea_mill_en',
			markerStyle : {
				initial : {
					fill : '#F8E23B',
					stroke : '#383f47'
				}
			},
			series : {
				regions : [ {
					values : countryData,
					scale : [ '#C8EEFF', '#0071A4' ],	// two colors: for minimum and maximum values 
					normalizeFunction : 'polynomial'
				} ]
			},
			markers : markers,
			markerStyle : {
				hover: {
					stroke: 'black',
					r : 10
				},
			},
            onMarkerLabelShow: function(e, el, idx) {
           		var msg = el.html();
            	var source = markers[idx];
            	var mapObject = jMap.vectorMap('get', 'mapObject');
            	msg += ""+source.stnNm+"";
            	msg += "
지점ID : "+source.stnId+""; msg += "
폭염일수 : "+source.heatWave+""; // 맵 다시 그리기.. mapObject.onResize(); el.html(msg); }, //----------------------------------------------- // changed to onRegionLabelShow from onLabelShow //----------------------------------------------- onRegionLabelShow: function(e, el, code) { jQuery.each(countryData, function(name, value){ if(name == code && value != undefined){ el.html(el.html() + "
인구 : "+ numberFormatComma(Number(value))); return; } }); } }); var map = $('#jvm_worldMap').vectorMap('get', 'mapObject'); var range = [50000, 100000, 300000, 500000]; jQuery(range).each(function(idx, value){ color = map.series.regions[0].scale.getValue(value); var span = jQuery('').addClass('jvm-legend-item').css('background', color); var valSpan = jQuery('').append(' '+numberFormatComma(value)); jQuery('#regionDiv').append(span).append(valSpan).append('
'); }); });


HTML
	
지점 범례
> 15
> 10
> 5
> 0

지역 범례

  • 츤데레 2013.11.25 12:18 댓글주소 수정/삭제 댓글쓰기

    안녕하세요. JVectorMap을 이용하고 있는데요..

    마커를 찍고있는데요...

    스위스라는 글이 적히면 스위스에 마커를 표시해야하는데

    lat과 lng를...알아내는 함수가 혹시 존재하나요..?

    • 안녕하세요.
      어떤 맵을 사용하시는지요..?
      기본적인 world-map 사용하시면 lati, lngt로 지점을 표시하실 수 있어요.
      그리고 마우스 동작이 아닌 이벤트로 마커를 표시하는건 구현되어 있지 않을겁니다.

      귀찮아서 저도 못한다고 그러고 넘어갔네요.. ;;

  • 츤데레 2013.11.25 16:10 댓글주소 수정/삭제 댓글쓰기

    안녕하세요.

    빠른 답변 감사합니다.;

    jquery-jvectormap-1.2.2.min.js 요것을 사용중이구요..

    좀 더 자세히 설명드리면 맵이 로드될 때 해당 나라에 대한 글이 있으면 해당 나라에 마커를 찍어줘야하는데

    도저희 좌표를 알 방법이 없어서.. 이거 일일이 구현해줘야하나요? 따로 API가 존재하는지가 궁금했었습니다..

    이벤트라기 보다는 맵이 로딩될 때 마커를 그려줘야해요..

    현재 스위스에 글을 적으면 객체가 생성되며 이 객체는 국가 코드를 가지고 있고요... JVectorMap에도 regions안에 국가 코드가 있잖아요? 여기서 이 두 코드를 if문 처리하여 true가 반환될 때, 해당 국가에 마커를 그리고 싶은데..ㅠㅠ 좌표가없어서 그리질못하고 있습니당..

    좌표를 첨에 강제적으로 박아주는 방법뿐이 없나요? 그것이 싫어서 이렇게 고생하고 있습니다...

  • 츤데레 2013.11.25 18:26 댓글주소 수정/삭제 댓글쓰기

    헉 감사합니다... 현재 point까지 구했는데 map.pointToLatLng 이놈이 자꾸 없는 함수라고 나오네요 크흑..감사합니다. ㅠ

  • 츤데레 2013.11.26 09:40 댓글주소 수정/삭제 댓글쓰기

    저는 포인트는 구했어요

    https://github.com/bjornd/jvectormap/issues/146 에 있습니다. map의 이름이 달랐어요 ㅠㅠ 저는 mapObject로 설정했는데 ㅠㅠ뻘짓...

  • 츤데레 2013.11.26 11:52 댓글주소 수정/삭제 댓글쓰기

    좌표가 올바른 좌표가 아니네요...그래도 컨버팅하는 방법은 저것이 맞습니다..