SVGでボタンの枠線アニメーション
一般的にボタンの枠線のアニメーションはCSSのborderを使う。
CSSだけで完結するので見やすく便利だが、角丸で2点から囲うようなアニメーションを作ろうと思ったらCSSでは難しそうなのでSVGでやってみた。
なんで線を描くだけでSVGを使うかというと破線の間隔(stroke-dasharray)や開始位置(stroke-dashoffset)といった設定が可能な為だ。
SVGを背景にするとアニメーションの設定が出来ないのでインラインSVGにしたが、都度HTMLに挟み込むのは面倒なのでjavascriptで配置する事にした。
ここで難所が現れた何故か埋め込んでも現れないのだ、開発ツール上ではあるのに現れず、CSSも適応されていない。
javascriptで通常何か要素を作る時は「createElement」を使うが、svgのような名前空間を持つ要素を作成する場合は「createElementNS」を使うらしい。
var navs = document.body.querySelectorAll('a.anirect');
navs.forEach(function(nav) {
var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
rect.setAttribute("x", "0.5");
rect.setAttribute("y", "0.5");
rect.setAttribute("rx", "3");
rect.setAttribute("ry", "3");
rect.setAttribute("width", nav.clientWidth - 1);
rect.setAttribute("height", nav.clientHeight - 1);
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
svg.setAttribute("viewBox", "0 0 "+nav.clientWidth+" "+nav.clientHeight);
svg.appendChild(rect);
nav.appendChild(svg);
});
次にCSSですが98というのは要素の高さと幅の合計です。
a.anirect {
color:#FFF;
text-decoration: none;
padding: 5px;
font-size: 12px;
display: block;
position: relative;
}
a.anirect svg {
position: absolute;
top: 0;left: 0;
display:block;
pointer-events: none;
}
a.anirect svg rect {
fill:none;
stroke:#FFF;
stroke-dasharray: 0 98;
stroke-dashoffset: -40;
stroke-width: 1;
transition: stroke-dasharray 500ms 0s ease;
}
a.anirect:hover svg rect {
stroke-dasharray: 98 0;
}