CSS3アニメーションをJSで制御
iOSでFlashがネイティブにサポートされない事から、JSあるいはCSS3でアニメーションを実装する機会が増えています。
クライアントから明確に「このアニメーションはJSorCSS3で(iOSでも閲覧出来るように)作って欲しい」と依頼を受けた経験のある方もいらっしゃるのではないでしょうか?
CSS3アニメーションは現状、対応ブラウザの課題から使用が限定されるため、
私自身はJSでアニメーションを実装する機会の方が圧倒的に多いのですが、
今後の考え方として、以下のような方法を影響の少ない範囲で導入しています。
- UIの制御をJSで
- アニメーションをCSS3で
CSS3でアニメーションを実装した際のメリット・デメリットを列挙します。
今後も積極的に導入していくかは未定ですが、一手段としてご覧いただければ幸いです。
CSS3アニメーションのメリット・デメリット
- メリット
-
-
JSアニメーションより比較的処理が軽い。
※ハードウェアスペック、GPUアクセラレーション有無に左右されます -
複雑なUIを構築した際にJSが管理しやすくなる。
※UIの制御をJSに、アニメーションをCSSに記述といった具合に分離可能 - 回転させたり、傾き(角度を変える)がネイティブにサポート。
-
JSアニメーションより比較的処理が軽い。
- デメリット
-
- 対応ブラウザが限られる。
- 現状ベンダープレフィックスが必要なため記述が助長になる。
JSアニメーションのメリット・デメリット
CSS3アニメーションのメリット・デメリットを裏返したイメージなので、今回は省略します。
上記を置き換えてお考えください。
JSとCSS3アニメーションの連携例
実現方法は簡単で、JSでイベント(トリガー)を設定して任意のタイミングでクラス(もしくはスタイル)を付与する。
そして、CSSでアニメーション(transitionなど)を定義することで連携させます。
当社オフィシャルサイトTOPページのスライドにマウスオーバーした際に
黒い透明のレイヤーが下がる部分は、アニメーションにCSS3(transition)を使っています。
そのため、IEではアニメーションしませんが、表示されるコンテンツは同じです。
こういった部分には今すぐにでも導入可能ではないでしょうか。
また、凝った演出が必要な場合は、(CSS3の)animationプロパティと連携させる事もできますし、
transitionでも、アニメーション終了時にJSでイベント(transitionEnd)が発火されますので、
2段階にアニメーションさせる事が可能です。
※transitionEndは現状JS必須ですが、今後はCSS単独で制御出来るようになるとのこと
サンプルコード
少しでもイメージして頂けるよう、簡単にサンプルコードを作成しました。
必要最小限の部分しか記載していませんし、このような単純なコードであれば
JSとCSSを分離させるメリットは薄いのですが、UIが複雑になってくる程効果を発揮するかと思います。
※あくまでイメージして頂くことが目的でコピペで使えるようなものではありません。
※変数/クラス名、ベンダープレフィックスは適宜置き換えてください。
※下記サンプルはクラス名を上書きしているため、実際にはjQueryのaddClass()のような実装を検討してください。
- JS(アニメーションはCSSに分離)
-
var animationElem = document.getElementById( 'animationElem' ), nextAnimationElem = document.getElementById( 'nextAnimationElem' ); // ターゲット要素クリックでアニメーション要素にクラス付与 document.getElementById( 'animationTrigger' ).addEventListener( 'click', function() { animationElem.className = 'doAnimation'; }, false ); // アニメーション(transition)終了時に他の要素にクラス付与 animationElem.addEventListener( 'webkitTransitionEnd', function() { nextAnimationElem.className = 'doNextAnimation'; }, false );
- CSS
-
#animationElem, #nextAnimationElem { /* 引数:対象プロパティ、速度、イージング、ディレイ */ -webkit-transition: left 2s ease-in-out 0s; } #animationElem { top: 0; } #animationElem.doAnimation { top: 500px; } #nextAnimationElem { left: 0; } #nextAnimationElem.doNextAnimation { left: 500px; }
- JSのみでアニメーションも実装
-
※簡易的なアニメーションです
var animationElem = document.getElementById( 'animationElem' ), nextAnimationElem = document.getElementById( 'nextAnimationElem' ); // ターゲット要素クリックでアニメーション開始(関数) document.getElementById( 'animationTrigger' ).addEventListener( 'click', function() { animationMove( animationElem, 'top', 0, 500, 10, function() { // アニメーション(関数)終了時にコールバックで再実行 animationMove( nextAnimationElem, 'left', 0, 500, 10 ); }); }, false ); // 段階的にプロパティを変化させる関数 // @param // elem: dom element // prop: string(style property name) // from: number // to: number // step: number // callback: function function animationMove( elem, prop, from, to, step, callback ) { var nowPos = from, decay = 0.9; (function() { nowPos += ( step * decay ); if ( nowPos >= to ) { nowPos = to; elem.style[ prop ] = nowPos + 'px'; if ( callback ) { callback(); } return; } else { elem.style[ prop ] = nowPos + 'px'; } setTimeout( arguments.callee, 1000 / 60 ); })(); }