[Vue.js] 뷰 트랜지션(transition)의 사용 방법과 치명적인 문제점
뷰 최신 버전인 2.5.17 버전에서 트랜지션을 사용해보았다.
참고로 그 사용 방법은 Vue.js 공식 페이지에 기가막히게 잘 나와있다.
뷰 트랜지션을 써보다가 마주친 문제를 설명하기에 앞서, 그놈을 어떤식으로 사용하는지 알아보자아~.
뷰(Vue) 트랜지션 사용하기
뷰 템플릿(template) 작성
<transition-group name="fade" v-on:after-enter="fadeNext" tag="div" class="text-center"> <img v-show="fade[0]" key="0" class="logo" src="../assets/logo.png"> <img v-show="fade[1]" key="1" class="logo" src="../assets/logo.png"> <img v-show="fade[2]" key="2" class="logo" src="../assets/logo.png"> </transition-group>
먼저 template 부분인데, 아주아주 간단하다.
- 그냥 "transition-group" 이라는 태그를 사용해주면 되고,
- 효과 이름을 정해서 name="내가 정한 트랜지션 이름" 의 형태로 속성을 넣어주고,
- 자식 엘리먼트들에다가 'key'를 부여해주자.
- 그리고, 이 효과가 나타나게 해주는 switch 역할을 하는 v-show="내가 정한 switch 데이터 변수명" 을 추가해준다(요놈 스위치 변수는 아래 script 코드 부분에서 추가할거심).
- 마지막으로, 우리는 세 개의 로고가 뿅뿅뿅 차례차례 뜨도록 하는게 목적이니까, 첫번째 로고가 다 뜨면 다음 로고가 뜨도록 하는 메소드를 호출해주어야 한다.
요거슨 뷰에서 트랜지션 훅(hook)을 제공해주니, 그것을 이용하면 된다.
사용하는 방법은 다양한데, 나는 'v-on' 디렉티브를 이용하는 방법을 선택했다.
v-on:after-enter="내가 정한 메소드명" 형태로 집어넣어 주면 된다(훅 메소드도 아래 script 코드 부분에서 추가할 것이니 인내하자).
<참고> 트랜지션 훅(hook) 메소드는 총 8가지가 있다. v-on:before-enter v-on:enter v-on:after-enter v-on:enter-cancelled v-on:before-leave v-on:leave v-on:after-leave v-on:leave-cancelled 각각이 어떤 것인지는 뷰 가이드에 두말하면 입아프게 너무나도 자세히 나와 있으니, 조오기 위에 링크 눌러서 참고하시길. |
아직까지는 아무런 효과를 적용해주지 않았으므로 걍 아래와 같은 정적인 상태가 보일 거심.
↓
↓
뷰 스타일(style) 코드 작성
얘가 뿅뿅 나타나도록 CSS 코드로 Fade-in 효과를 만들어보자.
.fade-enter { opacity: 0; } .fade-enter-active { transition: opacity .5s; };
이 코드는, "fade" 라는 이름의 뷰 트랜지션을 정의해준다.
트랜지션 진입 시 처음 상태는 "fade-enter"로 정해주고,
트랜지션 효과는 "fade-enter-active"로 정해준다.
위 코드를 통해 "fade"라는 뷰 트랜지션은
=> 처음에는 'opacity: 0' 에서 시작해서 0.5초동안 opacity가 1로 변하는 트랜지션
이라고 이해하면 된다.
뷰 스크립트(script) 코드 작성
이제 중요한 것 2가지가 남았다.
1. 처음에 트랜지션 효과가 일어나도록 해주는 스위치를 만들어주는 것과,
2. 첫번째 엘리먼트에 트랜지션 효과가 끝났으면, 그 다음 엘리먼트에 효과가 일어나도록 하는 훅 메소드를 만들어주는 것.
let fadeIdx = 0 export default { ... data() { return { fade: [false, false, false] } }, methods: { fadeNext: function() { this.fade.splice(fadeIdx++, 1, true) } }, mounted() { setTimeout(this.fadeNext, 1000) } } ...
fade 배열은 각각의 로고 이미지들의 트랜지션을 시작시켜주는 스위치들의 배열이다.
default 값이 모두 false 이므로, 어디선가 누군가가 값을 true로 바꿔주지 않으면, 트랜지션 효과는 일어나지 않는다.
fadeNext 함수는 다음 순서의 트랜지션 스위치를 켜는 역할을 한다.
즉, fade 배열에서, 다음 인덱스의 스위치를 켜는 역할을 한다.
인덱스 값의 default가 0이므로, 맨 처음 트랜지션도 해당 함수로 켜면 된다.
(위 코드에서는 mount가 되면, 1초 뒤에 맨 처음 로고의 트랜지션이 시작되도록 해놔씀)
결과물, 그리고...
읭...?
뭔가 이상하지 않음?
원하던 아름다운 그림이 아닐 거시다.
'by WANZARGEN' 이 위에있다가, 로고 트랜지션이 시작되어야 제자리로 내려간다...
by WANZARGEN 요거슬 괜히, 그냥, 한 번 짱인 척 할라고 넣은 것이 결코 아녀.
그 뿐만이 아님.
얘네들이 제자리에서 뿅뿅뿅 하고 뜨는게 아니라, 하나가 생길때마다 왼쪽으로 밀려난다는...
문제점
이러한 현상이 나타나는 이유는 아주 심플하다.
뷰의 트랜지션은 기본적으로 v-if, v-show 를 사용하여 트랜지션을 시작시키도록 되어있다.
뭔말이냐,
아까 위에서 '트랜지션 스위치' 역할을 하는 변수가 있다고 했잖음?
그 친구가 true면 v-if = true 혹은 v-show = true 가 되고, 해당 엘리먼트가 화면에 보여지기 시작한다는 말이 된다.
이렇게 엘리먼트가 화면에 출력되는 때가 트랜지션이 시작되는 때라고 이해하면 된다.
요까지만 말해도 이해하는 당신, 아래 '참고2'는 제끼십쇼.
<참고2>
|
자신의 영역이 없다가, 트랜지션 스위치가 켜지는 때에 영역이 생겨버리니...
그에 따른 부작용으로 '안예쁜', '의도한 바 없는' 애니메이션이 되버린 것이다.
비교해서 보자.
원하지 않은 결과물 | 이것이 내가 원한 그 것 |
|
|
로고의 영역이 없다가 생기니까 'by WANZARGEN' 문구가 위에 있다가 내려오는 것이고,
로고 이미지를 감싸고 있는 엘리먼트가 '가운데 정렬'인 상황에서,
엘리먼트들이 하나씩 늘어나니, 그에 따라 왼쪽으로 밀리는 것이다.
ㅠ_ㅠ
왜 이런걸 고려하지 않았을까..
솔루션