2021年4月22日木曜日

SPAを作ってみよう

SPAとは何か.SPAは,Single Page Application(シングルページ・アプリケーション)の頭文字をとったものである.シングルページ,つまり,ひとつのページで完結した比較的単純なアプリケーションのことをいう.

一般的なWebアプリケーションは,ネットワークの向こう側にあるサーバとユーザが操作するクライアントが連携し,ときにはページ遷移を伴いセッションを行う.SPAでは基本的にはページ遷移を行わない.

原則として,クライアントで動作するSPAはサーバとは密には連携せず(本プログラムで動画データを適宜ダウンロードしたり,ページ遷移を伴わないAJAX等の技術で逐次通信したりというように,全く切り離して運用するというわけではない),PWA(Progressive Web Application)のようにネットワークに接続されていなくてもある程度の範囲でサーバから独立して動作できるようなものもある.すなわち,一度,サーバからリソースを全てダウンロードして取得してしまえば,クライアント単独で動作させることも可能という形態のWebアプリである.

実装形態は様々だが,基本的に,コンポーネントの論理的な配置を示すHTML,デザインを指定するCSS,アプリケーションの動作,ロジックを記述するJavaScriptの3つがDOM(Document Object Model)を操作することでアプリケーションを実現する.最近ではAltJS(Alternative JavaScript,JavaScript代替品)と呼ばれる各種の言語で実装されることもある.

本稿では,簡単な映像編集アプリを想定して,SPAの開発手順を解説する.手順を追って説明するので,手元にソースコードを編集するエディタとプログラムの動作を確認するためのWebブラウザを用意して,ひとつひとつ確認しながら理解してほしい.

アプリの要求事項と技術的要件

まずは,今回,作り上げるアプリになにを求めるかを明確にしよう.「要求事項」を書き出すという作業である.システム開発は,まずこの段階から始める必要がある.

今回想定するアプリは,シンプルな映像操作アプリである.このアプリに求められる根本的な要件は,次のとおり.

  • いくつかの動画を連続して再生したい
  • その連続させる順序は,ドラッグ・アンド・ドロップの操作で直観的に指定したい

アプリを簡単に実現するために,動画データは作り付けとしよう.アップロードやダウンロードをできるようにしたいところだが,データの管理などサーバとの密な連携が必要になるので後回しとしたい.

続いて技術要件である.単純なSPAとはいえスクラッチから作る(0から作ること)のはいささかしんどい.まずは,どんな技術が使えるかを調べてみるところから始めよう.

調べてみると,コンポーネント(画面の部品)をグリッド配置して,マウス操作できるようにするにはMuuriというJSのライブラリを見つけた.これが使えそうだ(他にもいくつかあるようだが,とりあえずはこれを使ってみることにする).なお,Muuriを使うために,関連ライブラリが必要になるらしいのでそれも用意する.

JavaScriptの各種ライブラリは,都度,ネットからダウンロードして使うようにするやり方も一般的だが,今回はネットに繋がっていないときにでもローカルで開発作業を進められるように,ダウンロードしてローカル側に用意する方法をとった.そのあたりは,皆さんの環境に鑑みて,やりやすい方法を選んでほしい.

さらに,きれいな画面デザインを実現するために,BootstrapというCSSライブラリも用意する.HTML5で表現力が格段に向上したとはいえ,素のデザインはそっけなく,いささか頼りなさすら感じてしまう.本アプリでは,人気がありいろいろなところで使われているBootstrapを使うことにした.JavaScriptのライブラリ同様,Bootstrapもサイトからダウンロードしてローカルに参照することにする.

ステップ1

Muuriの使い方を理解して,白紙のページから粛々と開発していく方法もアリだろう.しかし,そのやり方は,やはり手間がかかる.Muuriをしっかり理解する必要があるし(まあ,これは最終的には必要なことではあるが),ちゃんと設定できないと動作確認すらできない.

