アニメーション

概要

AngularJS1.2では、$animateサービスを介したカスタムディレクティブはもちろんのこと、 ngRepeatngSwitchngViewのような一般的なディレクティブにアニメーションをフックする機能が提供されます。 これらのアニメーションのフックは、様々なディレクティブのライフサイクル中にアニメーションをトリガーし、 トリガーされた際にCSSトランジション、CSSキーフレームアニメーション、またはJavaScriptのコールバックアニメーションの実行を試みるように設定されます。 (アニメーションが与えられたディレクティブに配置されている場所に応じて) アニメーションは、AngularJSまたはファクトリーとして定義された際のJavaScriptコードの命名規則に従うことによって、 素のCSSを使用して設置することが可能です。

アプリケーションの依存関係として、ngAnimateモジュールを含めないと、 アニメーションを利用することは出来ません。

下記で、ngShowngHideのアニメーションを有効にする例をお見せします。

<!doctype html>
<html ng-app="ngAnimate">
  <head>
    <link rel="stylesheet" type="text/css" href="style.css">
    <script src="http://code.angularjs.org/1.2.0/angular.min.js"></script>
    <script src="http://code.angularjs.org/1.2.0/angular-animate.min.js"></script>
  </head>
  <body>
    <div ng-init="checked=true">
      <label>
        <input type="checkbox" ng-model="checked" style="float:left; margin-right:10px;"> Is Visible...
      </label>
      <div class="check-element animate-show-hide" ng-show="checked" style="clear:both;">
        Visible...
      </div>
    </div>
  </body>
</html>
.animate-show-hide {
  padding:10px;
  border:1px solid black;
  background:white;
}

.animate-show-hide.ng-hide-add, .animate-show-hide.ng-hide-remove {
  -webkit-transition:all linear 0.5s;
  -moz-transition:all linear 0.5s;
  -o-transition:all linear 0.5s;
  transition:all linear 0.5s;
  display:block!important;
}

.animate-show-hide.ng-hide-add.ng-hide-add-active,
.animate-show-hide.ng-hide-remove {
  opacity:0;
}

.animate-show-hide.ng-hide-add,
.animate-show-hide.ng-hide-remove.ng-hide-remove-active {
  opacity:1;
}
<!doctype html>
<html ng-app="ngAnimate">
  <head>
<style type="text/css">.animate-show-hide {
  padding:10px;
  border:1px solid black;
  background:white;
}

.animate-show-hide.ng-hide-add, .animate-show-hide.ng-hide-remove {
  -webkit-transition:all linear 0.5s;
  -moz-transition:all linear 0.5s;
  -o-transition:all linear 0.5s;
  transition:all linear 0.5s;
  display:block!important;
}

.animate-show-hide.ng-hide-add.ng-hide-add-active,
.animate-show-hide.ng-hide-remove {
  opacity:0;
}

.animate-show-hide.ng-hide-add,
.animate-show-hide.ng-hide-remove.ng-hide-remove-active {
  opacity:1;
}
</style>
    <script src="http://code.angularjs.org/1.2.0/angular.min.js"></script>
    <script src="http://code.angularjs.org/1.2.0/angular-animate.min.js"></script>
  </head>
  <body>
    <div ng-init="checked=true">
      <label>
        <input type="checkbox" ng-model="checked" style="float:left; margin-right:10px;"> Is Visible...
      </label>
      <div class="check-element animate-show-hide" ng-show="checked" style="clear:both;">
        Visible...
      </div>
    </div>
  </body>
</html>

インストール

ngAnimateのインストールの箇所を参照してください。

また、CSSベースのアニメーションが定義された分割された、CSSファイルのセットアップが必要になるかもしれません。

動作の仕組み

AngularJSのアニメーションは、完全にCSSクラスに基づいたものになっています。 サイト内でHTML要素にCSSクラスを割り当てれば、アニメーションを適用することが可能になります。 例として、下記のような繰り返し処理されるHTMLテンプレートがあるとします。

<div ng-repeat="item in items" class="repeated-item">
  {{ item.id }}
</div>

