ionic frameworkってなんだ?　初耳から3時間でいけるところまで理解する

 # はじめに
　この記事はionic frameworkを初めて知ったその日のうちに理解したところまでを雑にまとめた記事なので正確性は保証できない。
　ionic初心者がどのようにして概念を理解したかというメモという位置付けで記事を読んでほしい。
週一で技術記事を書くという目標のもとネタを考えていたが、締切日の夜にionicを初めて知って興味を持ち調べて今に至る。
締切が近いのでかなり雑に知識をキャッチアップした。


ただし、情報のキャッチアップ先は公式ドキュメントで正しい知識を身につけることに努めた。
また、英語は苦手だが翻訳すると不自然な日本語が出てきて、逆に理解度が下がると思い、なるべく英語原文を読む。
じっくり読むというより読める単語を拾って既知の情報で補完してくスタンスでいく。

:::note info
本記事はionicのインストールからプロジェクトの作成、**写真を撮るアプリの作成** までを記録している。
:::


# ionicとは
ionicとはクロスプラットフォームモバイルアプリを構築するためのオープンソースである。

https://ionicframework.com/

 **クロスプラットフォーム:**　異なるプラットフォーム上で同じ仕様のアプリケーションを動作させるプログラムのこと。ここでは１つのプロジェクトでAndroidとiOS両方対応できるという意味のはず。有名なのはFlutterとか。(クロスプラットフォームではないプログラムではAndroidアプリを作る時はKotolin、iOSアプリを作るときはSwiftを使ってそれぞれ開発をしないといけない。)



# 公式ドキュメントを読む
　とりあえず公式ドキュメントを読む

https://ionicframework.com/docs/

## Introduction
英語はどうせ読めないから雑に流す。
AngularかReactかVueで書けるフレームワークっぽい。
あとスマホアプリでよく見るコンポーネント(パーツとか部品)が既に用意されているっぽい(UI Componentsって枠が多分そう)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322871/60137951-4a15-025c-71c1-30e2d972738f.png)


スクロールするとionicの利点が書いてある
詳細は読めないし、読んでも分からんから省略
・ どこでも実行できる
・ パフォーマンスが良い
・ 綺麗でシンプル
・ MoblieもWebも両方いける
そんな事が書いてあるっぽい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322871/8e29f0ee-38b0-f7e2-def0-4028410216aa.png)


以降スクロールしても難しそうな話だったので飛ばす。


ページの一番下にEnvironment Setupがあるので次にいく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322871/049f3be0-0789-531f-2504-d28907569958.png)

## Environment Setup

https://ionicframework.com/docs/intro/environment

Node.jsとnpmがインストール済みだったら、インストールできるようだ。またエディタはVS Codeでいける。
私は全て既にインストール済みだったためこのままいけそうという事が分かった。
(Node.jsのインストールできていない人もググったら詳しい記事などすぐ見つかると思うのでそこまで時間はかからないだろう)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322871/bfbb7392-e695-3155-b605-caef1f6bea29.png)

このページはざっと見ても特にこれ以上重要な情報がなさそうなので次に行く。

## Installing Ionic
https://ionicframework.com/docs/intro/cli

　このページからionicのインストールが始まる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322871/d03e9c18-843b-c0c5-979d-fe29553473bc.png)

Try our App WizardのOPEN WIZARDをクリックすると
別ページに飛んで、なんかアプリ名とかレイアウトとか使いたいJavaScriptのフレームワークを選ばされた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322871/08745e2a-6bc2-bbbf-02ce-c9ee5b239907.png)

とりあえず、
アプリ名→test01
テンプレート→TABS(一番左)
JavaScript Framework→Vue（一番右）
を選んでContinueを押すとアカウントを作成ページに飛んだ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322871/419357a2-57aa-f88c-0816-92aa1af921b6.png)

GitHubのアカウントを持っていたのでContinue with Githubをクリックすると
今度はChoose a　git hostというページに飛んだ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322871/eb8c4a4e-ae1c-a7de-9240-9c6d2da1fe56.png)

ここもGitHubアカウントを持っていたのでGitHubのところのConnectをクリックすると
Compiling your appが始まった。(下記スクショは記事作成用に作った２個目のアプリなのでtest01ではなくtest02になっている)これがちょっと長かった。5分くらい待った気がする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322871/05627659-33ab-6225-8d96-c6878d8c6c69.png)


しばらく待つとホーム画面みたいなのが出てきた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322871/2f20c405-d029-3f0e-212d-b2c02997ca7a.png)

自分のGitHubリポジトリを確認すると、既にアプリ名と同じリポジトリが作成されており、
フレームワークがプッシュされていた！めっちゃ便利！！すごい！