そこで,サンプルプログラムを改造していくという方法がオススメしたい.今回の要求事項を満たすためには「Muuri が提供するKanbanという機能がちょうどよさそう」というようにアタリをつけて探してみると,CodePen というサービスに,良さそうなサンプルを見つけた.これを改造していくことを考えよう.

step01.zipをダウンロードして展開しよう(ちゃんと「展開」すること!Windowsの余計な機能に圧縮ファイルをメモリに展開して?そのままフォルダとしてアクセスできるという機能があるようだが,その状態でアクセスすると,CSSなどをうまく参照できず動かないので注意されたい).展開したなかにあるindex_01.htmlをクリックすると,CodePenのサンプル画面のようなSPAが実現されるはずである.アプリの構成は,同HTMLファイルの他,jsディレクトリの下に必要なJavaScriptコードが,cssディレクトリの下にCSSのコードが格納されている.それぞれ,script_01.jsとstyle_01.cssが,我々が修正を加えていくべきコードである.

なお,index_01.htmlをindex.htmlに,script_01.jsとstyle_01.cssをそれぞれscript.jsと style.cssにリネームし,index.htmlからそれぞれのコードを参照している箇所をscript.jsと style.cssに書き換えて作業を続けていくとよい.本稿では,適宜,それぞれのステップでその時点のスナップショットを用意しているが,実際には皆さんが修正を加えつつ,理解しながらコードを書き換えていくことを強くオススメする(次図は,ダウンロードした圧縮ファイルを展開してリネームした後の状態である).

ところで,表示したSPAの,各コンポーネントをドラッグ・アンド・ドロップ操作で動かして,順番を換えられることを確認しよう.Itemだけじゃないことに気付いただろうか?それぞれのカラムも動かして位置を変えることができるようになっている.

ステップ2

先のページを改造して,SPAとして仕上げる.ここで,最終的なゴールのイメージを確認しておこう.

最終的な画面のイメージは,次のようなものである.左側のカラムでサムネイルで表示されているアイテムを操作して,順序を決定,右側の大きなカラムで表示されている動画は,左側に並んだ順番に連続して再生される,というイメージである.

それでは,さっそく改造を施していくことにする.

まずは,CSSを書き換える.カラムの幅の調整である.カラムのデザインは,board-columnというクラスのデザインとして指定されている.

    ...

.board-column {

  position: absolute;

  left: 0;

  top: 0;

  padding: 0 10px;

  width: calc(100% / 5);

  z-index: 1;

}

.board-column.working {

  width: calc(100% * 4 / 5);

}

    ...

widthを,ウィンドウ全体の幅の1/5に調整するように指定しよう.また,右側のカラムには,サブクラスとしてworkingという名前が付いている.そこで,そちらのカラムは4/5になるようにしよう.これで,全体を5つに分けて,1:4の大きさで左右を分けることができるようになった.

もう一つ,細かいことだが,.board-column-headerの text-transform: uppercase;を削除しておこう.

    ...

.board-column-header {

  position: relative;

  height: 50px;

  line-height: 50px;

  overflow: hidden;

  padding: 0 20px;

  text-align: center;

  background: #333;

  color: #fff;

  border-radius: 5px 5px 0 0;

  font-weight: bold;

  letter-spacing: 0.5px;

  text-transformuppercase;

}

    ...

続いて,HTMLの書き換えである.まずは,<div  class="board-column done”>〜</div>をまるごと削除する.

    ...

      </div>

    </div>

  </div>

  <div class="board-column done">

    <div class="board-column-container">

      <div class="board-column-header">Done</div>

      <div class="board-column-content-wrapper">

        <div class="board-column-content">

          <div class="board-item"><div class="board-item-content"><span>Item #</span>11</div></div>

          <div class="board-item"><div class="board-item-content"><span>Item #</span>12</div></div>

          <div class="board-item"><div class="board-item-content"><span>Item #</span>13</div></div>

          <div class="board-item"><div class="board-item-content"><span>Item #</span>14</div></div>

          <div class="board-item"><div class="board-item-content"><span>Item #</span>15</div></div>

        </div>

      </div>

    </div>

  </div>

