본문 바로가기
블로그 이미지

방문해 주셔서 감사합니다! 항상 행복하세요!

  
   - 문의사항은 메일 또는 댓글로 언제든 연락주세요.
   - "해줘","답 내놔" 같은 질문은 답변드리지 않습니다.
   - 메일주소 : lts06069@naver.com


앵귤러, 리엑트, 뷰/Angular Tutorial(new)

앵귤러 튜토리얼(Angular tutorial) - 34 : 이벤트와 애니메이션(2)

야근없는 행복한 삶을 위해 ~
by 마샤와 곰 2020. 10. 28.

저번시간에는 마우스 이벤트를 감지하여 앵귤러에서 어떻게 데이터와 화면을 구성하는지에 대해서 살펴 보았습니다.
이번시간에는 비슷한 내용인 에니메이션(animations)에 대해서 살펴 보겠습니다.

Javascript의 라이브러리 중 유명한 Jquery라는 라이브러리가 있습니다.
animate, fadeIn, fadeOut 및 draggable등 다양한 함수를 통해서 이벤트를 지원해주는 멋진 라이브러리 입니다.
마찬가지로, 앵귤러에서도 이러한 애니메이션 이벤트를 직접 다루어 볼 수 있습니다.

버튼을 눌러서 특정 애니메이션을 주는 기능을 만들어 보겠습니다.
프로젝트는 저번과 동일한 프로젝트인 sixStudy에 진행하겠습니다.
먼저 모듈을 설정하여 줍니다.

* 대상 : app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { MyCheckDirective } from './my-check.directive';


import { FormsModule } from '@angular/forms';  
import { ReactiveFormsModule } from '@angular/forms';


import { BrowserAnimationsModule } from '@angular/platform-browser/animations';  //이벤트 에니메이션