.repeated-itemクラスが提供された要素は繰り返し処理され、 このクラスはアニメーションを実行するCSS、且つ/または、JavaScriptコードを、 AngularJSに伝えるために使用されます。

ngRepeatがこれを行うには、新しい各項目をリストに追加する際に、 ngRepeatはその追加された要素に、ng-enterのクラス名を追加します。 それが削除される際は、ng-leaveクラス名が適用され、それが移動する際はng-moveのクラス名が適用されます。

下記のCSSコードから、トランジションとキーフレームアニメーションコードが、 ngRepeatがトリガするそれぞれの各イベント用に用意されていることを確認してください。

/*
  .repeated-itemクラスを持つ要素の
  enterとmoveイベントがトリガされた際にCSSトランジションを使用します。
*/
.repeated-item.ng-enter, .repeated-item.ng-move {
  -webkit-transition:0.5s linear all;
  -moz-transition:0.5s linear all;
  -o-transition:0.5s linear all;
  transition:0.5s linear all;
  opacity:0;
}

/*
 ng-enter-activeとng-move-activeは、
 アニメーションのトランジションによって、
 到達するプロパティが設定されたものです。(翻訳に自信なし)
*/
.repeated-item.ng-enter.ng-enter-active,
.repeated-item.ng-move.ng-move-active {
  opacity:1;
}

/*
  .repeated-itemクラスを持つ要素の
 leaveイベントがトリガされた際に、
 CSSキーフレームのアニメーションを使用します。
*/
.repeated-item.ng-leave {
  -webkit-animation:0.5s my_animation;
  -moz-animation:0.5s my_animation;
  -o-animation:0.5s my_animation;
  animation:0.5s my_animation;
}

@keyframes my_animation {
  from { opacity:1; }
  to { opacity:0; }
}

/*
 残念ながら、各ブラウザベンダーは独自の
 キーフレームアニメーションの定義を必要とします...
*/
@-webkit-keyframes my_animation {
  from { opacity:1; }
  to { opacity:0; }
}

@-moz-keyframes my_animation {
  from { opacity:1; }
  to { opacity:0; }
}

@-o-keyframes my_animation {
  from { opacity:1; }
  to { opacity:0; }
}

アニメーションを同じアプローチでJavaScriptコードを使用して行うことが可能です。 (アニメーションの実行にjQeuryが使用されています。)

myModule.animation('.repeated-item', function() {
  return {
    enter : function(element, done) {
      element.css('opacity',0);
      jQuery(element).animate({
        opacity: 1
      }, done);

      // 発行されたアニメーションのクリーンアップを取り扱う
      // 任意のonDoneまたはonCancelコールバック関数です。
      return function(isCancelled) {
        if(isCancelled) {
          jQuery(element).stop();
        }
      }
    },
    leave : function(element, done) {
      element.css('opacity', 1);
      jQuery(element).animate({
        opacity: 0
      }, done);

      // 発行されたアニメーションのクリーンアップを取り扱う
      // 任意のonDoneまたはonCancelコールバック関数です。
      return function(isCancelled) {
        if(isCancelled) {
          jQuery(element).stop();
        }
      }
    },
    move : function(element, done) {
      element.css('opacity', 0);
      jQuery(element).animate({
        opacity: 1
      }, done);

      // 発行されたアニメーションのクリーンアップを取り扱う
      // 任意のonDoneまたはonCancelコールバック関数です。
      return function(isCancelled) {
        if(isCancelled) {
          jQuery(element).stop();
        }
      }
    },

    // また、下記のアニメーションイベントも制御可能です。
    addClass : function(element, className, done) {},
    removeClass : function(element, className, done) {}
  }
});

これらの生成されたCSSクラス名が要素に提供された際に、 AngularJSは自動的に、CSS且つ/またはJavaScriptアニメーションを実行するかどうかを算出します。 もし、CSSとJavaScriptアニメーションコードの両方が提供されており、要素のCSSクラス名に一致した場合、 AngularJSは両方のアニメーションを同時に実行します。

クラスとngClassアニメーションのフック

