Monaca × NCMBでマンガビューワーアプリを作る（その3：マンガビューワーの実装）

NCMBにはいくつかの機能がありますが、データベースのように使えるデータストアや写真などを保存しておくファイルストアはよく使われる機能になります。

今回はそのデータストアとファイルストアを組み合わせて、マンガビューワーアプリアプリを作ります。[前回はデータの準備と一覧画面の作成を行いました](https://qiita.com/goofmint/items/12fa244f01a0789a8f00)ので、今回はマンガビューワーの実装を解説します。

## 完成版のコード

作成したデモアプリのコードは[NCMBMania/Monaca_Comic: MonacaとNCMBを使ったマンガアプリのサンプルです](https://github.com/NCMBMania/Monaca_Comic)にアップロードしてあります。実装時の参考にしてください。

## ビューワー画面の実装

`www/pages/view.html` を作成します。HTMLを含めた基本形は次の通りです。

```html
<template>
  <div class="page">
    <div class="navbar">
      <div class="navbar-bg"></div>
      <div class="navbar-inner sliding">
        <div class="left">
          <a href="#" class="link back">
            <i class="icon icon-back"></i>
            <span class="if-not-md">戻る</span>
          </a>
        </div>
        <div class="title">${ title }</div>
      </div>
    </div>
    <div class="page-content">
			<div class="laymic" data-viewer-id="laymic">
			</div>
		</div>
  </div>
</template>
<script>
  export default (props, { $f7route, $on, $f7router, $update, $tick }) => {
		// ここにJavaScriptを記述
    return $render;
  };
</script>
```

### 変数を準備

まず画面で表示するための変数を準備します。基本的に一覧画面から送られてきた変数を受け取るだけです。

```js
const { key } = props; // 検索キー
const { title }  = $f7route.query; // 画面表示用のマンガタイトル
let pages = []; // マンガ画像が入る配列
```

### 画面表示処理

画面表示時のイベントでは、以下の処理を行います。

1. ローディングアイコンの表示
1. ファイルストアからの画像取得
1. マンガビューワーの立ち上げ
1. ローディングアイコンの非表示

コードで書くと、次のようになります。

```js
// 画面を表示する前に実行されるイベント
$on('page:beforein', async () => {
	// ローディング表示
	app.preloader.show();
	// ファイルストアのデータを取得
	const blobs = await getPage();
	// ファイルストアのデータをblob形式に変換
	pages = blobs.map(p => URL.createObjectURL(p));
	// 表示更新
	$update();
	// 描画完了を待つ
	await $tick();
	showLaymic();
	// ローディングを消す
	app.preloader.hide();
});
```

#### ファイルストアからの画像取得

ファイルストアからは、先ほどの `key` を使って取得対象の画像を絞り込みます。また、ファイル名ごとに並べることでページ番号順に取得しています。

ファイルストアを検索しただけではデータのダウンロードまでは行っていませんので、さらに `ncmb.File.download` を使ってダウンロード処理も行っています。

```js
// ファイルストアからデータを取得する関数
const getPage = async () => {
	// ファイル名のキーで検索
	const files = await ncmb.File
		.regularExpressionTo('fileName', `^${key}.*`)
		.order('fileName', false)
		.fetchAll();
	// 写真データをblob形式でダウンロード
	const promises = files.map(f => ncmb.File.download(f.fileName, 'blob'));
	// Promiseで処理を返す
	return Promise.all(promises);
};
```

#### マンガビューワーの立ち上げ

マンガビューワー[laymic](https://github.com/dettalant/laymic)の立ち上げ処理は次のようになります。注意点としては、Framework7の画面が邪魔をしてビューワーが後ろに開いてしまうことです。そのため、今回はlaymicが開いた段階で一旦Framework7全体を非表示にし、laymicを閉じた段階で表示を戻すと言ったことを行っています。

```js
// 電子書籍を表示する処理
const showLaymic = () => {
	// Laymicの表示
	const applicator = new laymic.LaymicApplicator(".laymic", {
		pageWidth: 690,
		pageHeight: 976,
	});
	applicator.open('laymic');
	// Framework7自体を一旦隠す
	app.el.style.display = 'none';
	// 電子書籍を閉じる際にFramework7を表示する
	$('.laymic_close').on('click', e => {
		app.el.style.display = 'block';
		// 一覧ページに戻る
		$f7router.back();
	});
}
```

#### 画面描画内容

`pages` 変数にはblob:ではじまるURLが配列になっています。これを画面上に表示します。

```html
<div class="laymic" data-viewer-id="laymic">
	<!-- 追記（ここから）-->
	${ pages.map(page => $h`
		<img data-src="${page}" />
	`)}
	<!-- 追記（ここまで）-->
</div>
```

さらに標準のCSP（Content-Security-Policy）ではblobが使えないので `www/index.html` を修正します。

```html
<meta http-equiv="Content-Security-Policy" content="default-src * 'self' 'unsafe-inline' 'unsafe-eval' data: gap: content: blob:"> <!-- 最後に blob: を追加-->
```

これでマンガビューワーが立ち上がるでしょう。

![FireShot Capture 282 - 20220506185729 Monaca × Framework7 × NCMB - localhost.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/5561522e-145f-b7b8-8ad4-c9acd52e1507.jpeg)


## まとめ

今回はデータの取得のみになっていますが、認証と組み合わせて既読管理を行ったり、マンガをグルーピングして複数巻管理を実現しても面白そうです。ぜひカスタマイズしてみてください。

NCMBでは他にも認証、プッシュ通知などの機能があります。ぜひあなたのアプリ開発に役立ててください。