LoginSignup
18
9

More than 5 years have passed since last update.

Ionicのカスタムコンポーネントでペルソナ5のUIを再現してみた

Posted at

この記事はIonic Advent Calendar 2018 18日目の記事になります。

今年になってIonicを触り始め、技術書典5にもIonicの本を出させてもらいました。
この記事では、カスタムコンポーネントで神ゲーであるペルソナ5のフレームUIを再現します。

開発環境

  • Ionic

    • Ionic CLI : 4.1.0
    • Ionic Framework : ionic-angular 3.9.2
    • @ionic/app-scripts : 3.2.1
  • System

    • NodeJS : v10.9.0
    • npm : 6.2.0
    • OS : macOS High Sierra

Ionicでペルソナ5みたいな枠を使いたいッッッ!

こんなの↓

window_S_LW.png

想定

想定としては、枠の中はion-cardと同様の使い方をしたいです。
ページのsassファイルを汚してしまうのは嫌なのでカスタムコンポーネント化します。
不規則なデザインかつ、大きさ(幅と高さ)も可変式にする必要があるのでsvgを使ってデザインを行います。

カスタムコンポーネント作成

$ ionic generate component p5-card

htmlテンプレート編集

<ion-card id="p5-card" (tap)="p5TapEvent()" no-margin>
    <!-- 外側の黒い枠 -->
    <svg class="p5-card-frame" viewBox="0,0,100,100" width=100 height=100 preserveAspectRatio="none" fill="black">
        <polygon points="0,95 90,100 100,0 5,10"></polygon>
    </svg>
        <!-- 内側の白い枠 -->
    <svg class="p5-card-frame" viewBox="0,0,100,100" width=100 height=100 preserveAspectRatio="none" fill="white">
        <polygon points="5,90 89,95 95,5 7,15"></polygon>
    </svg>
    <!-- <p5-card>ここがng-contentとして挿入される</p5-card> -->
    <ng-content></ng-content>
</ion-card>

やっていることは、<ion-card>の幅と高さを100として計算し、svgで枠の形のボックスを挿入しているだけです。
こうすれば、ion-cardの恩恵を受けつつ枠を作ることができます。

.scss編集

p5-card {
    .p5-card-frame {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height:100%;
        z-index: -1;
    }
    #p5-card {
        position: relative;
        background-color: rgba(0,0,0,0);
        border: none !important;
        box-shadow:none;
        padding: 15px 30px 15px 20px;
        text-align: center;
        width: 100%;
    }
}

.ts編集

import { Component, Output, EventEmitter } from '@angular/core';

@Component({
    selector: 'p5-card',
    templateUrl: 'p5-card.html'
})
export class P5CardComponent {
    @Output() p5Tap = new EventEmitter();
    constructor() {
    }
    p5TapEvent() {
        this.p5Tap.emit();
    }
}

アウトプットイベントにp5Tapというイベントを作成しました。
このように、Outputデコレータを使えばカスタムコンポーネント独自のイベントを作ることができます。

問題発生

このままionic serveしてもエラーが出ます。
標準では、カスタムコンポーネント内ではion-*といったIonicのコンポーネントを使うことができません。
では、使える使えるようにしましょう。
components.module.tsを編集します。

components.module.ts編集

import { NgModule, CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
import { CommonModule } from '@angular/common';
import { IonicModule } from 'ionic-angular';
import { P5CardComponent } from './p5-card/p5-card';
@NgModule({
    declarations: [P5CardComponent,
    ],
    imports: [CommonModule,
            IonicModule],
    exports: [P5CardComponent,
    ],
    schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class ComponentsModule {}

ここで新たにimportしたのは

  • P5CardComponent
  • CUSTOM_ELEMENTS_SCHEMA
  • CommonModule
  • IonicModule

P5CardComponentは言うまでもなく、先ほど作成したカスタムコンポーネントです。

CUSTOM_ELEMENTS_SCHEMA

まずschemasと言うのは、

Angularのコンポーネントやディレクティブではない、Angular外で定義された要素とプロパティをHTMLパーサがどのように取り扱うか指定するもの

CUSTOM_ELEMENTS_SCHEMAは、

Angularの標準コンポーネント以外をカスタムコンポーネント内で使っても認識するようにするもの

こうすることで、カスタムコンポーネント内でion-*系のコンポーネントや自分で定義したコンポーネントを使えるようになります。

CommonModule

CommonModule

カスタムコンポーネント内で、Angular標準のDirectiveやPipeを使えるようにするもの

つまり、

  • ngIf
  • ngFor
  • ngSwitch

などの構造Directiveや

  • AsyncPipe
  • DecimalPipe

などのPipeをカスタムコンポーネントで使えるようになります。

IonicModule

app.module.tsで以下のように定義したデザインの条件をカスタムコンポーネントでも使えるようにします。

@NgModule({
  declarations: [ MyApp ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp, {
      backButtonText: 'Go Back',
      iconMode: 'ios',
      modalEnter: 'modal-slide-in',
      modalLeave: 'modal-slide-out',
      tabsPlacement: 'bottom',
      pageTransition: 'ios-transition'
    }, {}
  )],
  bootstrap: [IonicApp],
  entryComponents: [ MyApp ],
  providers: []
})

IonicModuleをimportしていないと、アイコンやモーダルなど影響を受けるコンポーネントは正常に動作しなくなります。

完成

localhost_8100_(iPhone X).png

課題

paddingの値を適当に決めてしまっているので、検証してベストな値を見つけたい。

おまけ

この記事の要領でトグルとスライダーも作ってみた。

Untitled.gif

18
9
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
9