</div>


<script type='text/javascript' src='./js/web-animations.min.js'></script>

    ...

次に,<div  class="board-column working”>〜</div>の中身を削除する.

    ...

    </div>

  </div>

  <div class="board-column working">

    <div class="board-column-container">

      <div class="board-column-header">Working</div>

      <div class="board-column-content-wrapper">

        <div class="board-column-content">

          <div class="board-item"><div class="board-item-content"><span>Item #</span>6</div></div>

          <div class="board-item"><div class="board-item-content"><span>Item #</span>7</div></div>

          <div class="board-item"><div class="board-item-content"><span>Item #</span>8</div></div>

          <div class="board-item"><div class="board-item-content"><span>Item #</span>9</div></div>

          <div class="board-item"><div class="board-item-content"><span>Item #</span>10</div></div>

        </div>

      </div>

    </div>

  </div>

  <div class="board-column done">

    <div class="board-column-container">

    ...

あとは,細かな修正ではあるが,board-column-headerの記述内容を Todo → Order,Working → Resultに書き換えておこう.

この操作で,画面は次のようになるはずだ.

ドラッグ・アンド・ドロップの操作はそのまま維持されていることも確認しておきたい.ここまでのソースコードのスナップショットをstep02.zipとして置いておくので参考にされたい.

ステップ3

さて,いよいよ動画を扱っていくのだが,動画ファイルそのものと,サムネイル画像のデータをダウンロードしておこう.dataFiles.zipををダウンロードし,index.htmlの置いてあるディレクトリに,data/src01.mp4 … となるように展開してほしい.正しい置き方は,次のようなものである(dataディレクトリの中には,全ての動画,画像データが並ぶようにすること).

サムネイルはタイトルと画像が表示されるようにしたい.そのためにはBootstrapのcardレイアウトが使えそうだ.ひとつのカードはヘッダ(card-header)とボディ(card-body)からなる(図).

Bootstrapを使うために,HTMLに次の行(太字部分)を追加する.

<!DOCTYPE html>

<html lang="en" >

<head>

  <meta charset="UTF-8">

  <title>SPA example</title>

  <link rel="stylesheet" href="./css/style.css">

  <link rel="stylesheet" href="./css/bootstrap.min.css">


</head>

    ...

続いて,Itemの中身をカードで表したアイテムに入れ替えよう(下記の太字部分).

    ...

  <div class="board-column todo">

    <div class="board-column-container">

      <div class="board-column-header">Order</div>

      <div class="board-column-content-wrapper">

        <div class="board-column-content">


          <div class="board-item" id="src01" data-id=1>

            <div class="board-item-content">

              <div class="card">

                <div class="card-header">Movie #1</div>

                <div class="card-body" style="padding: 0px;">

                  <img src="./data/src01.jpg" width="100%">

                </div>

              </div>

            </div>

          </div>

          <div class="board-item" id="src02" data-id=2>

            <div class="board-item-content">

              <div class="card">

                <div class="card-header">Movie #2</div>

                <div class="card-body" style="padding: 0px;">

                  <img src="./data/src02.jpg" width="100%">

                </div>

              </div>

            </div>

          </div>

          <div class="board-item" id="src03" data-id=3>

            <div class="board-item-content">

              <div class="card">

                <div class="card-header">Movie #3</div>

                <div class="card-body" style="padding: 0px;">

                  <img src="./data/src03.jpg" width="100%">

                </div>

              </div>

            </div>

          </div>

          <div class="board-item" id="src04" data-id=4>

            <div class="board-item-content">

              <div class="card">

                <div class="card-header">Movie #4</div>

                <div class="card-body" style="padding: 0px;">

                  <img src="./data/src04.jpg" width="100%">

                </div>

              </div>

            </div>

          </div>


        </div>

      </div>

    </div>

  </div>

    ...

