본문 바로가기

FrontEnd/java script

[java script] Vue.js 애니메이션 효과 적용(transition)

728x90
반응형

1. transition : 표시/비표시 애니메이션 효과를 나타냅니다.

 

   ▷ 나타날(혹은 사라질) HTML 태그를 transition 태그로 감쌉니다.

   ▷ 어떻게 변화할지를 CSS로 준비합니다.

 

바로 예제로 알아보도록 하습니다!!

 

 

◎ 체크박스를 누르면 애니메이션 효과가 나타나는 예제

 

<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<link rel="stylesheet" href="style.css" >
	<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
</head>
<body>
	<h2>체크박스로 표시/비표시 애니메이션 효과를 주는 예제</h2>
	<div id="app">
		<label><input type="checkbox" v-model="isOk">변경</label>
		<transition>
			<p v-if="isOk">표시/비표시의 애니메이션~</p>
		</transition>
	</div>
	<script>
		new Vue({
			el:'#app',
			data: {
				isOk: false
			}
		})
	</script>

	<style>
		 /* 나타나고 있을 때와 사라질 때 0.5초 */
		.v-enter-active, .v-leave-active{
			transition: 5s;
		}

		/* 나타나기 전의 상태와 사라진 상태는 투명도가 0, 밑으로 20 이동 */
		.v-enter, .v-leave-to{
			opacity: 0;
			transform: translate(100PX, 200px);
		}
	</style>
</body>
</html>
애니메이션 효과를 사용할 때 효과를 주고싶은 문구에 <transition>으로 감쌉니다.

그리고 어떻게 변화할지 CSS로 준비합니다.

적용 가능한 CSS 스타일

(1) 태그가 나타날 때
   ▷ .v-enter : 나타나기 전의 상태
   ▷ .v-enter-active : 나타나고 있는 상태
   ▷ .v-enter-to : 나타난 상태

(2) 태그가 사라질 때
   ▷ .v-leave : 사라지기 전의 상태
   ▷ .v-leave-active : 사라지고 있는 상태
   ▷ .v-leave-to : 사라진 상태

(3) 태그가 이동할 때
   ▷ .v-move : 태그가 이동할 때

 

 

2. transition-group : 리트트의 수가 증감하거나 위치가 이동할 때 애니메이션 효과를 줄 수 있습니다.

 

◎ 버튼을 누르면 리스트가 증감할 때 애니메이션 효과를 주는 예제

 

<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<link rel="stylesheet" href="style.css" >
	<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
</head>

<body>
	<h2>버튼을 누르면 리스트가 증감할 때 애니메이션 효과를 주는 예제</h2>
	<div id="app">
		<transition-group>
			<li v-for="i in dataList" v-bind:key="i">{{ i }}</li>
		</transition-group>
		<input v-model="addText" placeholder="추가할 리스트">
		<button v-on:click="addList">추가</button><p>
		<button v-on:click="removeLast">맨 뒤 1개 삭제</button>
	</div>
	<script>
		new Vue({
			el: '#app',
			data: {
				dataList: ['벚꽃', '산수유', '진달래', '철죽'],
				addText: ''
			},
			methods:{
				addList: function(){
					this.dataList.push(this.addText);
					this.addText = '';
				},
				removeLast: function(){
					var txtLength = this.dataList.length - 1;
					this.dataList.splice(txtLength, 1);
				}
			}
		})
	</script>
</body>
</html>
transition-group을 만들어서 해당 list들은 모두 transition이 적용됩니다.

'추가'를 누르면 애니메이션 효과와 함께 입력한 text가 추가됩니다.
'삭제'를 누르면 애니메이션 효과와 함께 맨 뒤 text가 삭제됩니다.

 

 

3. list가 정렬되며 이동하는 transition

 

◎ 클릭하면 셔플하는 예제(Vue.js 사용x)

 

<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<link rel="stylesheet" href="style.css" >
</head>
<body>
	<h2>클릭하면 셔플하는 예제</h2>
	<button onclick="shuffleData()">셔플</button>
	<script>
		var dataArray = ['one', 'two', 'three', 'four', 'five'];
		function shuffleData(){
			var buffer = [];
			var len = this.dataArray.length;
			for(var i=0; len > 0; len--){
				var r = Math.floor(Math.random() * len);
				buffer.push(this.dataArray[r]);
				this.dataArray.splice(r, 1);
			}
			this.dataArray = buffer;
			alert(dataArray);

		}
	</script>	
</body>
</html>
셔플을 클릭하면 dataArray에 있는 배열이 자동으로 정렬되는 예제입니다.

1. 함수에 새로운 배열을 지정합니다.
2. 길이 변수를 지정해서 for문의 조건으로 만들어 줍니다.(배열 길이만큼 반복됩니다.)
3. 랜덤으로 섞어주기 위해서 변수 지정 후 random 값을 저장합니다.
4. 새로운 배열에 해당 값을 push로 넣어줍니다.
5. 가져온 데이터를 중복되지 않도록 dataArray에서 지워줍니다.
6. 마지막으로 buffer 배열을 기존 dataArray 배열에 넣은 후 출력합니다. 

 

 

◎ 클릭하면 소트, 셔플하는 예제(Vue.js 사용)

 

<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<link rel="stylesheet" href="style.css" >
	<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
