WebAPIでとったデータをGoogle Mapにのせるの続き的に。
流れ
- 府省ごとの情報システム予算をWebAPIからとってくる
- 府省名から住所をとってくる
- Google Mapを描画
- Google Mapの上に府省ごとに予算額に応じたグラフをD3.jsで描く
使うもの
- IT Dashboard WebAPI
情報システム予算があるので、それを使います。
http://www.itdashboard.go.jp/DataFeeds/webapi#300
- Google Geocoding API
住所を取得するのに使います。
https://developers.google.com/maps/documentation/webservices/?hl=ja
- Google Map API
地図に使います。
https://developers.google.com/maps/?hl=ja
府省ごとの情報システム予算をWebAPIからとってくる
fusho_array{
府省名{
budget: 予算,
lat: 緯度,
lng: 経度
}
}
の形式でデータを入れたいと思います。
まずは、緯度経度は空で府省名だけを入れます。
IT Dashboardの以下のページにサンプルコードもあります。
ポイントは、同じ府省でもシステムごとに予算がとれるので合計してやる必要があるところです。if-elseで分岐しているところがそうです。
あまりよくないかもしれませんが、上記流れをシーケンシャルに実行したいため、async: false
を入れて、同期処理にしています。
function getFushoITBudget() {
$.ajax({
url: "http://www.itdashboard.go.jp/PublicApi/getData.json",
data: {
dataset: "Budget",
field: "organization,sum_budget"
},
async: false
}).done(function(data) {
$.each(data.raw_data, function(i, item) {
if (fusho_array[item.organization] === undefined) {
fusho_array[item.organization] = {
"budget": item.sum_budget
};
} else {
fusho_array[item.organization].budget = Number(fusho_array[item.organization].budget) + item.sum_budget;
}
});
});
}
府省名から住所をとってくる
どうも、府省名によっては、住所が取れないものもあるようです。
そこで、分岐を入れて、とれなかったものはログに吐いています。
こちらも、上記流れをシーケンシャルに実行したいため、async: false
を入れて、同期処理にしています。
function getFushoAddress() {
$.each(fusho_array, function(name, object) {
var geocoding = "http://maps.googleapis.com/maps/api/geocode/json";
$.ajax({
url: geocoding,
data: {
address: name
},
async: false
}).done(function(data) {
if (data.results[0] === undefined) {
console.log(name);
} else {
fusho_array[name]["lat"] = data.results[0].geometry.location.lat;
fusho_array[name]["lng"] = data.results[0].geometry.location.lng;
}
});
});
}
Google Mapを描画
idがmap-canvasの要素にGoogle Mapを表示します。
mapのオプション(mapOptions)の中心地点は、とりあえず、霞が関の緯度経度をハードコーディングしています。s
function handleLoadGoogleMap() {
var mapOptions = {
center: new google.maps.LatLng(35.673838, 139.750899),
zoom: 16,
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: false,
disableDefaultUI: true
};
mymap = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
}
Google Mapの上に府省ごとに予算額に応じたグラフをD3.jsで描く
次のサイトを参考にさせてもらいました。
http://shimz.me/blog/d3-js/3733
overlay
を使うところ以外は通常のd3.jsです。
ポイントは、次の緯度経度をpx座標に変換しているところ。
// 緯度経度をpx座標に変換
var point = this.getProjection().fromLatLngToDivPixel(new google.maps.LatLng(object.lat, object.lng));
<style>
.SvgOverlay {
position: relative;
}
.SvgOverlay svg {
position: absolute;
top: 0;
left: 0;
width: 8000px;
height: 8000px;
}
</style>
function overlayITBudget() {
$.each(fusho_array, function(name, object) {
// D3jsでグラフを表示
if (object.lat !== undefined) {
var overlay = new google.maps.OverlayView(); //OverLayオブジェクトの作成
overlay.onAdd = function() {
//オーバーレイ設定
var layer = d3.select("#map-canvas").append("div").attr("class", "SvgOverlay");
var svg = layer.append("svg");
// 緯度経度をpx座標に変換
var point = this.getProjection().fromLatLngToDivPixel(new google.maps.LatLng(object.lat, object.lng));
overlay.draw = function() {
// 予算で棒グラフで表示
svg.selectAll(".node")
.data([point]).enter()
.append("line")
.attr("class", "node")
.attr("x1", function(d) {
return d.x;
})
.attr("x2", function(d) {
return d.x;
})
.attr("y1", function(d) {
return d.y - object.budget / 1000000000;
})
.attr("y2", function(d) {
return d.y;
})
.style("stroke", "gray")
.style("stroke-width", "10px");
// 府省名をテキストで表示
svg.selectAll("text")
.data([point]).enter()
.append("text")
.attr("x", function(d) {
return d.x;
})
.attr("y", function(d) {
return d.y;
})
.attr("fill", "blue")
.attr("font-size", "12px")
.text(name);
}
overlay.draw();
}
overlay.setMap(mymap);
}
});
}
完成品
<!DOCTYPE html>
<html lang='ja'>
<head>
<meta charset='utf-8'>
<title>府省map</title>
<script type='text/javascript' src='https://maps.googleapis.com/maps/api/js?sensor=false'>
</script>
<script src='js/d3.min.js'></script>
<script src='js/markerwithlabel_packed.js'></script>
<style>
# map-canvas {
width: 100%;
height: 600px;
}
.labels {
color: black;
background-color: white;
font-family: 'Lucida Grande', 'Hiragino Kaku Gothic ProN', 'ヒラギノ角ゴ ProN W3', Meiryo, メイリオ, sans-serif;
font-size: 10px;
text-align: center;
border: 1px solid black;
white-space: nowrap;
}
.SvgOverlay {
position: relative;
}
.SvgOverlay svg {
position: absolute;
top: 0;
left: 0;
width: 8000px;
height: 8000px;
}
</style>
</head>
<body>
<h1>府省情報システム予算</h1>
<div id='map-canvas'></div>
<script src='js/jquery-2.1.1.min.js'></script>
<script type="text/javascript">
var mymap;
var fusho_array = {};
google.maps.event.addDomListener(window, 'load', draw);
function draw() {
getFushoITBudget();
getFushoAddress();
handleLoadGoogleMap();
overlayITBudget();
}
function getFushoITBudget() {
$.ajax({
url: "http://www.itdashboard.go.jp/PublicApi/getData.json",
data: {
dataset: "Budget",
field: "organization,sum_budget"
},
async: false
}).done(function(data) {
$.each(data.raw_data, function(i, item) {
if (fusho_array[item.organization] === undefined) {
fusho_array[item.organization] = {
"budget": item.sum_budget
};
} else {
fusho_array[item.organization].budget = Number(fusho_array[item.organization].budget) + item.sum_budget;
}
});
});
}
function getFushoAddress() {
$.each(fusho_array, function(name, object) {
var geocoding = "http://maps.googleapis.com/maps/api/geocode/json";
$.ajax({
url: geocoding,
data: {
address: name
},
async: false
}).done(function(data) {
if (data.results[0] === undefined) {
console.log(name);
} else {
fusho_array[name]["lat"] = data.results[0].geometry.location.lat;
fusho_array[name]["lng"] = data.results[0].geometry.location.lng;
}
});
});
}
function handleLoadGoogleMap() {
var mapOptions = {
center: new google.maps.LatLng(35.673838, 139.750899),
zoom: 16,
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: false,
disableDefaultUI: true
};
mymap = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
}
function overlayITBudget() {
$.each(fusho_array, function(name, object) {
// D3jsでグラフを表示
if (object.lat !== undefined) {
var overlay = new google.maps.OverlayView(); //OverLayオブジェクトの作成
overlay.onAdd = function() {
//オーバーレイ設定
var layer = d3.select("#map-canvas").append("div").attr("class", "SvgOverlay");
var svg = layer.append("svg");
// 緯度経度をpx座標に変換
var point = this.getProjection().fromLatLngToDivPixel(new google.maps.LatLng(object.lat, object.lng));
overlay.draw = function() {
// 予算で棒グラフで表示
svg.selectAll(".node")
.data([point]).enter()
.append("line")
.attr("class", "node")
.attr("x1", function(d) {
return d.x;
})
.attr("x2", function(d) {
return d.x;
})
.attr("y1", function(d) {
return d.y - object.budget / 1000000000;
})
.attr("y2", function(d) {
return d.y;
})
.style("stroke", "gray")
.style("stroke-width", "10px");
// 府省名をテキストで表示
svg.selectAll("text")
.data([point]).enter()
.append("text")
.attr("x", function(d) {
return d.x;
})
.attr("y", function(d) {
return d.y;
})
.attr("fill", "blue")
.attr("font-size", "12px")
.text(name);
}
overlay.draw();
}
overlay.setMap(mymap);
}
});
}
</script>
</body>
</html>