NCMBとFramework7を使ったスワイパーコンポーネントの紹介と使い方

NCMBはモバイルアプリ開発におけるバックエンド機能（認証、データストア、ファイルストア、プッシュ通知など）を提供しています。バックエンドなのでAPIベースで利用するのが基本で、UI（アプリ側）は各自で開発する仕組みになっています。

現在、数多くのアプリが存在し、その中には定番とも言える機能があります。そうした定番機能を各フレームワークごとに実装しておくことで、再利用性高くNCMBが利用できるかと思います。

今回はFramework7で作ったスワイパーコンポーネントを紹介します。Monacaアプリでも利用可能です。

![swiper.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/1459ba76-8bcd-cea4-bea5-e3e6f88f8893.gif)


## UIについて

コンポーネントは1つのHTMLだけで実装されているのが特徴です。そのため、基本的には以下の方法で導入・利用ができます。

1. NCMB SDKの読み込み
1. NCMBのキーの取得
1. NCMBの初期化
1. ルーティングの設定
1. スワイパーUI（HTML）を配置

用意されている画面（機能）は次の通りです。

### スワイパーの表示

![FireShot Capture 084 - 20220221183209 Gallery - localhost.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/9dab6c85-a5e7-4eab-4b57-06584b335688.jpeg)


NCMBのファイルストアに保存されている写真をスワイパーを使って表示します。横方向にスクロールできます。

### ダミー画面への遷移

![FireShot Capture 085 - 20220221183216 Gallery - localhost.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/ea84d544-eeae-f2d7-6d76-48214f1e93e8.jpeg)


写真をタップすると、指定された画面に遷移します。

### 必要なライブラリ・SDKの読み込み

今回利用しているライブラリ・SDKは次の通りです。

- NCMB JavaScript SDK

これらを `www/index.html` で読み込みます。

```html
<script src="js/ncmb.min.js"></script>
```

### 必要なキーの取得

NCMBのアプリケーションキーとクライアントキーを取得します。