idでファイル名の拡張子以外の部分を指定していたり,data-idという属性を付けていたりしているところは,このあとの作業への伏線である(実はdata-idは最後まで使っていない.ソート機能を実装するときにこれが使えるので,将来への布石である).

ここまでの修正で,サムネイルを表示させることができるようになった(図).

ちょっとだけ修正を加えよう.サムネイルの周りにある余白の白い部分は不要だろう.CSSを修正し,このパディングを削除する.修正すべき点は,board-item-contentクラスにある.paddingの指定を削除しよう.

    ...

.board-item-content {

  position: relative;

  padding: 20px;

  background: #fff;

  border-radius: 4px;

  font-size: 17px;

  cursor: pointer;

  -webkit-box-shadow: 0px 1px 3px 0 rgba(0,0,0,0.2);

  box-shadow: 0px 1px 3px 0 rgba(0,0,0,0.2);

}

    ...

これで,画面は次のようになったはず.とりあえずはこれでヨシということにしよう.

サムネイルをドラッグ・アンド・ドロップすることで順番を指定できるようになった.ここまでのスナップショットをstep03.zipとして置いておく.

ステップ4

さあ,いよいよ右側の動画表示に着手である.右側のカラムに,ビデオ表示の要素を追加する(次のコードの太字部分).moviePaneというIDが付けられている点に注意しておこう.これは,あとでJavaScriptのコードから参照される重要な情報である.

    ...

  <div class="board-column working">

    <div class="board-column-container">

      <div class="board-column-header">Result</div>

      <div class="board-column-content-wrapper">

        <div class="board-column-content">

          <div>

            <video id="moviePane" src="./data/src01.mp4"

                   width="100%" controls="true">

          </div>

        </div>

      </div>

    </div>

  </div>

    ...

この追加で,画面は次のようになるはずだ.

だいぶ形になってきた.ここまでで実現できたことをまとめておこう.

  • 動画の順序をD&DでコントロールするUIを実現できた
  • コントロール用のカラムと,動画を表示するカラムのデザインを実現できた
  • 動画(ひとつだけ)を表示することができた

次に考えるべきことは,一番最初(トップ)のアイテムが変化したときに,ビデオを入れ替えるようにしたい,それにはどうするか,ということだろう.トップの位置をどうやって取得するか,右側画面で動画を入れ替えるにはどうするか,といったあたりがポイントになりそうだ.

JavaScriptを読む

動画の操作を実現するまえに,Muuriのサンプルが提供するJavaScriptのコードをざっと眺めておきたい.全部を理解する必要はないが,重要なポイントは押さえておきたい.

var dragContainer = document.querySelector('.drag-container');

var itemContainers = [].slice.call(document.querySelectorAll('.board-column-content'));

var columnGrids = [];

var boardGrid;


// Init the column grids so we can drag those items around.

itemContainers.forEach(function (container) {

  var grid = new Muuri(container, {

    items: '.board-item',

    dragEnabled: true,

    dragSort: function () {

      return columnGrids;

    },

    dragContainer: dragContainer,

    dragAutoScroll: {

      targets: (item) => {

        return [

          { element: window, priority: 0 },

          { element: item.getGrid().getElement().parentNode, priority: 1 },

        ];

      }

    },

  })

  .on('dragInit', function (item) {

    item.getElement().style.width = item.getWidth() + 'px';

    item.getElement().style.height = item.getHeight() + 'px';

  })

  .on('dragReleaseEnd', function (item) {

    item.getElement().style.width = '';

    item.getElement().style.height = '';

    item.getGrid().refreshItems([item]);

  })

  .on('layoutStart', function () {

    boardGrid.refreshItems().layout();

  });


  columnGrids.push(grid);

});


