#はじめに
Angularでスライドショーを作成する方法について説明しているこの記事、第2回目はTimer機能を使ったページの自動遷移についてです。
解説はいつものとおり「恋に落ちるコード.js」の絵子と樹里がお送りします。
##人物紹介
瀬尾絵子:「恋に落ちるコード.js」の登場人物。JavaScript勉強中の女子高生。
篠宮樹里: 同じく「恋に落ちるコード.js」の登場人物。JavaScriptに詳しい女子高生。
#今回の目的
樹里「さて、前回はルーティング機能によるページ遷移について学習したわけだが」
絵子「したねー。Angular CLI便利だねー」
樹里「ただし、手動でページを切り替えるのでは、ただのWebページと一緒だ」
絵子「そりゃそうだ」
樹里「目標はスライドショーの作成なので、自動でページが切り替わってくれないと困る。そうしないと各方面から苦情が来る」
絵子「どこの方面だろう」
樹里「なので、今日はタイマーを使ったページの自動切り替え機能を実装するぞ」
絵子「おっけー」
#ルートコンポーネントを修正する
樹里「では、前回の続きだ。app.component.tsを次のように修正しよう」
/* ↓(1) インポートするモジュールの追加 */
// import { Component } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { SlideshowService } from './slideshow.service';
/* ↑ */
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
/* ↓(2) メインの処理 */
/*
export class AppComponent {
title = 'app';
}
*/
export class AppComponent implements OnInit {
constructor(private slideshow: SlideshowService) { }
ngOnInit() {
this.slideshow.start();
}
}
/* ↑ */
##インポートするモジュールの追加
樹里「まず、Componentモジュールに加えてOnInitモジュールもインポートする」
絵子「OnInitって、「Redmineのチケット一覧を取得する」の時も出てきたよね。初期化処理はここに書くと良いんだっけ?」
樹里「そう。それから。後で作るSlideshowServiceもインポートしておく」
絵子「サービスも出てきたな。独立した機能はサービスとして別に作る、と」
##メインの処理
樹里「次に、メインの処理を書き換える。まず、SlideshowServiceのインスタンスを作成する」
絵子「ねえ、キレイに撮れてる?」
樹里「……言っておくが、インスタンスって、インスタに写真をアップする事じゃないからな」
絵子「ちょっとしたジョークじゃない……そんな冷たい目で睨まなくても」
樹里「次やったら、一生取れない犬の鼻を貼り付けるぞ……で、ngOnInit
メソッドで、SlideshowServiceのstart
メソッドを実行する」
絵子「はい……」
#サービス
樹里「次に、ページの自動切り替え機能を提供するサービス、slideshow.service.tsをサクッと作成しよう。コマンドで次のように入力する」
ng g service slideshow
絵子「サクッと出来たね」
樹里「では、サクッと修正だ」
import { Injectable } from '@angular/core';
/* ↓(1) インポートするモジュールの追加 */
import { Router } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/interval';
/* ↑ */
@Injectable()
export class SlideshowService {
/* ↓(2) コンストラクタの修正 */
//constructor() { }
constructor(public router: Router) { }
/* ↑ */
/* ↓(3) タイマーを作成 */
start(): void{
Observable
.interval(3000)
.subscribe(i => this.router.navigateByUrl("page" + (i % 3 + 1)));
}
/* ↑ */
}
##インポートするモジュールの追加
絵子「Observableって、また出てきたね。これって結局何なの?」
樹里「Observableとは、RxJS(Reactive Extensions for JavaScript)というライブラリの中核を成す機能だ。RxJSとは元々Microsoftが開発した非同期処理などを簡潔に処理するためのライブラリで、その非同期のストリームを観察(Observe)することにより……」
絵子「あれ、樹里の姿が遠くに見える。樹里の声が遠くから聞こえる」
樹里「要は、JSONの読み込みだとか、今回のタイマーの処理だとか、非同期の処理を上手いことやってくれる便利な機能だ」
絵子「そっかー。上手いことやってくれるならそれに任せよう」
樹里「で、上記の例ではObservableモジュールとintervalオペレータを別々に記述しているが、いちいち列挙するのが面倒ならこう書いてもいい」
import { Observable } from 'rxjs/Rx';
絵子「あ、これで全部読み込んでくれるんだ。そういう便利なことは早く言ってよ」
##コンストラクタの修正
樹里「これもさっきと同じように、Routerモジュールのインスタンスを作成している」
絵子「……何よ、もうふざけないよ……その手に持ってる犬の鼻と接着剤は何?」
##タイマーを作成
樹里「では、メインとなるタイマーの作成だ。interval
メソッドで、等間隔で値を発行することが出来る」
絵子「JavaScriptにも、setInterval
メソッドってあったよね。あれと同じもの?」
樹里「出来る事は同じだな。発行間隔をミリ秒で指定するのも同じだ」
絵子「3000ミリ秒、つまり3秒間隔に指定してるのね」
樹里「で、subscribe
メソッドで動作を指定する。その際、実行された回数が引数として渡されるので、それをi
という変数に格納している」
絵子「しかと受け取った」
樹里「タイマーが発行される度に、RouterモジュールのnavigateByUrl
メソッドが実行される。引数は遷移先のURLだ」
絵子「引数は『"page" + (i % 3 + 1)』ってやつだね…………何これ?」
樹里「i
にはタイマーの実行回数が格納されている。それを3で割って余りを算出し、1を足している。では、1回目の処理の時は何になる?」
絵子「えーと、1÷3だから、0余り1になって、それに1を足して……2だね」
樹里「そう、だから、1回目は『page2』に遷移することになる」
絵子「なるほど。2回目はpage3、3回目はpage1、4回目はまたpage2……になるわけだね」
#ルートモジュールを修正する
樹里「最後に、app.module.tsの修正だ」
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { Page1Component } from './page1/page1.component';
import { Page2Component } from './page2/page2.component';
import { Page3Component } from './page3/page3.component';
/* ↓(1) インポートするモジュールの追加 */
import { SlideshowService } from './slideshow.service';
/* ↑ */
@NgModule({
declarations: [
AppComponent,
Page1Component,
Page2Component,
Page3Component
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [
/* ↓(2) プロパイダーの追加 */
SlideshowService
/* ↑ */
],
bootstrap: [AppComponent]
})
export class AppModule { }
##インポートするモジュールの追加
樹里「さっき作ったSlideshowServiceをインポートしている」
絵子「うん、これはもうバッチリわかるよ」
##プロパイダーの追加
樹里「サービスをサービスとして使用する時には、このようにprovidersプロパティに追加する必要がある。……これはもう、こういうルールなんだ、と覚えておくしかないな」
絵子「うん、覚えた。こういうもんだ」
#動作確認
樹里「では、完成したところでさっそく動かしてみよう」
ng s
絵子「おー、3秒毎に勝手に画面が切り替わっていく」
樹里「単純なスライドショー機能ならこれだけで実現できる。しかし……」
絵子「現実はそんなに甘くはないよね」
樹里「そう。URLが連番でないと動作しないし、ページによって表示する時間を変えることも出来ない。実際には、もっと複雑な処理が必要になる」
絵子「ですよねー」
樹里「次回は、これをベースにして、もっと凝ったものを作ってみよう」
絵子「作ってみよう!」
#次回予告
次回は、より実践的なページの切り替え方法について解説します。