D3.jsで日本地図に地点をプロットしてツールチップを表示してみる
作ったもの
キャップ野球チームの全国分布図を作成。
- チームカラー
- (あれば)チーム旗
動作イメージ
地図データの準備
地図データはshapeファイルで提供されているものをGeoJSON→topojson化する。
npm i topojson -g
$ wget http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_admin_1_states_provinces.zip
# zip解凍 $ unzip ne_10m_admin_1_states_provinces.zip
# ogr2ogrが含まれているgdalをインストールする $ brew install gdal
# GeoJSONから日本のデータのみ抽出してtopoJson化する $ ogr2ogr -f GeoJSON -where "adm0_a3 = 'JPN'" ne_pref_japan_geo.json ne_10m_admin_1_states_provinces.shp
CRAでd3を扱う
準備
# d3とtopojson-clientをインストールする $ npm i --save d3 topojson-client
reactでzoom機能を扱う
コンストラクタでzoom機能を定義する
this.zoom = d3 .zoom() .scaleExtent([-5, Infinity]) .translateExtent([ [-100, -100], [200, 300] ]) .extent([ [0, 0], [0, 0] ]) .on("zoom", this.zoomed.bind(this));
zoomしたときに再描画を発火させるのがミソ。
zoomed() { this.setState({ zoomTransform: d3.event.transform }); }
点をプロットする
プロットする点のデータ構造
{ name:"学習院大", y:35.71, x:139.7, teamId: 73, color:"lightblue" },
データから円を書く
svg
.append("g")
.attr("id", "circle-g")
.selectAll("circle")
.data(teamInfo)
.enter()
.append("circle");
円を塗りつぶす
データで定義した色で塗りつぶします。 マウスオーバーしたときにツールチップに表示する情報や、 表示の切り替えなどもここで記述しています。
svg
.selectAll("#circle-g circle")
.attr("fill", (d)=>{
return (d.color !== undefined ? d.color :'gray')
})
//.attr("opacity", 0.5)
.attr("transform", function(d) {
var coord = projection([d.x, d.y]);
return "translate(" + coord.join(",") + ")";
})
.on("mouseover", function(d) {
//console.log(d.name);
tooltip
.style("display", "block")
.html(
`<div>
<h1>${d.name}</h1>
<div
style={{
display: flex,
margin: 10px
}}
>
<img src="/images/${d.teamId}.jpg" width="100" />
</div>
</div>`
)
})
.attr("r", 5 / (d3.event !== null ? d3.event.transform.k : 1));
