LoginSignup
10
9

More than 5 years have passed since last update.

AngularJSとCSS Transitionsの話

Last updated at Posted at 2015-12-13

はじめに

AngularJSを少しでも触ったことのある方なら、データバインディングによって簡単に動的なWebページが作れるのはご存じでしょう。
本稿では、動的に変化させるWebページにCSS Transitionsを使ったアニメーションを加えることで、Webページの見た目にも動きを加えるテクニックについて紹介したいと思います。

Transitionとは遷移といった意味です。
CSS Animationsという規格も存在するんですが、CSS Animationsは繰り返しのあるアニメーションの表現に強いです。
CSS TransitionsはCSSプロパティの値の変更、つまり遷移を、一瞬の切り替わりではなく連続的な変化で表現します。

AngularJSのバージョンは1.4.8で確認しています。

ngAnimate

AngularJSでアニメーションといえばまずngAnimateが思い浮かぶと思います。
はじめにngAnimateとCSS Transitionsの関係から紹介しましょう。

さて、ngAnimateのドキュメントを見ると「CSS-based Animations」の説明から入っています。
簡単なサンプルを示しましょう。
まずはアニメーションなしで、ngShowを使ってチェックボックスの値に応じて要素の表示非表示を切り替えるコードです。

<div ng-app="app">
  <div ng-controller="MainController">
    <button ng-click="toggleShow()">toggle</button>
    <div class="message" ng-show="show">
      hello
    </div>
  </div>
</div>
var MainController = function ($scope) {
  $scope.show = false;

  $scope.toggleShow = function () {
    $scope.show = !$scope.show;
  };
};

angular.module('app', [])
  .controller('MainController', MainController);

https://jsfiddle.net/xj7fz3fz/ で動作確認できるようにしています。
今はチェックボックスの値を変えると、即座に表示のオンオフが切り替わっています。
これを、徐々に透明になるように、あるいは透明な状態から徐々に現れてくるように変更します。

はじめに、ngAnimateの依存モジュールへの追加を行います。
angular-animateをscriptタグなどで読み込むのを忘れないでください。

angular.module('app', ['ngAnimate'])
  .controller('MainController', MainController);

次にスタイルを追加します。

.message {
  opacity: 1;
}

.message.ng-hide-add, .message.ng-hide-remove {
  transition: all linear 0.5s;
}

.message.ng-hide {
  opacity: 0;
}

これだけでアニメーションの追加が行えます。
動作は https://jsfiddle.net/t8j818xo/ で確認できます。

少しだけ解説をしましょう。
スタイルの方はAngularJS独自の要素は何もない標準のCSSです。
transitionプロパティがCSS Transitionsのキモとなります。
transitionプロパティは、transition-propertytransition-durationtransition-timing-functiontransition-delayの4つのプロパティの省略表記です。
上の例ではall linear 0.5sと3つの値を与えていて、順にtransition-propertytransition-timing-functiontransition-delayに対応しています。

transition-peropertyでは、アニメーション対象にするCSSプロパティを指定します。
上の例ではallを与えているので全てのCSSプロパティを対象とします。
上の例ではopacityのみを変化させているので、allの代わりにopacityと書くこともできます。

transition-durationはアニメーションの時間を指定します。
上の例では0.5sを与えていて、opacityの値が0から1に、あるいは1から0に0.5秒かけて連続的に変化します。

transition-timing-functionでは、CSSプロパティの変化の仕方を指定します。
上の例ではlinearを与えているので、アニメーション開始時点から終了時点までプロパティを線形に変形します。
上の例ではtransition-delay0.5sなので、アニメーション開始から0.25秒後のopacityの値は大体0.5になります。
他にも組み込みのtiming functionが存在しているので詳しくは http://www.w3.org/TR/css3-transitions/#transition-timing-function-property などを参照してください。

ngAnimateの話に戻ります。
ngAnimateを読み込んでいると、ngShowやngIf、ngRepeat、ngViewといったいくつかのディレクティブで要素が変化するときにclassの追加や削除が行われるようになります。
ngShowでは、要素が非表示のときにng-hideclassに追加されます。
ngAnimateを読み込んでいると、ngShowの値がtrueからfalseに切り替わるときにng-hide-add、falseからtrueに切り替わるときにng-hide-removeが一瞬だけclassに追加されます。
そのタイミングでtransitionプロパティを適用することでアニメーションを実現しています。

CSS Transitions

ngAnimateではCSS Transitionsを使うことで少ない記述でWebページにアニメーションを追加できることが確認できました。
CSS Transitionsは非常に強力で、ngAnimateを使わなくても便利になる場面があります。

例えば、ある要素の座標をCSSのtransformプロパティで設定してるとして、Scope中の変数の値でtransformプロパティの値が変化するとしましょう。
HTMLとJavaScript、CSSは以下のようなコードになります。

<div ng-app="app">
  <div ng-controller="MainController">
    <div>
      <label>x</label><input type="range" min="0" max="500" step="50" ng-model="x">
    </div>
    <div>
      <label>y</label><input type="range" min="0" max="500" step="50" ng-model="y">
    </div>
    <div class="message" ng-style="messageStyle()">
      hello
    </div>
  </div>
</div>
var MainController = function ($scope) {
  $scope.x = 50;
  $scope.y = 50;

  $scope.messageStyle = function () {
    return {
      transform: 'translate(' + $scope.x + 'px,' + $scope.y + 'px)'
    };
  };
};

angular.module('app', [])
  .controller('MainController', MainController);
.message {
  width: 50px;
  height: 50px;
  background-color: red;
}

xとyをバインディングしているだけの単純なコードです。
input要素でxとyを変更すると即座にmessageの位置が変化すると思います。

ここで、CSSにCSS Transitionsの記述を以下のように追加します。

.message {
  width: 50px;
  height: 50px;
  background-color: red;
  transition-property: transform;
  transition-duration: 1s;
}

動作確認は https://jsfiddle.net/hyuavLkn/1/ でできます。
messageの位置がアニメーションで連続的に変化するようになりました。
このようにngAnimateを使わない場合でも、AngularJSのデータバインディングとCSS Transitionsを組み合わせることで面白い動きのWebページが簡単につくれます。

おわりに

私は普段から可視化アプリケーションの開発を行っているんですが、ユーザーの操作による可視化結果の変化をアニメーションで表現することは当たり前になっています。
可視化のライブラリといえばD3.jsが有名だと思いますが、私の場合はアプリケーションの大規模化につれて開発が苦しくなってきたので、AngularJSなどを使って可視化部分の開発も行うようになってきました。
D3.jsが持っているアニメーションの機能は非常に強力なのですが、AngularJSでは可視化のためのアニメーションという点ではサポートがほとんどありません。
しかし、CSS Transitionsを使うことで、AngularJSでもD3.jsにも負けない強力なアニメーション表現ができるようになるので覚えてみて損はないかと思います。

10
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
9