https://github.com/haruharu3220/test-02

そして任意のフォルダと適当に作ってVSCodeをそのフォルダを開いて
```
git clone [GitHubのリポジトリのURL] 指定したいファイル名
```
を打てばGitHubにプッシュされていたコードをローカルに持ってくる事ができた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322871/89e4f6b4-dc2e-099e-df1d-eeb9e35512a1.png)


公式サイトの

https://ionicframework.com/docs/intro/cli

に戻って「Try our App Wizard」の下を確認するとなんかコマンドが書いてある。
多分、自分はTry our App Wizardでブラウザでボタンぽちぽちしてアプリのフレームワークの準備をしたけど、
コマンドを打っても同じようにできるという説明のようなので割愛。次のページにいく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322871/7ba1462a-5ffb-8973-26bc-a92a7c5051f4.png)

## Ionic Packages
https://ionicframework.com/docs/intro/cdn

CDNを使ってionicをインストールする方法が書いてある。npmでインストールしてきたから関係なさそう。飛ばす。

:::note info
**CDN（Contents Delivery Network）** とは、数多くのキャッシュサーバーなどで構成されたプラットフォームを用いることにより、Webサイト上のコンテンツを迅速にエンドユーザーに届けるための仕組み
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322871/f4d1411c-b957-4f47-b01c-e8252f512cf0.png)


## Ionic VS Code Extension
https://ionicframework.com/docs/intro/vscode-extension

VSCodeの拡張機能の話が書いてあるようだが、今は使いこなせないので飛ばす。

## Next Steps
https://ionicframework.com/docs/intro/next

ここから具体的なアプリの開発の説明に入るようだ。
その前に自分が設定したJavaScriptのフレームワークを聞かれた。
私はVueを選んだのでVueのページに飛ぶ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322871/be94926c-b79d-c36a-1e1f-bf263c659020.png)


## Your First Ionic App: Vue
https://ionicframework.com/docs/vue/your-first-app
このページを見ると写真を撮るアプリを作るようだ。
この記事ではここまでの開発することにする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322871/b17b574e-2a7d-c3e3-0c88-6b36a5cf6284.png)

スクロールをすると、Create an App の方法が書いてあるが、既にプロジェクトは作成しているので飛ばした。
ただ、npm install系のコマンドは叩いてインストールした。
具体的には以下のコマンド。(これも全部サイトに書いてある)

```
npm install -g @ionic/cli@latest native-run
npm install @capacitor/camera @capacitor/preferences @capacitor/filesystem
npm install @ionic/pwa-elements
```

そして以下のコマンドを叩いて、サーバを起動する。
```
ionic serve
```
具体的にはVS Codeのコマンドラインで以下のようにコマンドを入力する。
そうするとサーバが起動したURLが表示されるので、
commandを押しながらクリックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322871/940d4d39-dd0e-c953-1b7d-a411ec637d93.png)

すると勝手にブラウザが開いでアプリが動くようになる。

ここからはアプリを作るためにコードのどこを修正したら良いのか、どこにコードを追加すれば良いのかが細かく書いてある。
英語で書いてあるし、コードの全体が書いているのではなく、一部分のみ書いてあるので、どこを修正すればいいのか分かりにくく、何度かエラーに遭遇したが、説明文を読みながらtry&errorで実行した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322871/84c9c087-2e35-abce-bb8e-42b8567e1525.png)


https://ionicframework.com/docs/vue/your-first-app

## Taking Photos with the Camera
次のページも前ページ同様にコードの修正箇所が記載されている。ここもミスをするとエラーを吐くので丁寧に読み進めながらコードを修正していった。

https://ionicframework.com/docs/vue/your-first-app/taking-photos

結構、戸惑った。修正したファイルの全文はこの記事の最後の参考欄に載せておく。

## 完成版
ブラウザで写真を撮れるアプリができた。
娘のアンパンマンの人形もしっかり撮影できた。
サンプルコードはまだ機能追加があるが、この記事ではここまでで完成とする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322871/ad18bc5a-5fef-fb54-c2ac-b76ff6d00ea7.png)

## 振り返り
今回はionic frameworkを初めて知ってから公式サイトを元にサンプルコードを動かすという経験ができた。
公式サイトは読み飛ばしても何とかなるところと丁寧に読み進めないといけないところがあるというのを体感することができたので良かった。
僕は新しいことを学ぶ時に本を買ったり、Udemyの動画を買って基礎の基礎から学んで結局動くものを作るまでに息切れしてしまう経験を何度かしてしまっているので、今回の **「読み飛ばしながらスピード感を持ってまず動くものを作る」**　という経験ができるのは良かったです。これからもどんどん新しいことにスピード感を持って挑戦したいです。 



