AngularJSに触れてみる その2
前回のブログに引き続き、AngularJSの機能を触っていきたいと思います。 こちらは今回機能紹介のために用意したPC版のデモです。モバイルでは見にくいので、でうまく動かない場合はPCに最新版のブラウザ (最新版のGoogle Chromeなど) をダウンロードしてからご覧ください。
今回はデモで用いられているAngularJSの機能、主にngViewについて紹介していきたいと思います。ngViewを用いることでURLの切り替えによって読み込むコンテンツを切り替えることができます。
上記デモはボタンをクリックするごとにURLを切り替えて、そのURLに対応したHTMLテンプレートとコントローラーを読み込ませて表示を行なっています。また、切り替える時のアニメーションにはngAnimateというAngularJSのアニメーション機能を使っています。
まずはindex.htmlのソースコードを掲載します [※ソースは紹介に必要のない部分は削除しています] 。なお、画像を除いたソースコードは最下部に置いてあります。
index.html
<!DOCTYPE html>
<html ng-app="MonaApp">
<head>
<meta name="viewport" content="width=device-width; initial-scale=1.0;">
<base href="/blog1017/" />
<link rel="stylesheet" href="css/style.css"/>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="http://code.angularjs.org/angular-1.2.0-8336b3a/angular.min.js"></script>
<script src="http://code.angularjs.org/1.2.0-rc.2/angular-animate.min.js"></script>
<script src="http://code.angularjs.org/1.2.0-rc.2/angular-route.min.js"></script>
<script src="js/app.js"></script>
</head>
<body>
<div id="header">
<p id="title">AngularJS Books</p>
</div>
<div id="container" ng-controller="MonaCtrl">
<div ng-view class="view-demo"></div>
<div id="sidebar">
<ul>
<li id="book1"><a href="book1">Book1</a></li>
<li id="book2"><a href="book2">Book2</a></li>
<li id="book3"><a href="book3">Book3</a></li>
<li id="book4"><a href="book4">Book4</a></li>
<li id="book5"><a href="book5">Book5</a></li>
</ul>
</div>
</div>
</body>
</html>
app.js
var app = angular.module('MonaApp', ['ngRoute', 'ngAnimate']);
app.config(function($routeProvider, $locationProvider) {
$routeProvider.when('/book1', {
templateUrl: 'templates/book.html',
controller:book1Ctrl
});
$routeProvider.when('/book2', {
templateUrl: 'templates/book.html',
controller:book2Ctrl
});
$routeProvider.when('/book3', {
templateUrl: 'templates/book.html',
controller: book3Ctrl
});
});
});
app.config(function($locationProvider) {
$locationProvider.html5Mode(true);
});
function MonaCtrl($location, $scope) {
var pager = 1;
setInterval(function() {
$scope.$apply(function(){
if(pager === 6){
pager = 1;
}
$location.path('/book'+pager);
pager++;
});
}, 5000);
}
}
function book1Ctrl($scope) {
angular.element("#sidebar ul li").css("background", "#24100F");
angular.element("#book1").css("background", "#D0B29A");
$scope.MonaItems = [];
$scope.MonaItems.push({
"title" : "Mastering Web Application Development with AngularJS",
"author" : "Author: Pawel Kozlowski, Peter Bacon Darwin",
"image" : "images/1.png" ,
"link" : "http://www.amazon.co.jp/Mastering-Application-Development-AngularJS-ebook/dp/B00EQ67J30/ref=sr_1_4?ie=UTF8 &qid=1381665653 &sr=8-4 &keywords=AngularJS"
});
}
function book2Ctrl($route, $routeParams, $location, $scope) {
angular.element("#sidebar ul li").css("background", "#24100F");
angular.element("#book2").css("background", "#D0B29A");
$scope.MonaItems = [];
$scope.MonaItems.push({
"title" : "AngularJS",
"author" : "Author: Brad Green, Shyam Seshadri",
"image" : "images/2.png" ,
"link" : "http://www.amazon.co.jp/AngularJS-Brad-Green/dp/1449344852/ref=tmm_pap_title_0?ie=UTF8 &qid=1381668266 &sr=1-1"
});
}
function book3Ctrl($route, $routeParams, $location, $scope) {
angular.element("#sidebar ul li").css("background", "#24100F");
angular.element("#book3").css("background", "#D0B29A");
$scope.MonaItems = [];
$scope.MonaItems.push({
"title" : "Angularjs in Action",
"author" : "Author: Brian Ford, Lukas Ruebbelke ",
"image" : "images/3.png" ,
"link" : "http://www.amazon.co.jp/Angularjs-Action-Brian-Ford/dp/1617291331/ref=sr_1_6?ie=UTF8 &qid=1381731976 &sr=8-6 &keywords=AngularJS"
});
}
フォルダ構成は下記になります。
ではngViewの紹介に移っていきます。
ngView
ngViewを使うことでindex.htmlに読み込むHTMLテンプレートおよびコントローラー等をURLによって切り替えることができます。URLが切り替わるたびに そのURLに紐づけられたHTMLテンプレートとコントローラーに切り替わります。
上記デモでテンプレートが切り替わっている場所はindex.htmlに定義してある下記の場所です。divタグに属性としてng-viewが記述されていることが確認できると思います。
<div ng-view class="view-demo"></div>
具体的にapp.jsのコードを見ていきましょう。
var app = angular.module('MonaApp', ['ngRoute', 'ngAnimate']);
AngularJSではモジュールという機能があります。モジュールという機能によってアプリが起動 (ブート) する際の設定や挙動などを定義することができます。詳細は本家ドキュメントをご覧ください。
ここでは MonaAppという自分で作成したモジュールに、ngRoute (ngViewのルーティングのために必要) およびngAnimate (ngAnimateというAngularJSのアニメーション機能を用いるためにver1.2から必要 ) というモジュールを読み込んでいます。
このモジュールを読み込むためには、以下のJSファイルを読み込む必要があります。これらのファイルはindex.htmlでそれぞれロードしています。
<script src="http://code.angularjs.org/angular-1.2.0-8336b3a/angular.min.js"></script>
<script src="http://code.angularjs.org/1.2.0-rc.2/angular-animate.min.js"></script>
<script src="http://code.angularjs.org/1.2.0-rc.2/angular-route.min.js"></script>
また、ngRouteを使う場合にはindex.htmlのタグ中のタグで設定しておきます。私の場合はblog1017という名前のフォルダー直下にベースURLを設定してあるので以下のように
のタグに記述しています。
<base href="/blog1017/" />
下記ではngRouteロードされた
の設定を行っています。
はangular-route.jsで読み込まれるサービスであり、ルートプロバイディングの設定を行います。
app.config(function($routeProvider) {
$routeProvider.when('/book1', {
templateUrl: 'templates/book.html',
controller:book1Ctrl
});
$routeProvider.when('/book2', {
templateUrl: 'templates/book.html',
controller:book2Ctrl
});
.....
});
でテンプレートとコントローラーの設定を行います。今回は全て同じ
というテンプレートを使い回しています。
$routeProvider.when('/book1', {
templateUrl: 'templates/book.html',
controller:book1Ctrl
});
上記の記述は
1:ベースURL/book1にURLが切り替わった時に
<div ng-view class="view-demo"></div>
2:上記に対してtemplates/book.htmlというHTMLテンプレートを読み込ませて
3:book1Ctrlというコントローラーを割り当てる
という設定を行っています。
PCでこのブログをご覧の方は実際に
で試してみましょう。うまく動かない場合には最新のGoogle Chromeなどをダウンロードしてお試しください。
上記のURLは
ですが、
ボタンを押した際に、aタグでURLを変更しています。その際に
1:templates/book.htmlというテンプレートが読み込まれ
2:book1Ctrlというコントロー ラーが割り当てられます
そうすれば、
にURLが切り替わった時にng-view属性を指定した箇所に読み込まれるテンプレートとコントローラーが切り替わります。
割り当てられた
コントローラーを見てみましょう。
function book1Ctrl($scope) {
angular.element("#sidebar ul li").css("background", "#24100F");
angular.element("#book1").css("background", "#D0B29A");
$scope.MonaItems = [];
$scope.MonaItems.push({
"title" : "Mastering Web Application Development with AngularJS",
"author" : "Author: Pawel Kozlowski, Peter Bacon Darwin",
"image" : "images/1.png" ,
"link" : "http://www.amazon.co.jp/Mastering-Application-Development-AngularJS-ebook/dp/B00EQ67J30/ref=sr_1_4?ie=UTF8 &qid=1381665653 &sr=8-4 &keywords=AngularJS"
});
}
MonaItemsという配列の中に本のタイトルや著者名、画像、リンクなどのオブジェクトを入れています。これが下記のテンプレートである
中に記述された
の中でitemとして展開されます。それを
の中で、{{item.title}}や{{item.author}}、{{item.link}}という形でAngularJSの
で記述しています。Expressionsは
で紹介しています。
template/book.html
<div class="contents" ng-repeat = "item in MonaItems" >
<h1>{{item.title}}</h1>
<h2>{{item.author}}</h2>
<a href={{item.link}} target=”_blank”><img src={{item.image}} /></a>
<a href={{item.link}} target=”_blank”>Purchase this book on Amazon</a>
</div>
今回はテンプレートとして用いているのは
1つですが、
や
などバインドされたコントローラーごとに
という配列に代入される値は異なるので、URLが切り替わるたびに、コンテンツの異なる
が表示されます。
ngAnimate
はAngularJSが提供しているアニメーションのための機能です。上記デモでもngAnimateを使ってアニメーションを行なっています。
ngAnimateの仕組みは1.1.5から1.2にAngularJSがアップグレードする際に仕組みが変わっています。現在AngularJSのStable版の最新は1.0.8 (2013/10/17現在) なので、まだまだngAnimateの仕様は今後変更される可能性があります。
詳細は
というこちらブログが詳しいので興味のある方はご覧ください。
ngAnimateの仕組みについて紹介します。ngAnimateをサポートするディレクティブについては
をご覧ください。ngRepeatやngView、ngIncludeなどがサポートされています。
上記デモでngAnimateでアニメーションしている箇所は以下です。ここではclassとして指定されている
に着目してください。
<div ng-view class="view-demo"></div>
ngAnimateではアニメーションのイベントが発火した際にCSSのクラスが指定要素に追加される形でアニメーションを行ないます。幾つか使い方があるのですが、ngAnimateを使用したい場合には、例えばngRepeat、ngView、ngIncludeなどngAnimateをサポートしているディレクティブにクラスを設定します。ここでは
と設定しています。そして、その
に関連して、
、
などの幾つかのクラスのCSSを記述します。以下のCSSを見てみましょう。
に.ng-enter、.ng-enter-active、.ng-leave,.ng-leave-asctiveなどのクラスを記述しています。
ngViewではHTMLテンプレートや何らかのコンテンツが読み込まれて表示された時に
が、コンテンツが表示されなくなった時に
が発火します。enterイベントが発火した時には.ng-enterと.ng-enter-activeクラスが対象の要素に対して追加されます。leaveイベントが発火した際には、ng-leave、ng-leave-activeクラスが対象の要素に追加されます。アニメーションが完了するとこれらの付加されたCSSは取り除かれます。
例えば、URLが切り替わって
という組み合わせのコンテンツが消え、
という組み合わせのコンテンツが新しく表示されるとき、
および
が新しく表示される
に適用され、
および
が表示されなくなる
に適用されます。アニメーションが完了した時にはこれらのクラスは取り除かれます。
style.css
/*対象の属性 (view-demo) を持つ要素に追加されるCSS*/
.view-demo.ng-enter, .view-demo.ng-leave {
-webkit-transition-duration: 1s;
-moz-transition: 1s;
-o-transition: 1s;
transition:1s
display:block;
position:absolute;
}
/*コンテンツが表示される時に対象の要素に追加されるCSS(始点)*/
.view-demo.ng-enter {
left:100%;
}
/*コンテンツが表示される時に対象の要素に追加されるCSS*/
.view-demo.ng-enter-active {
left:0%;
}
/*コンテンツが表示されなくなる時に対象の要素に追加されるCSS(始点)*/
.view-demo.ng-leave {
opacity: 1;
left:0%;
}
/*コンテンツが表示されなくなる時に対象の要素に追加されるCSS*/
.view-demo.ng-leave-active {
opacity: 0;
left:100%;
}
このCSSを定義することで実際にURLが変わってテンプレートが切り替わった時には
1:新しく表示されるコンテンツのアニメーションの始点 (最初の状態) として
.view-demo.ng-enter {
left:100%;
}
が適用されます。
2:そして次に、新しく表示されるコンテンツに対して
.view-demo.ng-enter-active {
left:0%;
}
が適用されます。結果として、新しく入ってくるコンテンツはleftが100%の状態からleftが0の状態になるので、表示されるときには右から左へとスライドアニメーションで入ってきます。そして表示されなくなるコンテンツの場合は
3:表示されなくなる元のコンテンツのアニメーションの始点 (最初の状態) として
.view-demo.ng-leave {
opacity: 1;
left:0%;
}
が適用されます。
4:そして次に、表示されなくなる元のコンテンツに対して下記が適用されます。
.view-demo.ng-leave-active {;
opacity: 0;
left:100%;
}
表示されなくなるコンテンツに対しては最初はleft:0%;から始まり、そしてleft:100%およびopacity:0;が指定されます。すなわち、表示されなくなるコンテンツは透明になりながら、左から右側にスライドしつつ消えていきます。
下記でアニメーションの時間は1秒に設定して、position:absolute;にしてあります。どうやらngAnimateで移動させるコンテンツはposition:absolute;をかける必要があるようです。
.view-demo.ng-enter, .view-demo.ng-leave {
-webkit-transition-duration: 1s;
-moz-transition: 1s;
-o-transition: 1s;
transition:1s
display:block;
position:absolute;
}
※ 一番上のスマホのデモはデスクトップのデモとは異なりleave-activeをleft:100%;ではなく、left:-100%;にして右ではなく左にスライドしていくようにCSSを下記のように切り替えています。
/*アニメーション*/
.view-demo.ng-leave {
left:0%;
}
.view-demo.ng-leave.ng-leave-active {
left:-100%;
}
画像を除いたソースコードは全てこちらに添付しておきます。相変わらず自分自身勉強不足であるのと場当たり的に作ったので非効率な部分や不要な記述があると思いますがこちらに掲載しておきます。
=======================================================
参考リンク
*
*
*
*
*
*