- [ニフクラ mobile backend](https://mbaas.nifcloud.com/)

### NCMBの初期化

`www/js/app.js` にてNCMBを初期化します。今回は `www/js/config.json` というファイルにキーを記述しているので、以下のように読み込みを行っています。

```js
const $ = Dom7;
(async () => {
  const device = Framework7.getDevice();
	// 設定ファイルの読み込み
  const config = await (await fetch('./js/config.json')).json();
	// NCMBの初期化
  window.ncmb = new NCMB(config.applicationKey, config.clientKey);

  // Framework7の初期化
  window.app = new Framework7({
    name: 'NCMB Notice',
    theme: 'auto',
    el: '#app',
    id: 'com.nifcloud.mbaas.map',
    store: store,
    routes: routes,
    input: {
      scrollIntoViewOnFocus: device.cordova && !device.electron,
      scrollIntoViewCentered: device.cordova && !device.electron,
    },
    statusbar: {
      iosOverlaysWebView: true,
      androidOverlaysWebView: false,
    },
    on: {
      init: function () {
        if (this.device.cordova) {
          cordovaApp.init(this);
        }
      },
    },
  });
})();
```

### ファイルストアの公開設定

NCMBの管理画面にて、ファイルストアのHTTPS公開設定を有効にします。これでファイルストアにアップロードした写真に対してHTTPS経由でアクセスできるようになります（キーが不要になります）。

### ルーティングの設定

今回は最低限のルーティングを設定しています（ `www/js/routes.js` ）。 `/gallery/` でスワイパーコンポーネントを表示します。 `/cat/:id` は飛び先のURLとしてダミーで指定しているものです。

```js
const routes = [
  {
    path: '/',
    url: './index.html',
  },
  {
    path: '/gallery',
    componentUrl: './pages/gallery.html',
  },
  {
    path: '/cat/:id',
    componentUrl: './pages/dummy.html',
  },
  {
    path: '(.*)',
    url: './pages/404.html',
  },
];
```

`www/index.html` で `/gallery/cat` を最初に表示します。この場合、ファイル名が `cat` で始まっている写真を表示します。

```html
<div id="app">
	<!-- Your main view, should have "view-main" class -->
	<div class="view view-init safe-areas" data-url="/gallery">
	</div>
</div>
```

### スワイパーUI（HTML）を配置

後は [gallery.html](https://github.com/NCMBMania/framework7_swiper_component/blob/main/www/pages/gallery.html) をダウンロードして、`www/pages/gallery.html` に配置するだけです。

### 写真のアップロード

任意の写真をアップロードします。今回は[キャットボックスから警戒する猫の写真素材 - ぱくたそ](https://www.pakutaso.com/20170146011post-9923.html)より猫の画像をお借りしています。写真の名前は `cat-〜.jpg` といった形に統一しています。

### データの登録

今回はデータストアで `Photo` クラスを作成しました。このクラスには `fileName` と `url` というフィールドがあります。このフィールドにファイルストアのファイル名、さらにタップした際の飛び先URLを記述します。

### アプリIDの取得

NCMBではHTTPSアクセスする際に次のようなURLでアクセスします。

```
https://mbaas.api.nifcloud.com/2013-09-01/applications/MKpbJPxaTIU5m1nW/publicFiles/cat-13.jpg
```

この時の `MKpbJPxaTIU5m1nW` はNCMBのアプリによって異なります（これをアプリIDと呼びます）。このアプリIDは管理画面のURLでわかります。

```
https://console.mbaas.nifcloud.com/#/applications/MKpbJPxaTIU5m1nW/file
```

この時の `MKpbJPxaTIU5m1nW` がアプリIDです。

### スワイパーUIについて

スワイパーUIの内容は次のようになります。実装はコメントを参照してください。 `YOUR_APP_ID` は自分のアプリIDに書き換えてください。

```html
<template>
  <div class="page">
    <div class="navbar">
      <div class="navbar-bg"></div>
      <div class="navbar-inner sliding">
        <div class="title">スワイパー</div>
      </div>
    </div>
    <div class="page-content">
      <div class="gallery">
      <div
        data-pagination='{"el": ".swiper-pagination"}'
        data-space-between="10"
        data-slides-per-view="1"
        class="swiper-container swiper-init"
      >
        <div class="swiper-wrapper">
          ${ photos.map(photo => $h`
            <div class="swiper-slide">
              <a href="${photo.url}">
                <img
                  src="https://mbaas.api.nifcloud.com/2013-09-01/applications/${appId}/publicFiles/${photo.fileName}"
                  class="photo"
                  @load=${load}
                />
              </a>
            </div>
          `)}
        </div>
        <div class="swiper-pagination"></div>
      </div>
    </div>
    </div>
  </div>
</template>
<style>
  .swiper-slide {
    width: 80%;
  }
  .photo {
    width: 100%;
    object-fit: cover;
  }
</style>
<script>
  export default function (props, {$f7, $onMounted, $update }) {
    const prefix = `${props.name}`; // 表示対象のファイル名（前方一致）
    const appId = 'MKpbJPxaTIU5m1nW'; // アプリID
    let photos = []; // 取得した画像のURLを入れる変数
    let loadCount = 0; // 読み込み完了した画像の数
    $onMounted(async () => {
      // 読み込み完了画像カウントのリセット
      loadCount = 0;
      reset();
      // ローディングアイコンを表示
      app.preloader.show();
      // 写真を取得します
      photos = await getPhotos();
      // 表示を更新
      $update();
      // ローディングを消します
    });

    // 画像が読み込まれると呼ばれる関数です
    const load = (e) => {
      // 読み込み完了画像のカウンターを1上げます
      loadCount += 1;
      // 全画像が読み込み終わるまで待ちます
      if (loadCount < photos.length) return;
      // 画像の幅を取得
      const width = $('.photo').width();
      // 全画像の高さを幅と同じ（正方形）にします
      $('.photo').css('height', `${width}px`);
      const swiper = app.swiper.get('.swiper-container');
      swiper.update();
      // ギャラリーを表示します
      app.preloader.hide();
    };

    const getPhotos = () => {
      return ncmb.DataStore('Photo')
        .regularExpressionTo('fileName', `${prefix}.*`)
        .limit(100)
        .fetchAll();
    }
    return $render;
  }
</script>
```

## 使いどころ

アプリの中でお知らせや新機能の通知などで画像を並べて表示することはよくあります。1つのデータにつき、複数の写真を並べたい時にもこのスワイパーUIが使えるでしょう。

## まとめ

スワイパーコンポーネントはアプリの中でよくあるUIかと思います。ぜひ使いこなしてください。

[mBaaSでサーバー開発不要！ | ニフクラ mobile backend](https://mbaas.nifcloud.com/)