</head>
<body>
	<h2>리스트의 순서가 이동하면서 변하는 애니메이션 예제</h2>
	<div id="app">
		<transition-group>
			<li v-for="item in dataArray" v-bind:key="item">{{ item }}</li>
		</transition-group>
		<button v-on:click="sortData">소트</button>
		<button v-on:click="shuffleData">셔플</button>
		<button v-on:click="addData">추가</button>
	</div>
	<script>
		new Vue({
			el:'#app',
			data:{
				dataArray: ['one', 'two', 'three', 'four', 'five']
			},
			methods:{
				sortData: function(){
					this.dataArray.sort(function(a, b){
						return a - b > 0 ? 1 : -1;
					})
				},
				shuffleData: function(){
					var buffer = [];
					var len = this.dataArray.length - 1;
					for(var i=0; len >= 0; len--){
						var r = Math.floor(Math.random() * len);
						buffer.push(this.dataArray[r]);
						this.dataArray.splice(r, 1);
					}
					this.dataArray = buffer;
				},
				addData: function(){
					var num = this.dataArray.length;
					this.dataArray.push(num + 1);
				}
			}
		})
	</script>

	<style>
		.v-move{
			transition: 5s;
		}
	</style>
</body>
</html>
위의 예제와 shuffle은 동일하고 sort를 추가해서 Vue.js에 적용한 예제입니다.

소트를 누르면 아스키코드 기준으로 오름차순으로 정렬됩니다.

sort의 조건에 따른 정렬 방법이 항상 기억이 안나는데 다시 한 번 정리할게요!

a > b 이면 1, a < b 이면 -1, 그 외는 0으로 입력받고 a>b 일때만 순서를 바꿔줍니다.
따라서 오름차순이 됩니다.

마지막으로 추가 버튼을 누르면 숫자가 추가되게끔 만들어 보았습니다!

 

 

◎ 마무리 예제

 

▷ 변경시 + 100하고 리스트에 값이 있으면 +1씩 더 추가할 것
▷ 삭제 버튼시 오른쪽으로 페이드 아웃 추가
▷ 추가시 마지막 숫자 +1한 숫자를 맨  아래 페이드인 효과로 추가
▷ 소트시 move에 2초 추가
▷ 구구단 보이기 페이드인 추가

 

<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<link rel="stylesheet" href="style.css" >
	<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
</head>
<body>
	<h2>애니메이션이 들어간 숫자 배열 조작과 구구단 출력</h2>
	<div id="app">
		<ul>
			<transition-group>
				<li v-for="(i,index) in myArray" v-bind:key="i">{{ i }}
					<button v-on:click="changeNum(index)">변경</button>
					<button v-on:click="deleteNum(index)">삭제</button>
				</li>
			</transition-group>
			</ul>
			<button v-on:click="addNum">추가</button>
			<button v-on:click="sortNum(myArray)">소트</button>
			<button v-on:click="guguNum">구구단 보이기</button>
			<transition>
			<ul v-if="tf">
					<li v-for="i in myArray">
						<p v-for="j in 9">{{ i }} x {{ j }} = {{ i*j }}</p><br>
					</li>
				</ul>
			</transition>
	</div>
	
	<script>
		new Vue({
			el: '#app',
			data: {
				myArray: [2,3,4,5,6,7,8,9],
				tf: false
			},
			methods:{
				changeNum: function(index){
					var a = this.myArray[index] + 100;

					while(true){
						if(this.myArray.indexOf(a) == -1){
							break;
						} else{
							a += 1;
						}
					}

					this.myArray.splice(index, 1, a);

				},
				deleteNum: function(index){
					this.myArray.splice(index, 1);
				},
				addNum: function(){
					this.myArray.push(this.myArray[this.myArray.length-1]+1);
				},
				sortNum: function(){
					this.myArray.sort(function(a, b){
						return(a < b ? -1 : 1) ;
					})

					this.myArray = this.myArray.filter(function(val, pos, arr){
						return arr.indexOf(val) === pos;
					})

					// for(var i=0; i<this.myArray.length; i++){
					// 	for(var j=i+1; j<this.myArray.length; j++){
					// 		if(this.myArray[i] == this.myArray[j]){
					// 			this.myArray.splice(j, 1);
					// 			j--;
					// 		}
					// 	}
					// }
				},
				guguNum: function(){
					this.tf = !this.tf;
				}
			}
		})
	</script>
	<style>
		.v-enter-active, .v-leave-active{
			transition: 1s;
		}
		.v-leave-to{
			opacity: 0;
			transform: translateX(50px) ;
		}
		.v-enter{
			opacity: 0;
			transform: translateY(50px) ;
		}
		.v-move{
			transition: 1s;
		}
	</style>
</body>
</html>
저번에 했던 조건, 반복문 마무리 문제에서 추가하는 예제입니다.

여기서 애니메이션 효과를 주기 위해서는 효과를 주고싶은 문단마다 transition으로 묶어주는 것 입니다!

그렇게 지정하고 위의 style과 같이 코드를 입력하면 애니메이션 효과가 나타납니다.

아래의 부분은 변경을 누르면 숫자가 100증가하고 만약 중복된다면 1씩 증가시키는 코드입니다.

var a = this.myArray[index] + 100;

while(true){
	if(this.myArray.indexOf(a) == -1){
		break;
	} else{
		a += 1;
	}
}

this.myArray.splice(index, 1, a);​

 

100씩 증가하면서 중복되는 부분을 없애기 위해 많은 시간을 투자했지만 결국 하지 못하고 주변의 도움을 받았습니다.

 

그래도 하나 배웠으니 다음 번에는 더 잘할 수 있겠죠!!

 

많은 분들의 피드백은 언제나 환영합니다! 많은 댓글 부탁드려요~~

 

728x90
반응형