// Init board grid so we can drag those columns around.

boardGrid = new Muuri('.board', {

  dragEnabled: true,

  dragHandle: '.board-column-header'

});

このコードは,CodePenが提供するKanbanサンプルのJavaScriptソースコードである.ここで,注目すべきは.on('dragReleaseEnd' ... )の部分だ.ここがポイントである.このメソッドは2つ引数をとり,最初の引数で対応するイベント,2つめの引数で,そのイベントが発火したときの処理を記述する.

ここの記述は,ドラッグ・アンド・ドロップが終わったときに呼び出される処理を記述しているということになる.したがって,順番の入れ替えによってメインの動画を書き換える処理は,ここに書いていけばよさそうだということが分かる.

動作の確認

試しに,次のようなデバッグプリントを入れてみる(太字部分).

    ...

  .on('dragReleaseEnd'function (item) {

    item.getElement().style.width = '';

    item.getElement().style.height = '';

    item.getGrid().refreshItems([item]);


    console.log('KOKO');

  })

    ...

このデバッグプリントを入れたことで,ドラッグ・アンド・ドロップの操作が終了した時点でコンソールにメッセージが出力されるはずである.

コンソールの出力を確認するには,Webブラウザの開発ツールを表示してそのコンソールで確かめてみればよい.Google ChromeならF12キーを押せば表示される.Safariなら,開発メニューから「Webインスペクタを表示」させればよい.

コンソールを見ながら,並べ替え操作を行うとどうなるか?「KOKO」というメッセージがコンソールに出力されることを確かめてほしい(図).


JavaScriptコードの追加

では,ドラッグ・アンド・ドロップで並べ替えを行なったときに右側に表示されているビデオを入れ替えるコードを考えていこう.動画を入れ替えるには,video要素のsrcを差し替えればよさそうだ.また,入れ替えるタイミングは一番上のサムネイルが入れ替わったときだけでよい.2つめ以降の順序が入れ替わったとしても,当面は右側の表示を変える必要はないからだ.

video要素を取得するには,document.getElementById('moviePane')とすればよい.当該要素にmoviePaneというIDを付けておいたことを思い出そう.その要素に対してソースを入れ替えればよいが,同じか変える必要があるかはファイル名だけで判定する.パス名は不要なので,パス区切りである「/」で分割して,一番最後の要素を取ってくれば適切な比較ができそうだ.そのために,次のようなメソッドisSrcDifferent()を用意する.

var dragContainer = document.querySelector('.drag-container');

var itemContainers = [].slice.call(document.querySelectorAll('.board-column-content'));

var columnGrids = [];

var boardGrid;


isSrcDifferent = function(a, b) {

  x = a.split("/").slice(-1)[0];

  y = b.split("/").slice(-1)[0];

  return (x != y);

}


// Init the column grids so we can drag those items around.

    ...

split("/")を用いてパス区切り文字「/」で区切り配列にし,slice(-1)で最後の要素のみからなる配列を取得,~[0]でその要素を取得するという手順である.引数に与える2つの文字列を比較し,違っていたらtrueを返すという仕様にした.

大域変数columnGridは,カラムごとにアイテムを管理するための配列である.その対象は次のようになっている.

したがって,columnGrid[0]はサムネイルの集合を含めたカラムであり,getItems()でアイテムの集合を取得できる.ということは,getItems()[0]とすれば先頭のアイテムを取得できるはず.さらにそれに対してgetElement()メソッドを適用することで,HTML要素を取得できる.

その要素が持つIDをgetAttribute('id')で参照すれば,ファイル名の語幹部分を取得可能なので,文字列操作で新しい動画ファイルの参照先を作ることができる.あとは,先ほど用意したisSrcDiffence()を使って「すでに設定されているソースと異なっていれば入れ替える」という処理を加えればよいはずだ.

