angular.jsをやってみる (19) - 動的に追加したエレメントに対して$animate.enter -

2014-04-08T00:00:00+00:00 angular.js JavaScript

公式リファレンス: http://docs.angularjs.org/api/ngAnimate/service/$animate

例えばクリックイベントによりノードを追加したりするにあたって、ngAnimateなアニメーションを利用したい場合とかに$animate.enter等を利用する事で出来るっぽいのでやってみた

とりあえず、わかりやすい例としては画面上に通知的なのを出す。それをクリックイベントにてエレメントを追加し$animateを使ってfadeIn/fadeOutなアニメーション的な事をする

index.html

<!DOCTYPE html>
<html ng-app="app">
  <head>
    <script src="jquery.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.5/angular.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.5/angular-animate.min.js"></script>
    <script src="app.js"></script>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <div id="notifications"></div>
    <div ng-controller="Controller1">
      <a href="#" ng-click="click()">click</a>
    </div>
  </body>
</html>

CSSに関しては

.ng-animate {
  -webkit-transition: 3s linear all;
  transition: 3s linear all;
}

#notifications {
  position: absolute;
  top: 10px;
  right: 10px;
}

.notify {
  margin: 10px;
  width: 300px;
  height: 100px;
  line-height: 100px;
  border: 1px solid red;
  border-radius: 3px;
  vertical-align: middle;
  text-align: center;
}

的な所でng-animateクラスな辺りでtransition設定をしておく。これ以前にも書いたので詳細は(ry

app.js

angular.module("app", ["ngAnimate"])
  .animation(".notify", function($timeout, $animate) {
    return {
      enter: function(element, done) {
        element.css("opacity", 0);

        jQuery(element).animate({ opacity: 1 }, function() {
          $timeout(function() {
            $animate.leave(element);
            done();
          }, 5000);
        });
      },
      leave: function(element, done) {
        element.remove();
        done();
      }
    };
  })
  .controller("Controller1", function($scope, $animate) {
    $scope.click = function() {
      var elm = angular.element("<div>");
      elm.addClass("notify");
      elm.text(new Date().getTime());

      // 第2引数で指定しているエレメントに対して第1引数で指定したエレメントが追加されてng-enterなどのCSSクラスが処理される
      $animate.enter(elm, angular.element("#notifications"));
    };
  });

んな感じで動的に追加したエレメントに対して$animate.enterを使う事でCSSクラスに対応したアニメーションを利用できる模様

追記: $animate.enterの第3引数について

要は既にあるのならそれよりも下にエレメント追加するようにしたい場合とかだと

angular.module("app", ["ngAnimate"])
  .animation(".notify", function($timeout, $animate) {
    return {
      enter: function(element, done) {
        element.css("opacity", 0);

        jQuery(element).animate({ opacity: 1 }, function() {
          $timeout(function() {
            $animate.leave(element);
            done();
          }, 3000);
        });
      },
      leave: function(element, done) {
        jQuery(element).animate({ opacity: 0 }, done);
      }
    };
  })
  .controller("Controller1", function($scope, $animate) {
    $scope.click = function() {
      var time = new Date().getTime();

      var elm = angular.element("<div>");
      elm.attr("id", time);
      elm.addClass("notify");
      elm.text(time);

      var top = angular.element(".notify").last();
      if (!top.hasClass("notify")) {
        top = null;
      }

      $animate.enter(elm, angular.element("#notifications"), top);
    };
  });

っていう風に既にあるかチェックしてないのならnullで初期化する的な事すりゃいいっぽい

angular.jsをやってみる (20) - $q - angular.jsをやってみる (18) - $emit -