LoginSignup
6
5

More than 5 years have passed since last update.

Angularでスライドショー(2) 〜Timerによるページの自動切り替え〜

Last updated at Posted at 2017-09-16

はじめに

Angularでスライドショーを作成する方法について説明しているこの記事、第2回目はTimer機能を使ったページの自動遷移についてです。
解説はいつものとおり「恋に落ちるコード.js」の絵子と樹里がお送りします。

人物紹介

瀬尾絵子:「恋に落ちるコード.js」の登場人物。JavaScript勉強中の女子高生。
篠宮樹里: 同じく「恋に落ちるコード.js」の登場人物。JavaScriptに詳しい女子高生。

今回の目的

樹里「さて、前回はルーティング機能によるページ遷移について学習したわけだが」
絵子「したねー。Angular CLI便利だねー」
樹里「ただし、手動でページを切り替えるのでは、ただのWebページと一緒だ」
絵子「そりゃそうだ」
樹里「目標はスライドショーの作成なので、自動でページが切り替わってくれないと困る。そうしないと各方面から苦情が来る」
絵子「どこの方面だろう」
樹里「なので、今日はタイマーを使ったページの自動切り替え機能を実装するぞ」
絵子「おっけー」

ルートコンポーネントを修正する

樹里「では、前回の続きだ。app.component.tsを次のように修正しよう」

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

絵子「サクッと出来たね」
樹里「では、サクッと修正だ」

slideshow.service.ts
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オペレータを別々に記述しているが、いちいち列挙するのが面倒ならこう書いてもいい」

slideshow.service.ts(抜粋)
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の修正だ」

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が連番でないと動作しないし、ページによって表示する時間を変えることも出来ない。実際には、もっと複雑な処理が必要になる」
絵子「ですよねー」
樹里「次回は、これをベースにして、もっと凝ったものを作ってみよう」
絵子「作ってみよう!」

次回予告

次回は、より実践的なページの切り替え方法について解説します。

6
5
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
6
5