본문 바로가기

d3.js

Google Maps + D3.js

Google Map위에 D3.js를 이용하여 마커 혹은 차트를 랜더링 하는 방법을 알아보자.


우선 Google Map 객체를 생성해보자.

Google Map 객체는 MapOption 줌레벨, 지도유형 등을 세팅 가능하다.

자세한 사항은 여기를 참고하기 바란다.

var map = new google.maps.Map(d3.select("#map").node(), {
	zoom: 12, 
	center: new google.maps.LatLng(37.556059, 126.91009),
	mapTypeId: google.maps.MapTypeId.ROADMAP
});

여기서는 줌레벨과 초기 지도 센터 위도/경도 정보, 그리고 지도유형을 설정하였다.


이제 지도위에 마커정보(위도/경도)와 오버레이 객체를 생성한다.

지도위에 마커나 차트를 랜더링하기 위해서는 오버레이 객체를 생성해야 한다.

오버레이는 지도 상의 위도/경도 좌표에 연결된 객체를 말한다.

지도를 드래그하거나 확대/축소하면 연결된 오버레이도 함께 움직이며 지도에 '추가'하는 객체를 말한다.

var overlay = new google.maps.OverlayView();
var data = {"우리집":[126.8998768,37.4639925, 15,],"구로디지털단지역":[126.901472,37.48525, 15,2], /*생략*/};

data는 마커용 라벨정보와 위도/경도 정보 마커크기, 그리고 지하철 노선정보가 있다. 이 데이터를 이용하여 D3.js로 Circle를 랜더링할 수 있으며 이 글에서는 해당 정보에서 위도/경도만 사용하여 Pie Chart를 그려보고자 한다.

이제 오버레이에 Pie Chart를 랜더링 해보자.

overlay.onAdd = function() {
	var layer = d3.select(this.getPanes().overlayMouseTarget).append("div").attr("class", "stations");
		
	overlay.draw = function() {
		var projection = this.getProjection(), padding = 50;

여기까지 코드를 살펴보면 지도에 오버레이 랜더링할 준비가 되었을 경우(onAdd) stations div를 추가하고

오버레이에 초기 랜더링(draw)해준다. getProjection()은 Map상에 표시할 좌표를 계산하기 위한 메소드이다.

여기서 중요한건 overlayMouseTarget이다. 마커나 차트에 이벤트 바인딩을 하려면 해당 속성을 지정해줘야 한다.


이제 실제 마커할 D3.js소스를 추가해보자. 여기서 Pie Chart는 NVD3.js 라이브러리를 사용하였다.

		var marker = layer.selectAll("svg")
			.data(d3.entries(data))
			.each(transform)
			.enter().append("svg:svg")
			.each(transform)
			.attr("class", "marker");

		var pieData = [{"key": "One","value" : 29.765957771107} , {"key": "Two","value" : 10} ,{"key": "Three","value" : 32.807804682612} , {"key": "Four","value" : 196.45946739256}];

		nv.addGraph(function() {
			var chart = nv.models.pieChart()
				.x(function(d) { return d.key; })
				.y(function(d) { return d.value; })
				.margin({top: 0, right: 0, bottom: 0, left: 0})
				.showLabels(true)
				.labelThreshold(.05)
				.donut(true)
				.showLegend(false);
						  
			marker.datum(pieData).transition().duration(1200).call(chart);

			return chart;
		});
		function transform(d) {
			d = new google.maps.LatLng(d.value[1], d.value[0]);
			d = projection.fromLatLngToDivPixel(d);
			return d3.select(this)
				.style("left", (d.x-padding) + "px")
				.style("top", (d.y-padding) + "px");
		}
	}; //overlay.draw end
}; //overlay.onAdd end
overlay.setMap(map);

2번 라인 d3.entries(data)으로 data를 key, value로 변경해준다.

[{"key":"우리집","value":[126.8998768,37.4639925,15]},{"key":"구로디지털단지역","value":[126.901472,37.48525,15,2]}];

3번 라인에서 data 갯수만큼 each 메소드이용하여 24-30라인의 transform함수를 호출한다.

transform함수의 역활은 Map상에서 실제 마커될 Pie Chart의 픽셀 위치를 위도/경도를 이용하여 세팅해준다.


1-6라인으로 생성된 Element


8번 라인은 Pie Chart의 Data이다. 10-23라인은 NVD3.js를 이용한 Pie Chart를 추가해준다.


Google Maps + Pie Chart


Google Map은 zoom_changed, dragend와 같은 각종 이벤트를 제공한다.

해당 이벤트를 사용하는 방법도 간단하게 살펴보자.

google.maps.event.addListener(map, 'zoom_changed', function() {
	var zoomLevel = map.getZoom();
	var lat_south = map.getBounds().getSouthWest().lat();
	var lat_north = map.getBounds().getNorthEast().lat();
	var lng_west = map.getBounds().getSouthWest().lng();
	var lng_east = map.getBounds().getNorthEast().lng();
	var lat_center = map.getCenter().lat();
	var lng_center = map.getCenter().lng();
});

위 소스를 보면 Google Map에서 zoom_charged 이벤트가 발생할때 Map상에 줌레벨, 위도/경도 정보를 구할 수 있다.

해당 정보를 이용하여 현재 Map상에 표현할 마커나 차트정보를 서버 측에서 구해와 랜더링 할 수 있을 것이다.


서울시 도서관정보 마커



참고자료




'd3.js' 카테고리의 다른 글

Naver Maps + D3.js  (4) 2014.02.18
bar chart  (4) 2013.09.16
Using D3.js to draw a grid‎  (3) 2013.05.31