Ionic의 커스텀 컴퍼넌트로 페르소나 5의 UI를 재현해 보았다

13355 단어 AngularIonic3ionicSVG
이 기사는 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


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


  • Ionic에서 페르소나 5 같은 테두리를 사용하고 싶습니다!



    이런 ↓



    가정



    상정으로서는, 프레임 안은 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 {}
    

    여기서 새로 가져온 것은
  • 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하지 않으면 아이콘이나 모달과 같은 영향을 받는 구성 요소가 제대로 작동하지 않습니다.

    완성





    도전



    padding의 값을 적당히 결정해 버리고 있으므로, 검증해 베스트인 값을 찾아내고 싶다.



    이 기사의 요령으로 토글과 슬라이더도 만들어 보았다.

    좋은 웹페이지 즐겨찾기