@NgModule({
  declarations: [
    AppComponent,
    MyCheckDirective
  ],
  imports: [
    BrowserModule,
    FormsModule,
    ReactiveFormsModule,
    BrowserAnimationsModule  //이벤트 에니메이션
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

 

BrowserAnimationsModule을 추가하여 에니메이션 이벤트를 지원해 주도록 설정 하였습니다.
이어서 app컴포넌트에 컴포넌트 데코레이터에 속성을 추가하여 줍니다.

* 대상 : app.component.ts

import { state, trigger,style,transition,animate } from '@angular/animations';  //나중에 사용할 에니메이션 입니다.
import { Component } from '@angular/core';
import { FormControl } from '@angular/forms';  //추가
import { my_check } from './my-check.directive';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  animations: [  //에니메이션 속성을 추가하였습니다.

  ],  
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = new FormControl('', my_check()); 
  private canElementMove = false; 
  position = {
    left : '0px',
    top : '0px',
    width : '200px',
    height : '200px',
    border : '1px solid gray',
    position : 'absolute'
  };
  set mouseStatus(arg){
    this.canElementMove = arg;
  }
  getEvent(event) : void{
    if(this.canElementMove){  
      //console.log(event)
      this.position.left = event.clientX - 100  + 'px';
      this.position.top = event.clientY - 100   + 'px';
    }
  }

 

컴포넌트에 animations라는 속성을 추가하였습니다.
해당 속성을 통해서 사용자가 정의한 에니메이션을 추가할 수 있습니다.
앵귤러에서의 에니메이션은 기본적으로 조건, 상태, 행동 3가지로 나누어 집니다.
1. trigger : 방아쇄, 행동을 정의합니다.
2. state : 상태, 주어진 상태에서의 스타일을 정의 합니다.
3. transition : 변화(전이), 상태가 변경될 때의 행동을 정의 합니다.

animations 속성에 위 단계를 맞추어서 기능을 정의하여주면 됩니다.

────────────────────────────────────────
* 1단계
    trigger('이름', [
      //상태와 변화에 대한 정의
    ])
────────────────────────────────────────
* 2단계
    trigger('이름', [
      state('상태값',css속성),
      //...
    ])
────────────────────────────────────────
* 3단계
    trigger('이름', [
      state('상태값',css속성),
      //...
      transition('변화조건', [행동])
      //...
    ])
────────────────────────────────────────

 

위 3단계가 이번내용의 핵심 입니다.
1단계부터 3단계까지의 단계를 살펴본 뒤에 아래코드를 보도록 합니다.

* 대상 : app.component.ts

import { state, trigger,style,transition,animate } from '@angular/animations';
import { Component } from '@angular/core';
import { FormControl } from '@angular/forms';
import { my_check } from './my-check.directive';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  animations: [
    trigger('bigSmall', [  //* 1단계 : 에니메이션 이름
      state('open', style({  //* 2단계 : 상태 값이 open인 경우
        height: '200px',
        width: '200px',
        color: 'white',
        opacity: 1,
        backgroundColor: 'blue'
      })),
      state('closed', style({//* 2단계 : 상태 값이 closed 경우
        height: '100px',
        width: '100px',
        opacity: 0.5,
        backgroundColor: 'green'
      })),
      transition('open => closed', [  //* 3단계 : 상태 값이 open에서 closed로 변하는 경우
        animate('1s')
      ]),
      transition('closed => open', [  //* 3단계 : 상태 값이 closed에서 open로 변하는 경우
        animate('0.5s')
      ]),
    ]),
  ],  
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = new FormControl('', my_check()); 
  private canElementMove = false;
  position = {
    left : '0px',
    top : '0px',
    width : '200px',
    height : '200px',
    border : '1px solid gray',
    position : 'absolute'
  };
  set mouseStatus(arg){
    this.canElementMove = arg;
  }
  getEvent(event) : void{
    if(this.canElementMove){  
      this.position.left = event.clientX - 100  + 'px';
      this.position.top = event.clientY - 100   + 'px';
    }
  }

  //에니메이션 -------------------------
  isOpen = true;  //상태값

  //버튼이벤트
  trigger() {
    this.isOpen = !this.isOpen;
  }

}

 

조건을 이해한 뒤에 코드를 보면 어렵지 않는 내용입니다.
해당 에니메이션 이름은 bigSmall이며, open과 closed상태인 경우에 행동하도록 정의되어 있습니다.
open과 closed상태는 순수 문자열 값을 의미합니다.
state에 정의된 style이라는 함수는 해당 속성을 해당 상태인 경우 적용해주는 함수 입니다.

다음으로 transition 함수는, 변화에 대한 방향을 보여주고 있습니다.
open값이 closed값으로 변하면 스타일이 바뀌는데, 바뀔 때 animate라는 함수를 지정된 시간동안 하도록 정의하였습니다.
이어서 app컴포넌트 html코드를 수정하여 줍니다.

* 대상 : app.component.html

<!-- <input type="text" name='_title' [formControl]="title" my_check/> -->
<!-- my_check은 my-check디렉티브 셀렉터이며, 유효성 검사 함수입니다. -->
<!-- <div *ngIf="title.errors?.wrongID">
  {{title.errors?.wrongID}} 형식은 사용할 수 없는 아이디 입니다.
</div> -->

<!-- 
<div [ngStyle]="position" (mousemove)="getEvent($event)" (mousedown)="mouseStatus = true" (mouseup)="mouseStatus = false"  (mouseleave)="mouseStatus = false">Drag Area</div> 
-->

<div [@bigSmall]="isOpen ? 'open' : 'closed'">
  <p>상태 : {{ isOpen ? 'Open' : 'Closed' }}!</p>
</div>

<input type='button' value='trigger' (click)='trigger()'/>

 

처음보는 속성기호가 나왔습니다.
animations를 사용하기위한 일종의 규칙입니다. 여기에 trigger함수를 통해서 isOpen값을 변하도록 하면 에니메이션이 동작합니다.

에니메이션이 동작합니다!

 

이렇게 만들어준 에니메이션을 그대로 컴포넌트에 사용하는 것은 재활용성에 좋지 않습니다.
만들어진 에니메이션을 분리하여 줍니다.
여기서는 bigSmall.ts라는 파일을 만들어서 분리하였습니다.

* 대상 : bigSmall.ts

import { state, trigger,style,transition,animate } from '@angular/animations';

export const bigSmall = trigger('bigSmall', [  //* 1단계 : 에니메이션 이름
    state('open', style({  //* 2단계 : 상태 값이 open인 경우
        height: '200px',
        width: '200px',
        color: 'white',
        opacity: 1,
        backgroundColor: 'blue'
    })),
    state('closed', style({//* 2단계 : 상태 값이 closed 경우
        height: '100px',
        width: '100px',
        opacity: 0.5,
        backgroundColor: 'green'
    })),
    transition('open => closed', [  //* 3단계 : 상태 값이 open에서 closed로 변하는 경우
        animate('1s')
    ]),
    transition('closed => open', [  //* 3단계 : 상태 값이 closed에서 open로 변하는 경우
        animate('0.5s')
    ]),
])

 

이제 app컴포넌트를 변경하여 봅니다.

기존의 에니메이션과 관련된 내용을 제거하고 새로 만들어준 파일을 import하여 내용을 가져오도록 합니다.

* 대상 : app.component.ts

import { Component } from '@angular/core';
import { FormControl } from '@angular/forms';
import { my_check } from './my-check.directive';

import {bigSmall} from './bigSmall';  //분리한 ts파일이 있는 위치

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  animations: [
    bigSmall
  ],  
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = new FormControl('', my_check()); 
  private canElementMove = false;
  position = {
    left : '0px',
    top : '0px',
    width : '200px',
    height : '200px',
    border : '1px solid gray',
    position : 'absolute'
  };
  set mouseStatus(arg){
    this.canElementMove = arg;
  }
  getEvent(event) : void{
    if(this.canElementMove){  
      this.position.left = event.clientX - 100  + 'px';
      this.position.top = event.clientY - 100   + 'px';
    }
  }

  //에니메이션 -------------------------
  isOpen = true;  //상태값

  //버튼이벤트
  trigger() {
    this.isOpen = !this.isOpen;
  }

}


이렇게 분리를 하고나면 어디서는 사용 가능한 에니메이션이 완성되었습니다!
에니메이션 같은 경우에는 css와 관련된 내용을 많이 알아야 하므로, 이에 대한 숙달이 조금 필요 합니다.

css에 조금 미흡하면 검색하여 잘 만들어진 모듈을 가져다 쓰는 것도 좋습니다...+ㅁ+
이번 시간에는 앵귤러에서의 에니메이션과 관련된 내용에 대해서 살펴 보았습니다.

sixStudy.zip
0.02MB

 

반응형
* 위 에니메이션은 Html의 캔버스(canvas)기반으로 동작하는 기능 입니다. Html 캔버스 튜토리얼 도 한번 살펴보세요~ :)
* 직접 만든 Html 캔버스 애니메이션 도 한번 살펴보세요~ :)

댓글