その処理を.on('dragReleaseEnd', …)に追記しよう.次の太字で表記した部分である.

    ...

  .on('dragReleaseEnd', function (item) {

    item.getElement().style.width = '';

    item.getElement().style.height = '';

    item.getGrid().refreshItems([item]);


    topElm = columnGrids[0].getItems()[0].getElement();

    newSrc = "./data/" + topElm.getAttribute("id") + ".mp4";

    mov = document.getElementById("moviePane");


    if (isSrcDifferent(mov.src, newSrc)) { mov.src = newSrc; }

  })

    ...


ソースコードの修正が終わったら,ドラッグ・アンド・ドロップで先頭を入れ替えたときに,メインの動画も差し替えられるか,確認してみよう.

ここまでのコードはstep_04.zipに置いてあるので,迷ったらそれを参照すること.

ステップ5

動画を指定した順序で再生することを考える.それには,ビデオ再生ボタンが必要だろう.ビデオの再生をどうやって制御するかも考えなければならない.さらには,指定した並び順をどうやって取得して,連続再生するか,その仕組みも考える必要があろう.

まず,HTMLを修正して再生ボタンを追加する.Bootstrapのボタンクラス(btn)を使おう.動画表示の要素の下に,次の一行(太字部分)を追加する.

    ...

  <div class="board-column result">

    <div class="board-column-container">

      <div class="board-column-header">Result</div>

      <div class="board-column-content-wrapper">

        <div class="board-column-content">

          <div>

            <video id="moviePane" src="./data/src01.mp4"

                   width="100%" controls="true">

          </div>

          <a class="btn btn-primary" onClick="playMovies();">Play</a>

        </div>

      </div>

    </div>

  </div>

    ...

onClick属性で,クリックイベントに対してplayMovies()メソッドを結びつけてやる.クリックされたらそのメソッドが呼ばれるという仕掛けである.

JavaScriptにはそのメソッドを記述する.script.js の末尾に次(太字部分)を追加する.

    ...

// Init board grid so we can drag those columns around.

boardGrid = new Muuri('.board', {

  dragEnabled: true,

  dragHandle: '.board-column-header'

});


playMovies = function() {

  console.log('The play button was pushd!');

}

見てのとおり,コンソールにメッセージを出力するだけのスタブである.まずは,これで動作確認してみよう.

このように,Playボタンを押すごとに,コンソールにメッセージが出力される,すなわちコールバック関数としてこのメソッドplayMovies()が呼び出され,実行されていることが確認できただろう.

ここまでのソースコード,スナップショットはstep05.zipにあるのでご参考まで.

ステップ6

さあ,ゴールは見えてきた.次は,Playボタンを押したらムービーの再生が始まるようにする手順である.

JavaScriptの当該部分を修正する.追記したplayMovies()を修正すればよい.video要素を取得する方法はすでに学んでいる.取得した要素に対してplay()メソッドを呼ぶだけ,ビデオの再生が始まるはずである.以下のとおりコードを修正して,動作確認してほしい.

    ...

// Init board grid so we can drag those columns around.

boardGrid = new Muuri('.board'{

  dragEnabled: true,

  dragHandle: '.board-column-header'

});


playMovies = function() {

  mov = document.getElementById("moviePane");

  mov.play();

}

いちおう,この段階のコードをstep06.zipとして置いておいた.為念.

ステップ7

もうほぼ完成だが,「指定した順序でビデオを再生したい」という機能がまだできていない.並び順を取得して連続再生を可能にするにはどうすべきだろうか.

まず,JavaScriptソースコードの冒頭あたりで,大域変数movieFilesを導入しておく.再生すべき動画のソース文字列を格納した配列として扱われる変数である.この宣言は無くても動作するようだが,きちんと書いておいたほうが分かりやすいだろう.

var dragContainer = document.querySelector('.drag-container');

var itemContainers = [].slice.call(document.querySelectorAll('.board-column-content'));

var columnGrids = [];

var boardGrid;

