Google マップでフッタに表示した画像をホバーすると、うにょーって吹き出し線が伸びていくの知ってます?
それに近いものをやってみたくて作ってみました。
これです。
地図には、オープンソースの地図ライブラリ Leaflet を使います。
Leaflet は Facebook とか Evernote とかメジャー Web サービスに使われてたりします。
見たことないですか?
話が逸れました。
本題に入りましょう。
吹き出しからでる線をうにょーってマーカーまで引っ張るアニメーションを SVG で作ります。直線が伸びるだけだから簡単なはず。
既存の吹き出し線
Leaflet の標準の吹き出しはこんな感じ。
吹き出し線のコンテナは以下の HTML で構成されてました。
<div class="leaflet-popup-tip-container">
<div class="leaflet-popup-tip"></div>
</div>
leaflet-popup-tip
が実際に白い吹き出し線の部分。
正方形の白い <div>
を transform: rotate(45deg);
で 45度回転させて、吹き出し線を表現してるようです。
うにょーって伸びる吹き出し線
<div class="leaflet-popup-tip"></div>
を消して、そこに <svg>
と <path>
を突っこんでみる。
その際に線が伸びるアニメーションも追加。
SVG の部分は D3 で実装しました。
// 吹き出しの表示イベント
map.on('popupopen', function (e) {
// 吹き出し線コンテナ DIV に SVG を配置
var svg = d3.select(".leaflet-popup-tip-container").append("svg")
.attr({
class: 'leaflet-popup-tip-svg',
width: 2,
height: 100,
});
// 吹き出し線グラフィックの作成
var c1 = [1, 0];
var c2 = [1, 91];
var carray = [c1, c2];
var line = d3.svg.line()
.x(function(d) {return d[0];})
.y(function(d) {return d[1];});
var path = svg.append('path')
.attr({
'class': 'leaflet-popup-tip-path',
'd': line(carray), // SVG 描画範囲での線の頂点座標
'stroke': 'rgba(255,100,0,0.8)', // 線の色
'stroke-width': 2, // 線の太さ
'stroke-dashoffset': 91 // 点線の開始位置 = 線の全長
})
.style("stroke-dasharray", "91") // 点線の長さ = 線の全長
.style("stroke-linecap", "round");
// アニメーションの実行
path.transition().delay(300).duration(1000).attr('stroke-dashoffset', 0);
});
線が伸びるアニメーションは以下の2つで実現されます。
- stroke-dasharray(点線の長さ): 線の全長と一緒にすると実線になる
- stroke-dashoffset(点線の開始位置): 線の全長と一緒にすると線がすべてしまわれた状態になり、0 にするとすべてが表示された状態になる
吹き出しが消えると SVG 要素も消え、再び表示されたら同じように SVG 要素が作られ、アニメーションが実行されます。
// 吹き出しを閉じたら SVG 要素を削除
map.on('popupclose', function (e) {
e.popup._tipContainer.children[1].remove();
});