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));