【D3.js】 SVGで地球儀を描く
データはNaturalEarthの「Admin 0 – Countries」から。
見づらくなるので南極大陸には消えていただいた。
消し方は、ダウンロードしたsahpeデータを Quantum GISに取り込んで、メニューの「レイヤー」から「属性テーブルのオープン」を選択。
属性テーブルの中から「sovereignt」の値が「Antractica」になっている行を選択し、下のほうにあるアイコンから「選択部分を反転する」をクリック。
南極大陸以外が選択されているのを確認して「レイヤー」から「選択部分をベクタファイルとして保存する」をクリック→「Geo JSON」形式で保存。
一応topojsonに変換して軽量化。
1 |
$ topojson -o conuntries.topojson conuntries.geojson |
以上で、地図データ作成終了。
あとは、D3の「Geo Projections」機能を使って表示するだけ。
この辺のデータ作成については、過去の記事に詳細を載せているので興味ある方はこちらを。
サンプルコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
const stage = d3.select("svg"); const seaLayer = stage.append("g"); const landLayer = stage.append("g"); const projection = d3.geoOrthographic() //投影法を指定 const path = d3.geoPath()//geometryをsvgのパスに変換する関数 d3.json("conuntries.topojson", function(json){ //地図情報の読み込み const data = topojson.feature(json, json.objects.conuntries).features; //topojson->geojson変換 /*プロジェクション設定*/ projection .rotate([0,0,0]) //x,y,z回転 .clipAngle(90); //表示する角度 180度を指定すると裏側の大陸まで表示される /*パスジェネレーターにプロジェクションを設定*/ path.projection(projection); /*海面を描画するためのパスをDOMに追加*/ seaLayer.append("path") .datum({type: "Sphere"}) .attr("fill", "blue") /*地図を表示するためのパスをDOMに追加*/ landLayer .selectAll("path") .data(data) .enter() .append("path") .style("background-color", "blue") .attr("fill", "green") .attr("stroke", "#222") .on("mouseover", function(){ d3.select(this).attr("fill", "red"); }) .on("mouseout", function(){ d3.select(this).transition().duration(500).attr("fill", "green"); }) }); /*地形を回転させる*/ const draw = () => { let i = 0; return () => { const w = stage.node().clientWidth; const h = stage.node().clientHeight; i = i+0.5; projection .rotate([i,0,0]) //rotateのx値を増やして横に回転させる .scale(d3.min([w, h]) / 2) //画面サイズを元に地球儀の大きさを決定 .translate([w/2, h/2]) //画面中央に表示されるように移動する path.projection(projection); //path関数をアップデート seaLayer.select("path").attr("d", path); //海面用パスを描画 landLayer.selectAll("path").attr("d", path); //地図用パスを描画 } } setInterval(draw(), 100); //定期的に回転させる |