## 参考
修正したコードの全文は以下の通り

### src/views/Tab2Page.vue(コード修正)
```javascript:Tab2Page.vue
<template>
  <ion-page>
    <ion-tabs>
      <ion-router-outlet></ion-router-outlet>
      <ion-tab-bar slot="bottom">
        <ion-tab-button tab="tab1" href="/tabs/tab1">
          <ion-icon aria-hidden="true" :icon="triangle" />
          <ion-label>Tab 1</ion-label>
        </ion-tab-button>

        <ion-tab-button tab="tab2" href="/tabs/tab2">
          <ion-icon :icon="images" />
          <ion-label>Photos</ion-label>
        </ion-tab-button>

        <ion-tab-button tab="tab3" href="/tabs/tab3">
          <ion-icon aria-hidden="true" :icon="square" />
          <ion-label>Tab 3</ion-label>
        </ion-tab-button>
      </ion-tab-bar>
    </ion-tabs>
  </ion-page>
</template>

<script setup lang="ts">
import {
  IonTabBar,
  IonTabButton,
  IonTabs,
  IonLabel,
  IonIcon,
  IonPage,
  IonRouterOutlet,
} from "@ionic/vue";
import { ellipse, square, triangle } from "ionicons/icons";
</script>
```

### src/views/TabsPage.vue(コード修正)
```javascript:TabsPage.vue
<template>
  <ion-page>
    <ion-tabs>
      <ion-router-outlet></ion-router-outlet>
      <ion-tab-bar slot="bottom">
        <ion-tab-button tab="tab1" href="/tabs/tab1">
          <ion-icon aria-hidden="true" :icon="triangle" />
          <ion-label>Tab 1</ion-label>
        </ion-tab-button>

        <ion-tab-button tab="tab2" href="/tabs/tab2">
          <ion-icon :icon="images" />
          <ion-label>Photos</ion-label>
        </ion-tab-button>

        <ion-tab-button tab="tab3" href="/tabs/tab3">
          <ion-icon aria-hidden="true" :icon="square" />
          <ion-label>Tab 3</ion-label>
        </ion-tab-button>
      </ion-tab-bar>
    </ion-tabs>
  </ion-page>
</template>

<script setup lang="ts">
import {
  IonTabBar,
  IonTabButton,
  IonTabs,
  IonLabel,
  IonIcon,
  IonPage,
  IonRouterOutlet,
} from "@ionic/vue";
import { ellipse, square, triangle } from "ionicons/icons";
</script>
```

### src/composables/usePhotoGallery.ts(新規追加ファイル)
```javascript:usePhotoGallery.ts
import { ref, onMounted, watch } from "vue";
import {
  Camera,
  CameraResultType,
  CameraSource,
  Photo,
} from "@capacitor/camera";
import { Filesystem, Directory } from "@capacitor/filesystem";
import { Preferences } from "@capacitor/preferences";

const photos = ref<UserPhoto[]>([]);

export const usePhotoGallery = () => {
  const takePhoto = async () => {
    const photo = await Camera.getPhoto({
      resultType: CameraResultType.Uri,
      source: CameraSource.Camera,
      quality: 100,
    });
    const fileName = new Date().getTime() + ".jpeg";
    const savedFileImage = {
      filepath: fileName,
      webviewPath: photo.webPath,
    };

    photos.value = [savedFileImage, ...photos.value];
  };

  return {
    photos,
    takePhoto,
  };
};

export interface UserPhoto {
  filepath: string;
  webviewPath?: string;
}

```

### src/main.ts(コード修正)
```javascript:main.ts
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";

import { IonicVue } from "@ionic/vue";

/* Core CSS required for Ionic components to work properly */
import "@ionic/vue/css/core.css";

/* Basic CSS for apps built with Ionic */
import "@ionic/vue/css/normalize.css";
import "@ionic/vue/css/structure.css";
import "@ionic/vue/css/typography.css";

/* Optional CSS utils that can be commented out */
import "@ionic/vue/css/padding.css";
import "@ionic/vue/css/float-elements.css";
import "@ionic/vue/css/text-alignment.css";
import "@ionic/vue/css/text-transformation.css";
import "@ionic/vue/css/flex-utils.css";
import "@ionic/vue/css/display.css";

/* Theme variables */
import "./theme/variables.css";

// Above the createApp() line
import { defineCustomElements } from "@ionic/pwa-elements/loader";

// Call the element loader after the platform has been bootstrapped
defineCustomElements(window);

const app = createApp(App).use(IonicVue).use(router);

router.isReady().then(() => {
  app.mount("#app");
});

```