[Vue] Router 이동할 때 페이지 스와이프 효과 주기
안녕하세요! aloveu입니다.
웹을 돌아다니다 보면 메뉴를 클릭할 때 다음 페이지가 옆에서 나오는 걸 보신 적 있나요?!
어떻게 만들어 졌는지 궁금하시지 않으세요??

Vue에서는 애니메이션처리에 대한 컴포넌트를 제공합니다. <transition /> 인데요.
Vue에서 router로 이동할때 swipe 효과 주려면 transition과 router를 적절히 사용해주면 됩니다.
| 슬라이드 메뉴이동
router-view 컴포넌트를 transition으로 감쌉니다.
transition에 name를 바탕으로 css를 작성합니다.
transition 컴포넌트에서 name 속성은 트랜지션 클래스에 접두사를 지정하는 역할을 합니다. 이를 통해 다양한 트랜지션 효과를 CSS로 스타일링할 수 있습니다.
name="slide"로 지정하면 다음과 같은 클래스가 생성됩니다
.slide-enter: 트랜지션이 시작되기 전 상태
.slide-enter-active: 트랜지션이 진행 중인 상태
.slide-enter-to: 트랜지션이 종료된 상태 (2.1.8 버전부터 추가됨)
.slide-leave: 트랜지션이 시작되기 전 상태
.slide-leave-active: 트랜지션이 진행 중인 상태
.slide-leave-to: 트랜지션이 종료된 상태 (2.1.8 버전부터 추가됨)
코드는 이렇고요.
App.vue 파일
<template>
<div id="app">
<nav>
<!-- 메뉴 링크 -->
<router-link to="/">Home</router-link>
<router-link to="/profile">Profile</router-link>
<router-link to="/blog">Blog</router-link>
</nav>
<div class="wrap">
<transition name="slide">
<router-view></router-view>
</transition>
</div>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
.wrap{
position:relative;
}
.home{
height:100%;
width: 100%;
}
.slide-enter-active,
.slide-leave-active {
position: absolute;
top: 0;
left: 0;
right: 0;
transition: all 0.3s ease;
}
.slide-enter {
transform: translateX(-100%);
}
.slide-leave-to {
transform: translateX(100%);
}
</style>
메뉴를 누르면 스와이프 효과를 내면서 페이지 전환이 됩니다. css를 손보면 fadeIn/Out도 가능하죠.
음...
메뉴를 이동하다 보니 뭔가 어색해요.
어떤 메뉴를 누르던지 무조건 오른쪽에서 왼쪽으로 이동을 하고 있네요. 그래서 메뉴의 순서에 따라 슬라이드 되는 방향을 다르게 적용을 하고 싶어 졌습니다.
router index에 따라 방향을 오른쪽이냐 왼쪽이냐를 정하고 트랜지션 네임을 변경해줬어요. 그리고 그 트랜지션 네임에 따른 css도 다시 설정을 했습니다.
| 방향이 있는 슬라이드 메뉴 이동
App.vue
<template>
<div id="app">
<nav>
<router-link to="/">Home</router-link>
<router-link to="/profile">Profile</router-link>
<router-link to="/blog">Blog</router-link>
</nav>
<div class="router-view-container">
<transition
:name="transitionName"
mode="out-in"
>
<router-view></router-view>
</transition>
</div>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
transitionName: 'slide-left'
}
},
methods: {
getRouteIndex(route) {
const routes = ['/', '/profile', '/blog']
return routes.indexOf(route.path)
},
},
watch: {
$route(to, from) {
const toIndex = this.getRouteIndex(to)
const fromIndex = this.getRouteIndex(from)
this.transitionName = toIndex > fromIndex ? 'slide-right' : 'slide-left'
}
},
}
</script>
<style>
.home{
height: 100%;
}
.router-view-container {
position: relative;
}
.slide-left-enter-active,
.slide-left-leave-active,
.slide-right-enter-active,
.slide-right-leave-active {
position: absolute;
top: 0;
left: 0;
right: 0;
transition: all 0.3s ease;
}
.slide-left-enter {
transform: translateX(-100%);
}
.slide-left-leave-to {
transform: translateX(100%);
}
.slide-right-enter {
transform: translateX(100%);
}
.slide-right-leave-to {
transform: translateX(-100%);
}
nav {
display: flex;
justify-content: space-around;
padding: 20px;
background-color: #f1f1f1;
}
.home{
padding:40px;
}
</style>
그랬더니 짜잔!!
의도한 대로 잘되네요.
코드상에서 mode라는 게 보이는데 이건 transition 컴포넌트에서 mode="out-in" 속성은 새로운 요소가 렌더링 될 때 이전 요소를 먼저 제거하고 새로운 요소를 렌더링 하는 방식을 의미합니다.
in-out (기본값): 새로운 요소가 트랜지션 되어 렌더링된 다음, 이전 요소가 트랜지션되어 제거됩니다.
out-in: 이전 요소가 먼저 트랜지션되어 제거된 후, 새로운 요소가 트랜지션되어 렌더링 됩니다.
out-in을 코드에 적용을 한건 새로운 요소가 이전 요소 위에 렌더링 되지 않기에 애니메이션이 자연스럽게 이어지는 효과를 보기 위해서였어요.
실무에서는 거의 쓰이질 않는데 가끔 이런 요구사항을 요청하실때가 있습니다. 그럴때는 이걸로 참고해서 하세요~!
오늘도 감사합니다. ^___^
| 참고
https://vuejs.org/guide/built-ins/transition#transition-modes
'IT > 개발' 카테고리의 다른 글
[JS] 실무에서 꼭 필요한 Array 메서드 (79) | 2024.04.11 |
---|---|
[JS] 깊은 복사와 얕은 복사 (72) | 2024.04.10 |
[CSS] 버튼에 animation 적용하기 (59) | 2024.04.05 |
[Vue] DefineModel (72) | 2024.04.05 |
[NPM] Bundlephbia (60) | 2024.04.04 |