d3.jsで地図をぬるっとアニメーションさせる。
前回、d3で気象庁降灰予報を描画しましたが、
https://qiita.com/miyawa-tarou/items/f101f0248cdc5744302d
地図の中心緯度経度やズームなどは一度描画した後でも変えることができます。
また単に変えるのではなく、ぬるっとスムーズにアニメーションしながら動かすことができます。
完成版はこちら:https://miyawa-tarou.github.io/d3_nuru_map/
基本は前回のコードをもとに説明します。今回の説明に邪魔なので桜島に置いた丸は消しています。
https://github.com/miyawa-tarou/d3_nuru_map/tree/01.setting
1.クリックしたらズームするようにする
やることは、初めに設定した
// 中心座標とスケール
var projection = d3.geoMercator()
.center([137, 38])
.scale(1600)
.translate([width / 2, height / 2]);
この部分を
pathのtransform属性で再定義するような形になります。
今回鹿児島をクリックしたらズームするという形にします。
svg.selectAll("path") // おまじない。というか理解できてない
.data(topojson.feature(data, data.objects.pref).features)
.enter() // dataで入れた配列をそれぞれ以下のpathにしていく
.append("path")
.attr("d", path) // <path d="">に path()の返り値を入れていく
.attr("fill", function(d,i){ return d.properties.code === 46 ? "darkgreen" : "green";}) // 鹿児島だけダークグリーン
.on("click", function(d,i){ // 各pathをクリックすると実行されることを書く
if (d.properties.code === 46) { // 鹿児島をクリックしたときに
var zoomCenter = projection([130.6, 31.6]); // 中心座標
var zoom = 20000/1600; // ズーム
svg.selectAll("path").attr("transform", "translate(" + width/2 + "," + height/2 + ")scale(" + zoom + ")translate(" + - zoomCenter[0] + "," + - zoomCenter[1] + ")");
}
});
すべてのpathに対して移動・ズームするため、
svg.selectAll("path")
に対して行っています。classやidなどで指定を限定すれば一部だけ動かすみたいなことも可能です。
この時ズームに20000/1600を入れていますが、ここは「はじめの設定からのズーム比」になります。
なので前回桜島にズームしたときscale(20000)にしたため、初期のズーム1600との比の20000/1600にしています。
もし2度以上移動する場合も、scale()ははじめの1600基準の数値になります(多分)
そしてtransform属性に
translate():おまじないのwidth/2, height/2 を入れる
scale():上で説明した通り
translate():移動先の座標
を入れます(参考:https://developer.mozilla.org/ja/docs/Web/SVG/Attribute/transform )
scale()を指定しなければ移動するだけです。1以下にすればズームアウトするはずです。
2.降灰予報もズームする
1では地図はズームしましたが、肝心の降灰予報がごみのようにズームされずにそのまま残っています。
これは前回書いたのがpolygonタグだったためで、pathで書けば同様に処理されます。
初めにMをつけて区切り文字をLにしZで終了すると同じものが描画できます。
https://qiita.com/a-ide/items/107c9044d0f4e0354112#%E3%83%91%E3%82%B9
svg.append('g')
.attr('class', 'ashFall')
.append("path")
.attr("d", 'M' + svgCoordinate.join('L') + 'Z') // "Mx,yLx,yLx,yZ"
3.ぬるっと動かす
d3ではズームする際に簡単にアニメーションにすることができます
svg.selectAll("path").transition().duration(2000).attr("transform", ...);
.transition().duration(2000)
を追加しただけです。
duration()の引数が移動の時間でミリ秒になります。
ここが一番楽しいけどQiitaには貼れないのが残念
ちなみに回転とかもできますが、今回はそれはなしで。
また動き方も直線的なのから加速していくのなども指定できます(ease()を挟む)
詳しくは
4.火山灰の枠線をどうにかする
ズームすると線がズームの分太くなります。
なんかきもいのでこれも変更します。
地図の方は影響を避けるために別にアニメーションを指定します。
svg.select(".ashFall").select('path').transition().duration(2000).attr("stroke-width", 1600/20000).attr("transform", "translate(" + width/2 + "," + height/2 + ")scale(" + zoom + ")translate(" + - zoomCenter[0] + "," + - zoomCenter[1] + ")");
.attr("stroke-width", 1600/20000)を追加しています。
ズーム前はstroke-widthが1だったので、ズームの分細くしている感じです。
二つのアニメーションが同時に動かせなくて、上で設定したtransformよりこちらの設定が勝ってしまうので、transformをこちらにも記載します。
なんかきれいに細くなっていってない気がするが。。。
ex.クリッカブルに見せるためにカーソルにする
鹿児島をクリックできる感を持たせるためにカーソルにします。
せっかくなので、都道府県ごとにclassを指定し、鹿児島のclassに対してカーソルがつくスタイルシートを当てます
svg.selectAll("path") // おまじない。というか理解できてない
.data(topojson.feature(data, data.objects.pref).features)
.enter() // dataで入れた配列をそれぞれ以下のpathにしていく
.append("path")
.attr("d", path) // <path d="">に path()の返り値を入れていく
.attr("class", function(d,i){ return "Prefs Pref" + d.properties.code;}) // すべての都道府県にPrefsクラスを、各都道府県にPref{Code}クラスを指定
<style>
.Prefs {
fill: green; /* 緑で塗る */
}
.Pref46 { /* 鹿児島限定 */
fill: darkgreen;
cursor: pointer;
}
</style>
Author And Source
この問題について(d3.jsで地図をぬるっとアニメーションさせる。), 我々は、より多くの情報をここで見つけました https://qiita.com/miyawa-tarou/items/3bb6d639b14f08a62248著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .