MonacaとNCMBで地図メモアプリを作る（その1: 画面の仕様とSDKの初期化）

スマートフォンと地図は相性が良いです。スマホは持ち歩いて使うのが基本ですし、位置情報などの情報も取得できます。

今回はNCMBとMonacaを使って地図上にメモできる地図メモアプリを作ります。地図はOpenStreetMapのものを利用し、タップした場所にメモと写真を残しておけるアプリです。

まず最初の記事では画面の説明とSDKの導入までを進めます。

## コードについて

今回のコードは[map-note-monaca](https://github.com/NCMBMania/map-note-monaca) にアップロードしてあります。実装時の参考にしてください。

## 利用技術について

今回は次のような組み合わせになっています。OpenLayersは地図ライブラリです。国土地理院APIは位置情報を住所に変換する、逆ジオコーディングに利用しています。

- Monaca
- Framework7
- OpenLayers
- 国土地理院API

## 仕様について

地図はOpenLayersを使い、OpenStreetMapを表示します。

## 利用する機能について

地図メモアプリで利用するNCMBの機能は次の通りです。

- データストア
  - データ登録
  - データ取得
- ファイルストア
  - アップロード
  - ダウンロード

## 画面について

今回は以下の3つの画面があります。

### www/pages/map.html

![1357 localhost - 0712180616.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/f47acbde-9f97-02d2-a30b-7b92e3503ed5.jpeg)


OpenLayerを使い、OpenStreetMapを表示します。デフォルトは東京タワーの位置情報としていますので、位置情報取得のダイアログは使いません。

### www/pages/note.html

![1356 localhost - 0712180608.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/2df23d87-25de-6283-29a5-df3e6451f0c3.jpeg)


地図上のタップされた場所にメモおよび画像を記録するための画面です。

### www/pages/list.html

![1359 localhost - 0712180638.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/d9340aea-d5bd-8727-baa9-8f926842ef5b.jpeg)


地図画面で表示しているメモを一覧表示する画面です。

### SDKのインストール

今回はMonacaのJS/CSSコンポーネントの追加と削除より、NCMBを追加します。アプリのテンプレートはFramework7のJavaScript版（VueやReactではなく）を選択しています。

## NCMBのAPIキーを取得

[mBaaSでサーバー開発不要！ | ニフクラ mobile backend](https://mbaas.nifcloud.com/)にてアプリを作成し、アプリケーションキーとクライアントキーを作成します。

## js/config.jsonの作成

js/config.jsonを作成し、その中に先ほど取得したNCMBのAPIキーを設定します。内容は次のようになります。

```json
{
	"applicationKey": "YOUR_APPLICATION_KEY",
	"clientKey": "YOUR_CLIENT_KEY"
}

```

## 初期化

初期化は `js/app.js` にて行います。config.jsonを読み込む関係上、非同期処理内にて行います。cordovaの有無（アプリまたはプレビューの違いを検知）によって初期化時のイベント処理を変えています。

```jsx
// NCMBの初期化を行う
// window.cordovaが存在する場合は'deviceready'、それ以外の場合は'DOMContentLoaded'イベントが発火した時に実行
const event = window.cordova ? 'deviceready' : 'DOMContentLoaded';
document.addEventListener(event, async (e) => {
  // この中に処理を書きます
});
```

config.jsonの内容を読み込んで、NCMBとFramework7の初期化を行います。

```jsx
// 設定ファイルを非同期で取得
const config = await (await fetch('./js/config.json')).json();
// NCMBのインスタンスを作成
window.ncmb = new NCMB(config.applicationKey, config.clientKey);
// Framework7のインスタンスを作成
window.app = new Framework7({
  name: 'My App', // アプリ名
  theme: 'auto', // テーマの自動検出
  el: '#app', // アプリのルート要素
  store: store, // 状態管理ストア
  routes: routes, // ルーティング設定
});
```

これでNCMBの初期化が完了します。

## ルーティング設定

今回は地図画面、ノート画面、リスト画面の3画面になります。これを `js/routes.js` に定義します。

```jsx
// ルーティングの設定を行う配列
const routes = [
  {
    // pathはルーティングのパスを指定します。
    // '/'の場合はルート（ホーム）を意味します。
    path: '/',
    // urlはそのパスが指定された時にロードされるHTMLファイルの場所を指定します。
    url: './index.html',
  },
  {
    // '/map/'というパスが指定された時にロードされるコンポーネントのURL
    path: '/map/',
    componentUrl: './pages/map.html',
  },
  {
    // '/list/'というパスが指定された時にロードされるコンポーネントのURL
    path: '/list/',
    componentUrl: './pages/list.html',
  },
  {
    // '/note/:lat/:lng/'というパスが指定された時にロードされるコンポーネントのURL
    // この場合、:latと:lngはパラメータとなり、動的に値が入ります。
    path: '/note/:lat/:lng/',
    componentUrl: './pages/note.html',
  },
  // どのルートにもマッチしない場合（404）のルート定義
  // ルーティングの一番最後に配置しなければなりません（全てのルートがマッチしない場合にこのルートが使用されるため）
  {
    path: '(.*)',
    url: './pages/404.html',
  },
];
```

## ストア

ストアはアプリ全体で利用する変数です。今回は取得したメモ一覧と、現在の中心座標の2つをストアで管理します。

```jsx
// Framework7のcreateStore関数を使ってストアを作成します
const createStore = Framework7.createStore;

// ストアを作成し、初期状態としてnotesとcoordsを設定します
const store = createStore({
  // stateはアプリケーションの状態を保存します
  state: {
    // notesはメモのリストを保存します。初期状態は空配列です
    notes: [],
    // coordsは現在の座標を保存します。初期状態は東京タワーの座標です
    coords: {
      lat: 35.6585805,
      lng: 139.7454329,
    },
  },
  // gettersはstateから特定のデータを取得するための関数を定義します
  getters: {
    // notesのゲッター。stateからnotesを取得します
    notes({ state }) {
      return state.notes;
    },
    // coordsのゲッター。stateからcoordsを取得します
    coords({ state }) {
      return state.coords;
    },
  },
  // actionsはstateを更新するための関数を定義します
  actions: {
    // coordsを更新するためのアクション
    setCoords({ state }, coords) {
      state.coords = coords;
    },
    // 新たなメモを追加するためのアクション
    addNote({ state }, note) {
      state.notes = [...state.notes, note];
    },
    // 複数のメモを一度に追加するためのアクション
    resetNote({ state }) {
      state.notes = [];
    },
  },
})
```

## まとめ

今回は地図メモアプリの仕様と画面、NCMBの初期化までを解説しました。次は[地図表示とメモの追加を実装します](https://qiita.com/goofmint/items/038f186f99bdab1aa088)。