본문 바로가기

책/Vue.js 퀵스타트

트랜지션 효과

CSS 트랜지션 기초

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title></title>
    <style>
        .box {
            background-color: blue;width: 50px;height: 50px;
        }
        
        .box:hover {
            transition: .5s;transform: translateX(10px);background-color: green;
        }
    </style>
</head>
<body>
    <div class="box"></div>
</body>
</html>

 

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
<style>
    .box {
        background-color: blue;
        width: 50px;
        height: 50px;
        position: absolute;
        top: 20px;
        left: 30px;
    }
    @keyframes shake-box {
        0% { transform: translateX(-20px);background-color: blue;}
        50% {transform: translateX(10px);background-color: yellow;}
        100% {transform: translateX(-20px);background-color: blue;}
    }
    .box:hover {animation: shake-box 0.2s infinite;}
</style>
</head>
<body>
<div class="box"></div>
</body>
</html>

트랜지션 컴포넌트 기초

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
    <title></title>
    <style>
        .box {
            margin: 10px;
        }
        
        .fade-enter-active,
        .fade-leave-active {
            transition: opacity .5s;
        }
        
        .fade-enter,
        .fade-leave-to {
            opacity: 0;
        }
    </style>
</head>

<body>
    <div id="app">
        <div class="box">
            <button @click="changeVisible">보여주기 토글</button>
        </div>
        <div class="box">
            <transition name="fade">
                <img src="hill.jpg" alt="언덕" v-if="visible" />
            </transition>
        </div>
    </div>
</body>
<script type="text/javascript">
    Vue.config.devtools = true;
    var v = new Vue({
        el: '#app',
        data: function() {
            return {
                visible: true
            };
        },
        methods: {
            changeVisible: function() {
                this.visible = !this.visible;
            }
        }
    })
</script>

</html>

 

트랜지션 CSS 클래스

트랜지션 CSS 클래스 설명
v-enter 요소가 나타나기 시작할 때 적용할 클래스
v-enter-active 요소가 나타나는 트랜지션이 진행되는 동안 적용할 클래스
v-enter-to 요소가 나타나는 트랜지션이 완료될 때 적용할 클래스
v-leave 요소가 사라지기 시작할 때 적용할 클래스
v-leave-active 요소가 사라지는 트랜지션이 진행되는 동안 적용할 클래스
v-leave-to 요소가 사라지는 트랜지션이 완료될 때 적용할 클래스

CSS 애니메이션 처리

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
    <title></title>
    <style>
        .box { margin: 10px;}
        .elastic-enter-active { animation: elastic-in .5s; }
        .elastic-leave-active { animation: elastic-in .5s reverse; }
        @keyframes elastic-in {
            0% {transform: scale(0);opacity: 0;}
            50% {transform: scale(1.2);opacity: .5;}
            100% {transform: scale(1);opacity: 1;}
        }
    </style>
</head>
<body>
    <div id="app">
        <div class="box">
            <button @click="changeVisible">보여주기 토글</button>
        </div>
        <div class="box">
            <transition name="elastic">
                <img src="https://kr.vuejs.org/images/transition.png" alt="언덕" v-if="visible" />
            </transition>
        </div>
    </div>
</body>
<script type="text/javascript">
    Vue.config.devtools = true;
    var v = new Vue({
        el: '#app',
        data: function() {
            return {
                visible: true
            };
        },
        methods: {
            changeVisible: function() {
                this.visible = !this.visible;
            }
        }
    })
</script>

</html>

트랜지션 이벤트 훅

 

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
    <title></title>
    <style>
        .box {
            margin: 10px;
        }
        
        .elastic-enter-active {
            animation: elastic-in .5s;
        }
        
        .elastic-leave-active {
            animation: elastic-in .5s reverse;
        }
        
        @keyframes elastic-in {
            0% {
                transform: scale(0);
                opacity: 0;
            }
            50% {
                transform: scale(1.2);
                opacity: .5;
            }
            100% {
                transform: scale(1);
                opacity: 1;
            }
        }
    </style>
</head>

<body>
    <div id="app">
        <div class="box">
            <button @click="changeVisible" :disabled="!buttonEnabled">보여주기 토글</button>
        </div>
        <div class="box">
            <transition name="elastic" 
                @before-enter="elasticBeforeEnter" 
                @after-enter="elasticAfterEnter" 
                @before-leave="elasticBeforeLeave" 
                @after-leave="elasticAfterLeave">
                <img src="https://kr.vuejs.org/images/transition.png" alt="언덕" v-if="visible" />
            </transition>
        </div>
    </div>
</body>
<script type="text/javascript">
    Vue.config.devtools = true;
    var v = new Vue({
        el: '#app',
        data: function() {
            return {
                visible: true,
                buttonEnabled: true
            };
        },
        methods: {
            changeVisible: function() {
                this.visible = !this.visible;
            },
            elasticBeforeEnter: function() {
                console.log("* BeforeEnter!");
                this.buttonEnabled = false;
            },
            elasticAfterEnter: function() {
                console.log("* AfterEnter!");
                this.buttonEnabled = true;
            },
            elasticBeforeLeave: function() {
                console.log("* BeforeLeave!");
                this.buttonEnabled = false;
            },
            elasticAfterLeave: function() {
                console.log("* AfterLeave!");
                this.buttonEnabled = true;
            },
        }
    })
