SVGのロゴをネオンサインが点灯するようなイメージのアニメーションにできないかと試行錯誤した結果を記事に残しておく。
最終完成バージョン
まずは出来上がりを、Codepen で確認してほしい。Start ボタンを押すと、ロゴが点灯する。
ネオンサインが点灯する雰囲気にみえるとうれしい。
(と言っても、今となってはネオン管っぽいLEDチューブが主流なので、本物のネオン管を見たことがない世代が多いかもしれないが...)
See the Pen Neon Sign by hiroatsu (@scqspcfg-the-solid) on CodePen.
なお、このアニメーションは、地図共有サイト Toboggar のスプラッシュ画面で使用しているものである。
どうやったらネオンサインの点灯のように見えるか
今回の方法がベストだとは思えないし、ベターですらないような気がするが、とりあえず私はこれで納得した。
- うっすら明るくなったあと短く3回点滅する
- その後、数度パチっと一瞬消える
- 点滅の間隔はランダム
- 時間は全体で2秒前後
- 影とぼかしで光ってる雰囲気を出す
テクニック
影とぼかし
これは簡単、SVG全体にフィルターを掛ければよい。
drop-shadow CSS関数は、Xのオフセット、Yのオフセット、ぼかし半径、色を指定して影を作る。
svg {
filter: drop-shadow(0px 3px 10px #71f7ed);
}
アニメーション
点滅はCSSアニメーションで実現する。ロゴ自体はSVGで作成されているが、CSSで操作している。
SVG内でいくつかに分割されたpathに対して、点滅させるためのランダム値を用いて動的に生成される別々の kayframe を設定する。
const title = document.querySelectorAll('svg path');
title.forEach((path) => {
const keyframe = [];
/* -----
ランダムに点滅させるkeyframeを動的に生成する
----- */
animate(path, keyframe);
});
点滅
点滅は単純に opacity の設定で実現できる。
0 から 1 にし、すぐに0に戻せば一瞬光る。アニメーションで0.05秒でoacityを増減させる。
path {
opacity: 0;
}
よって、アニメーションの keyframe は opacity を0か1に設定しているだけである。
keyframe.push({ opacity: 1, offset: timming });
keyframe.push({ opacity: 0, offset: timming + 0.01 });
keyframe.push({ opacity: 1, offset: timming + 0.02 });
ただ、単純にアニメーションするだけでなく、それっぽくするためにいくつか処理を追加している
冒頭、点滅する前に opacity が 0.2 になるようにうっすら光らせている。
アニメーション全体は2500ミリ秒に設定しているので、平均125ミリ秒かけてうっすら光る。
keyframe.push({ opacity: 0 });
let timming = Math.random() * 0.5;
keyframe.push({ opacity: 0.2, offset: timming });
最初に3回点滅するときには、0.8、0.9、1と段々明るくなるように設定している。
keyframe.push({ opacity: 0.8, offset: timming});
keyframe.push({ opacity: 0, offset: timming + 0.01 });
keyframe.push({ opacity: 0.9, offset: timming + 0.02 });
keyframe.push({ opacity: 0, offset: timming + 0.03 });
keyframe.push({ opacity: 1, offset: timming + 0.04 });
3回点滅したあとランダムに、ときどき点滅するようにする。
offset が 1を超えない範囲でランダムに点滅させるのだが、適当な増分(increase
)を設定しているので、段々点滅間隔が長くなるようになっている。
概ね1回か2回点滅するはずである。
let increase = 0;
timming = timming + 0.05 + Math.random() * 0.8;
while (timming < 0.97) {
keyframe.push({ opacity: 1, offset: timming });
keyframe.push({ opacity: 0, offset: timming + 0.01 });
keyframe.push({ opacity: 1, offset: timming + 0.02 });
timming = timming + 0.05 + Math.random() * (1.1 + increase * 0.1);
increase = increase + 3;
}
完成ソースはCodepenで確認してほしい。