また、AngularJSは追加・削除のフックのトリガによる、要素上のCSSクラスの変更に注意を払っています。 これは、要素からCSSクラスが追加または削除された場合、 CSSクラスの追加または削除が確定するまでの間に、アニメーションを実行できることを意味します。 (AngularJSは、式または要素上でng-classディレクティブが使用された場合、クラスの変更のみを捉える事ができる事に注意してください。)

下記の例で、クラスが変更される際のアニメーション実行の方法を確認してください。

<!doctype html>
<html ng-app="ngAnimate">
  <head>
    <link rel="stylesheet" type="text/css" href="style.css">
    <script src="http://code.angularjs.org/1.2.0/angular.min.js"></script>
    <script src="http://code.angularjs.org/1.2.0/angular-animate.min.js"></script>
  </head>
  <body>
    <p>
      <input type="button" value="set" ng-click="myCssVar='css-class'">
      <input type="button" value="clear" ng-click="myCssVar=''">
      <br>
      <span ng-class="myCssVar">CSSアニメーションテキスト</span>
    </p>
  </body>
</html>
.css-class-add, .css-class-remove {
  -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
  -moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
  -o-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
  transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
}

.css-class,
.css-class-add.css-class-add-active {
  color: red;
  font-size:3em;
}

.css-class-remove.css-class-remove-active {
  font-size:1.0em;
  color:black;
}
<!doctype html>
<html ng-app="ngAnimate">
  <head>
<style type="text/css">.css-class-add, .css-class-remove {
  -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
  -moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
  -o-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
  transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
}

.css-class,
.css-class-add.css-class-add-active {
  color: red;
  font-size:3em;
}

.css-class-remove.css-class-remove-active {
  font-size:1.0em;
  color:black;
}
</style>
    <script src="http://code.angularjs.org/1.2.0/angular.min.js"></script>
    <script src="http://code.angularjs.org/1.2.0/angular-animate.min.js"></script>
  </head>
  <body>
    <p>
      <input type="button" value="set" ng-click="myCssVar='css-class'">
      <input type="button" value="clear" ng-click="myCssVar=''">
      <br>
      <span ng-class="myCssVar">CSSアニメーションテキスト</span>
    </p>
  </body>
</html>

CSSは前述したものと少し異なりますが、基本的な考え方は同じです。

どのディレクティブがアニメーションをサポートするのか?

AngularJSの一部のディレクティブは、アニメーションのフックをサポートし、 ライフサイクルの期間に主要なイベントが発生するとそれをトリガします。 下記のテーブルは、アニメーションイベントのトリガについての詳細になります。

ディレクティブ サポートされるアニメーション
ngRepeat enter、leave、move
ngView enter、leave
ngInclude enter、leave
ngSwitch enter、leave
ngIf enter、leave
ngClass または {{class}} add、remove
ngShowngHide add、remove (ng-hideクラス値)

各アニメーションイベントが実行される、それぞれのステップの詳細については、 APIドキュメントを参照してください。

自分のディレクティブでどのようにしてアニメーションを使用するか?

Animations within custom directives can also be established by injecting $animate directly into your directive and making calls to it when needed.

myModule.directive('my-directive', ['$animate', function($animate) {
  return function(element, scope, attrs) {
    element.bind('click', function() {
      if(element.hasClass('clicked')) {
        $animate.removeClass(element, 'clicked');
      } else {
        $animate.addClass(element, 'clicked');
      }
    });
  };
}]);

アニメーションのより詳しい情報について

$animateで利用可能な各メソッドの詳細については、APIドキュメントを参照してください。

完全なデモを確認したければ、チュートリアルのアニメーションのステップ12を参照してください。

 Back to top

© 2017 Google
Licensed under the Creative Commons Attribution License 3.0.

このページは、ページトップのリンク先のAngularJS公式ドキュメント内のページを翻訳した内容を基に構成されています。 下記の項目を確認し、必要に応じて公式のドキュメントをご確認ください。 もし、誤訳などの間違いを見つけましたら、 @tomofまで教えていただければ幸いです。

  • AngularJSの更新頻度が高いため、元のコンテンツと比べてドキュメントの情報が古くなっている可能性があります。
  • "訳注:"などの断わりを入れた上で、日本人向けの情報やより分かり易くするための追記を行っている事があります。