var movieFiles;


// Init the column grids so we can drag those items around.

    ...

そして,後ろのほうに書いておいたplayMovies()メソッドを修正する.実際の再生指示は,新たに用意するplayNext()メソッドで実現する.配列movieFilesが空だったら(length == 0だったら)何もせず戻るとか,配列movieFilesの先頭からひとつ取り出して(movieFiles.shift)セットするといった工夫を加えているが,さほど難しいコードではないから理解は容易だろう.

    ...

// Init board grid so we can drag those columns around.

boardGrid = new Muuri('.board'{

  dragEnabled: true,

  dragHandle: '.board-column-header'

});


playNext = function() {

  if (movieFiles.length == 0) return;

  mov = document.getElementById("moviePane");

  mov.src = movieFiles.shift();

  mov.play();

}


playMovies = function() {

  movieFiles = columnGrids[0].getItems()

    .map(function(item) {

      return "./data/" + item.getElement().getAttribute("id") + ".mp4";

     });

  document.getElementById("moviePane")

          .addEventListener('ended', playNext);

  playNext();

}

playMovies()メソッドは少し丁寧な解説が必要かもしれない.

columnGrids[0]には,サムネイルのアイテムが入っている.そしてgetItems()でその配列が取得できる.配列を対象に操作するmap()メソッドは,関数を引数にとり,それぞれの要素についてその関数を適用した結果を配列にして返す.item.getElement().getAttrribute(“id”)で “src01”などの文字列が得られるので,最終的に変数movieFilesには
( “./data/src01.mp4”, “./data/src02.mp4”… ) という文字列の配列が得られることになる.ここまでが,最初の処理の解説である.

次は,動画要素に「イベントリスナー」を追加する処理である.addEventListener()メソッドは,その処理を行う.

ところでイベントリスナーとは何だろうか?これについてはあとで補足するが,‘ended’イベントが動画が終了したときに発生し,それに応じてplayNext()メソッドが呼ばれるように追加するという設定をここでは行なっている.

最後に,playNext()を明示的に呼び出して最初の動画を再生し,playMovies()は終了する.イベントリスナーを追加することによって,終わったら次,終わったら次,というように,配列で指定するリソースを順次設定して再生する,という手順が少し分かりにくくなっているかもしれない.このような非同期プログラミング(プログラムの進行と実際の処理が同期しないようなプログラミングのこと)は慣れるまでは難しいかもしれないが,ぜひ,慣れておくようにしたいところである.

イベント駆動型プログラミング

非同期プログラミングの1つとしてイベント駆動(event driven)プログラミングにも慣れておきたい.実はすでに使っていて,ドラッグ・アンド・ドロップ終了時の処理の記述とか,Playボタンが押されたときのメソッド呼び出しとか,これらは全て「ドラッグ・アンド・ドロップが押されたよ!」というときに発生するイベントや,「Playボタンが押されたよ!」というときに発生するイベントを受けてメソッドや関数を実行するという形態になっていた.

このようなプログラミングパラダイムのことを,イベント駆動型プログラミングという(図).

ここまでのソースコードはstep07.zipとしてまとめておいた.本稿の指示通りに修正していれば,あらためてダウンロードする必要はないはずだ.Playボタンを押して,Orderカラムに並べたサムネイルの順番にビデオが再生されることを確認しておこう.

まとめ

本稿では,簡単な映像編集アプリを題材にして,シングルページアプリ(SPA)を作りながら,その簡単な作り方について解説した.既存の素晴らしいライブラリを流用しているので,とても簡単に作れることを実感できたことだろう.

今回利用したMuuriにはソートを行う機能もあるので,Muuriを公開しているオリジナルのWebサイトを見るなり情報を調べて,ソートする機能を実装してみるのも一興である.タイトルをクリックすると並べ替えをしてくれるなどの実装例が考えられるだろう.

0 件のコメント:

コメントを投稿