</script>

</html>

Velocity.js 사용

yarn add velocity-animate@1.5.1
또는 
npm install --save velocity-animate@1.5.1


## 사용
import Velocity from 'velocity-animate';

 

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.5.1/velocity.min.js"></script>
    <title></title>
    <style>
        .box {
            margin: 10px;
        }
    </style>
</head>

<body>
    <div id="app">
        <div class="box">
            <button @click="changeVisible">보여주기 토글</button>
        </div>
        <div class="box">
            <transition appear @before-enter="beforeEnter" @enter="enter" @leave="leave">
                <img src="https://kr.vuejs.org/images/transition.png" alt="언덕" v-if="visible" />
            </transition>
        </div>
    </div>
</body>
<script type="text/javascript">
    Vue.config.devtools = true;
    var v = new Vue({
        el: '#app',
        data: function() {
            return {
                visible: true
            };
        },
        methods: {
            changeVisible: function() {
                this.visible = !this.visible;
            },
            beforeEnter: function(el) {
                el.style.opacity = 0;
            },
            enter: function(el, done) {
                Velocity(el, {opacity: 0, scale:.2},{duration: 200} );
                Velocity(el, {opacity: 0.7, scale:1.2},{duration: 200} );
                Velocity(el, {opacity: 1, scale:1},{complete: done} );
            },
            leave: function(el, done) {
                Velocity(el, {translateX: '0px', opacity:1},{duration: 200} );
                Velocity(el, {translateX: '20px', opacity:1},{duration: 100, loop:2} );
                Velocity(el, {translateX: '0px', opacity:1},{duration: 200} );
                Velocity(el, {translateX: '100px', opacity:0},{complete: done} );
            }
        }
    })
</script>

</html>

 

 

리스트에 대한 트랜지션

totolistapp 프로젝트 변경

 

List.vue

<style>
....

.list-enter-active, .list-leave-active {transition: all .5s;}
.list-enter, .list-leave-to { opacity: 0; transform: translateX(50px); }
</style>
<template>
    <transition-group name="list" tag="ul">
        <li v-for="a in todolist" :key="a.id" :class="checked(a.done)" @click="doneToggle({id: a.id})">
            <span>{{ a.todo }}</span>
            <span v-if="a.done">(완료)</span>
            <span class="close" @click.stop="deleteTodo({id:a.id})">&#x00D7;</span>
        </li>
    </transition-group>
</template>
<script type="text/javascript">
....
</script>

 

연락처 애플리케이션에 트랜지션 적용하기

contactapp 프로젝트 변경

yarn add velocity-animate@1.5.1
또는 
npm install --save velocity-animate@1.5.1


## 사용
import Velocity from 'velocity-animate';

src/App.vue

<template>
  <div id="container">
....
        <transition name="flip" mode="out-in">
          <router-view></router-view>
        </transition>
        <loading v-show="isloading"></loading>
  </div>
</template>
<script>
....
</script>
<style scoped>
....
.flip-enter-active, .flip-leave-active {
  transition: all .4s ease-in-out;
}
.flip-enter, .flip-leave-to {
  transform : scaleY(0) translateZ(0);
  opacity : 0;
}
</style>

src/ContactList.vue

<template>
    <div>
 ....
        <transition 
            @before-enter="beforeEnter"
            @enter="enter"
            @leave="leave">
            <router-view></router-view>
        </transition>
    </div>
</template>
<script>
//import eventBus from '../EventBus.js';
import Constant from '../Constant';
import {mapState} from 'vuex';
import Paginate from 'vuejs-paginate';
import Velocity from 'velocity-animate';

export default {
....
    methods : {
 ....
        beforeEnter : function(el) {
            el.style.opacity = 0;
        },
        enter : function(el, done) {
            Velocity(el, {opacity: 0,scale: .2}, {duration: 200});
            Velocity(el, {opacity: 0.7,scale: 1.2}, {duration: 200});
            Velocity(el, {opacity: 1,scale: 1}, {complete: done});
        },
        leave : function(el, done){
            Velocity(el, {translateX : '0px',opacity: 1}, {duration: 100});
            Velocity(el, {translateX : '20px',opacity: 1}, {duration: 100, loop:2});
            Velocity(el, {translateX : '0px',opacity: 1}, {duration: 200});
            Velocity(el, {translateX : '100px',opacity: 0}, {complete: done});
        }
    }
}
</script>

' > Vue.js 퀵스타트' 카테고리의 다른 글

서버 사이드 렌더링  (0) 2020.11.28
단위 테스트  (0) 2020.11.28
vue-router를 이용한 라우팅  (0) 2020.11.28
Vuex를 이용한 상태관리  (0) 2020.11.27
axios를 이용한 서버통신  (0) 2020.11.25