CSSアニメーションのための時間ベース方式の活用
- CSSで数学関数がサポートされるようになり、時間ベース方式のCSSアニメーションを改めて試せるようになった
- mod()、round()、三角関数などがサポートされている
- デモを確認するには実験的機能フラグを有効化する必要がある場合がある
基本アイデア
- CSS Houdini APIを使って、時間(ミリ秒)を追跡するカスタム変数を定義できる
@property ルールを使って --t 変数を定義し、初期値を0に設定
@keyframes ルールで --t 変数を24時間(86,400,000ms)かけて線形的に増加させる
--t に基づく他の値は連動して変化し、アニメーション効果を作り出す
counter() 関数を使って --t 変数の値を表示できる
フレームレート制御
- 毎秒60フレーム(FPS)の更新周期を維持すれば、スムーズなアニメーションには十分
- 必要に応じて
step() 関数を使ってフレームレートを手動で制御できる
animation-timing-function プロパティで step() 関数を使い、希望するFPS値を計算
時間の変換
--t 値は一方向に継続的に増加するため、一部のCSSプロパティには適していない場合がある
min() 関数で特定の値に達したときにアニメーションを停止できる
mod() 関数でアニメーションを再開できる
sin() 関数で前後に動く効果を作れる
カスタムイージング関数
- 数式関数と
--t 変数を使って、カスタムイージング関数を作成できる
cubic-bezier() では実現しにくい効果を作れる
- 例: ease-out-cubic、ease-out-elastic など
CSS Doodle の実験
- 複雑な式では
var() と calc() がコードの可読性を下げることがある
- css-doodleでは
@t 関数を使って --t 変数を表現できる
- css-doodleの最新版では、引数内で簡単な数学式を直接許可している
@T と @TS 関数も追加で提供される
@T は1日の始まりからの時間を表す
@TS は @t(/1000) の省略形で、秒単位で時間を追跡する
- 時計の例やジャンプモーションの例などを css-doodle で実装できる
結論
- 時間を変数として扱うこのアプローチは興味深い
- Keyframesを使うほうが直感的なこともあるが、数学計算と入力変数の多いデモシーンでは、時間を変数として扱うことでより多様な結果が得られる
GN⁺の見解
- CSSの時間ベースアニメーション技術は、単にCSSで実装できるアニメーションの幅を広げるだけでなく、シェーダーやWebGLなど他技術との連携活用の可能性も高めると考えられる
- CSS HoudiniやCSS Doodleなどのツールと併用すれば、さらに柔軟で多様な表現が可能になりそうだ
- ただしブラウザ互換性の問題やパフォーマンス課題など、実案件への適用時に検討すべき事項がある。既存のKeyframe方式と長所短所を比較して、選択的に使うのがよい
- GSAPなど専門のアニメーションライブラリと比較した際の長所短所も分析する必要がある。相互補完的に利用できる方法を模索するのもよいだろう
- 時間ベースCSSアニメーションの例や活用事例がさらに共有され、フロントエンド開発者がもっと簡単に試せるようになることを期待したい
1件のコメント
Hacker Newsコメント
CSSでは、負の
animation-delay値を使って JavaScript でアニメーション進行を制御できる。たとえばanimation-delay: -1500msと設定すると、即座に開始しつつ再生位置を1.5秒地点へスキップできる。JavaScript でこの値を操作することで CSS アニメーションをスクラビングでき、すべてのアニメーションをゲームエンジン風の「計算-更新-レンダリング」ティックループと互換させることができる。簡単なイージング関数や1〜2チャネル程度の基本キーフレームを超えると、このアプローチはすぐ限界にぶつかる。Theatre.js ライブラリは、キーフレームとベジェ曲線を編集するためのタイムラインを備えたスタジオ UI と、これらのキーフレームを取り込んでタイムライン上で値を補間するランタイムで構成されており、調整済みアニメーションが必要な場合に便利だ。
本記事では、ブラウザサポート率が88%のカスタムCSS
@propertyを活用している。ブラウザごとの初期値の設定方法が異なる点に注意が必要だ。Chrome は未定義または無効な値の場合は初期値を使うが、Firefox は未定義の場合のみ初期値を使う。ほとんどのプロジェクトには問題にならないだろうが、ブラウザ間での実装差分を解消するには JavaScript で Firefox のデフォルト値を設定しなければならない場合がある。CSSには
mod()、round()、三角関数などの十分な数学関数がサポートされている。CSSは JavaScript のようにタイマーを開始することはできないが、最近では CSS Houdini API でカスタム変数を定義し、ミリ秒単位で時間を追跡できる。ただ、JavaScript があるのに、なぜこれらすべてが必要なのだろう? 描画レイヤは描画プリミティブにしか関心を持つべきではないのか? どうして高次元レイヤをさらに追加していこうとするのだろう?作られた時計はかなり洗練されて見える。よく書かれた記事だ。Chrome はまだ
mod()の CSS サポートをリリースしていないため、プレビューリリースを使わないとページのほとんどのデモがアニメーションしない。ティックを制御する必要なしに、すべてのブラウザでスムーズな CSS アニメーションを実現したいなら、FLIP手法が有効だ。
吸う-止める-吐く-止めるの各段階をすべてカスタムして自分の体に合わせ、望む効果を出したいと思っていたが、このページにあるような方法(JS や過度な複雑化なしでは)ならではなかった。ここには本当に創造的なデモがある!
興味深いことに、
mod()を使用する前のデモは動作するが、mod()とsin()は最新の Android Chrome では何も動作しない。ページ下部のアニメーションが非常に印象的だ。 要素ではなく のように見える。
非常に印象的だが、どう見ても数十年前の Flash でできたことに近いところに到達したように感じる。Flash の復活を望んでいるわけではないが、CSS アニメーションを作るためにもっとユーザーフレンドリーなツールがあればいい。