4. transition(화면 전환 효과)
Tags: svelte, frontend, 스벨트
Published: 2022-08-04 08:39:00

# 1. transition 소개

이번에 알아볼 Svelte의 기능은 transition 즉 화면전환 효과 입니다. HTML 돔 영역이 화면에 나타날때 혹은 사라질 때 페이드효과(점점 선명해지는 효과)나 회전 등의 전환 효과를 줄 수 있는 기능입니다.

svetle에서는 이 전환효과를 쉽게 구현할 수 있도록 다음과 같은 트랜지션 효과들을 지원하고 있습니다. 보통 PPT를 작성할 때 사용했던 효과를 떠올리시면 대략 어떤 기능의 효과인지 알 수 있을 것입니다. 

그럼 이 효과들이 어떻게 작동하는지 하나씩 살펴보도록 하겠습니다. 

- fade: 투명한 상태에서 점점 진해지는 효과
- blur: 초점이 맞지 않은 상태에서 선명한 상태로 변화는 효과
- fly: 특정위치로 날라가는 효과
- slide: 접힌 상태에서 펼쳐지는 효과
- scale: 가운데를 중심으로 작은상태에서 큰 상태로 변하는 효과
- draw: svg를 이용하는 전환효과 (뒤에 따로 설명)

```jsx
<script>
	import { fade, blur, fly, slide, scale, draw } from 'svelte/transition';
	import { bounceInOut, backOut } from 'svelte/easing';	
	
	let visibles = {
		'fade': false,
		'slide': false,
		'blur': false,
		'fly': false,
		'scale': false,
	}

	const changeVisible = (type) => {
		visibles[type] = !visibles[type]
	}
	
</script>

<button on:click={() => changeVisible('fade')}>fade</button>
<button on:click={() => changeVisible('slide')}>slide</button>
<button on:click={() => changeVisible('blur')}>blur</button>
<button on:click={() => changeVisible('fly')}>fly</button>
<button on:click={() => changeVisible('scale')}>scale</button>

<br/>

{#if visibles.fade}
	<div transition:fade class="wrap" >
		<h1>fade 예제</h1>
	</div>
{/if}

{#if visibles.slide}
	<div transition:slide class="wrap" >
		<h1>slide 예제</h1>
	</div>
{/if}

{#if visibles.blur}
	<div transition:blur class="wrap" >
		<h1>blur 예제</h1>
	</div>
{/if}

{#if visibles.fly}
	<div transition:fly={{x:100}} class="wrap" >
		<h1>fly 예제</h1>
	</div>
{/if}

{#if visibles.scale}
	<div transition:scale class="wrap" >
		<h1>scale 예제</h1>
	</div>
{/if}

<style>
	.wrap {
		padding: 20px;
		background-color: #288EDD;
		text-align: center;
	}
</style>
```

이 트랜지션을 사용하는 방법은 다음과 같습니다. 사용할 transion을 svelte/transition에서 가져오고, 또 나중에 설명할 easing도 사용할 효과들을 선택해 import로 가져온 다음 효과를 주고싶은 HTML 돔이나 컴포넌트에 transition drective를 입력하면 그 돔이나 컴포넌트가 나타나거나 사라질때 선택한 효과가 나타나게 됩니다. 

```jsx
<script>
	import { fade, blur, fly, slide, scale, draw } from 'svelte/transition';
	import { bounceInOut, backOut } from 'svelte/easing';	
	...
</script>

<div transition:트랜지션이름 > 
	...
</div>
```

그리고 이 transition은 다음과 같은 공통 옵션들이 있습니다. 

- delay: 지정된 시간(밀리초) 후에 전환 효과가 실행.
- duration: 효과가 지정된 시간동안 실행.
- easing: 샘플링된 전환 효과 옵션들

옵션의 경우 transition 이름옆에 이처럼 대활호를 두번 작성하고 그안에 원하는 옵션을 넣어주면 됩니다. delay와 duration의 경우 모두 시간과 관련된 옵션으로 1000은 1초를 의미합니다. 

```jsx
<div transition:트랜지션이름={{duration:1000, delay:500 }} > 
	...
</div>
```

여기 taransiton들 중에서  fade, slide 의 경우는 이 기본 옵션만을 사용합니다. 

# 2. 효과 종류

## 2-1. fade
fade는 효과를 적용할 대상이 투명한 상태에서 점점 진해지도록 하는 전환 효과 입니다. 이 fade의 경우 delay와 duration이라는 속성을 가집니다. 이 두가지 속성을 통해서 효과를 제어할 수 있습니다.

- delay: 지정된 시간(밀리초) 후에 전환 효과가 실행.
- duration: 효과가 지정된 시간동안 실행.
- easing: 샘플링된 전환 효과의 속도 함수.

delay와 duration을 적용해 보도록 하겠습니다. 실행해 보시면 1초후에 동작이 시작되고, 적용되는 효과도 duration 때문에 좀더 천천히 발생하는 것을 볼 수 있습니다.

```jsx
<div transition:fade="{{delay: 1000, duration: 1000}}" class="wrap">
```

추가로 easing이라는 것을 이용할 수 도 있습니다. 이 easing은 효과가 일정한 속도로 나오는 것이 아니고 

좀 다른 속도로 나타나게 됩니다. 이것도 효과를 보면서 설명하겠습니다.

아래 주소에서 각각의 easing이 있습니다. 이중에서 in은 나타날때 out은 사라질때 효과가 적용되고 inout은 나타나고 사라질 때 모두 특정 easing이 적용되는 옵션을 말합니다. 

[https://svelte.dev/docs#run-time-svelte-easing](https://svelte.dev/docs#run-time-svelte-easing)
[https://svelte.dev/examples/easing](https://svelte.dev/examples/easing)

이 easing의 경우transiton처럼 사용할 easing을 import하고 옵션에 적용하면 되겠습니다.

```jsx
import { easing이름 } from 'svelte/easing';
```

## 2-2. slide
slide는 말그대로 슬라이드 효과 즉 접었다 펴지는 효과를 나타냅니다. 속성은 fade와 같은 delay, duration, easing 만을 가집니다. 

- delay
- duration
- easing

## 2-3. blur

blur는 초점이 맞지 않은 것과 같은 흐린 상태에서 점점 선명해지는 효과 입니다. 
blur를 제어하는 속성으로 delay, duration, easing말고 opacity, amount 라는 속성이 추가로 있습니다. 여기서 opactity는 불투명도를 나타내고, amount는 흐릿한 효과의 크기를 나타냅니다. 

- delay
- duration
- easing
- opacity: 애니메이션 불투명도 값(기본값: 0~100)
- amount: px단위로 흐릿해지는 애니메션 크기(기본값: 5)

 옵션을 조절해서 확인해 보면 도움이 될 것입니다. 

```jsx
<div transition:blur="{{delay: 200, duration: 300, opacity: 1, amount: 5}}" class="wrap">
```

## 2-4. fly
fly는 말그대로 설정 좌표(x, y)에서 부터 날라오는 효과입니다. 기본적으로 시작할 좌표를 설정해야 합니다. 그래서 x, y 라는 속성이 필수로 적용해야 합니다. 이때 x, y  하나만 입력해도 됩니다. 
또 다른 옵션으로 선명해 지는 효과도 같이 적용되므로 opacity 도 적용할 수 있습니다. 

- delay
- duration
- easing
- x : 화면효과가 시작되거나 끝나는 x축 좌표
- y: 화면효과가 시작되거나 끝나는 y축 좌표
- opacity

## 2-5. scale

scale은 아주 작은 사이즈에서 원래의 설정된 사이즈로 커지거나 작아지는 효과입니다.  설정값으로는 start가 추가되는데 이값은 효과의 시작시 스케일 사이즈를 나타냅니다. 또 scale역시도 opacity 옵션을 가집니다. 

- delay
- duration
- easing
기본 효과 이외에 
- start : 설정한 크기만큼 커지거나 작어지면서 사라지거나 나타남(기본값:0)
- opacity

## 2-6. in, out 효과

기본적인 트랜지션 사용방법인 'transition:fade' 처럼 적용하면 화면에 나타날때와 사라질 때 모두 같은 효과가 적용됩니다. 여기에 in과 out이라는 디렉티브 이용하면 나타낼때 사라질때 서로 다른 효과를 줄 수 있습니다. 

- in:트랜지션이름
- out:트랜지션이름

사용방법은 이렇습니다. 기존 트렌지션 데신에 in 또는 out에 트렌지션 이름을 사용하면 됩니다. 그리고 옵션은 기존과 동일하게 사용가능합니다.

```jsx
	<div in:트렌지션이름 out:트렌지션이름={{옵션}} class="wrap" >
		...
	</div>
```

예제코드 추가
```jsx
<script>
	import { fade, blur, fly, slide, scale, draw } from 'svelte/transition';
	import { bounceInOut, backOut } from 'svelte/easing';	
	
	let visibles = {
		'fade': false,
		'slide': false,
		'blur': false,
		'fly': false,
		'scale': false,
		'inOut': false,

	}

	const changeVisible = (type) => {
		visibles[type] = !visibles[type]
	}
	
</script>

<button on:click={() => changeVisible('fade')}>fade</button>
<button on:click={() => changeVisible('slide')}>slide</button>
<button on:click={() => changeVisible('blur')}>blur</button>
<button on:click={() => changeVisible('fly')}>fly</button>
<button on:click={() => changeVisible('scale')}>scale</button>
<button on:click={() => changeVisible('inOut')}>in,out</button>

<br/>

{#if visibles.fade}
	<div transition:fade class="wrap" >
		<h1>fade 예제</h1>
	</div>
{/if}

{#if visibles.slide}
	<div transition:slide class="wrap" >
		<h1>slide 예제</h1>
	</div>
{/if}

{#if visibles.blur}
	<div transition:blur class="wrap" >
		<h1>blur 예제</h1>
	</div>
{/if}

{#if visibles.fly}
	<div transition:fly={{x:100}} class="wrap" >
		<h1>fly 예제</h1>
	</div>
{/if}

{#if visibles.scale}
	<div transition:scale class="wrap" >
		<h1>scale 예제</h1>
	</div>
{/if}

{#if visibles.inOut}
	<div in:fade out:slide={{duration:500}} class="wrap" >
		<h1>in, out 예제</h1>
	</div>
{/if}

<style>
	.wrap {
		padding: 20px;
		background-color: #288EDD;
		text-align: center;
	}
</style>
```
in,. out 디렉티브를 이용하면 돔이 나타날 때와 사라질 때 각각 다르게 효과를 줄 수 있게 됩니다. 이 기능도 필요에 따라 유용하게 사용할 수 있습니다. 

## 2-7. draw

draw는 지금까지와는 조금 다른 전환효과 입니다. 일반적인 돔영역에 효과를 주는 것이 아니고, svg라는 일종의 벡터형식의 이미지에 효과를 주는 것입니다. 

참고로 벡터이미지의 경우  <path d='..'> 의 정보와 같이 좌표 하나하나를 기록해서 이미지로 만드는 방식입니다. 즉 svg는 좌표값으로 이루어진 이미지 입니다. 그래서 이 svg이미지에 draw효과를 주면 마치 실제로 이 이미지를 그리는 것과 같은 효과를 볼 수 있습니다. 

옵션으로는 기본적인 delay, duration, easing이 있고 여기에 추가로 speed가 있습니다. speed는 말그대로 그림을 그리는 속도입니다. 

- delay
- duration
- easing
- speed : svg가 그려지는 속도

코드 를 실행시켜 draw가 어떤 효과인지 확인해 보겠습니다.

```jsx
<script>
	import { draw } from 'svelte/transition';
	let visible = true;
</script>

{#if visible}
	<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 103 124">
		<g>
			<path
				in:draw="{{duration: 1000}}"
				style="stroke:#ff3e00; stroke-width: 1.5"
				d='M45.41,108.86A21.81,21.81,0,0,1,22,100.18,20.2,20.2,0,0,1,18.53,84.9a19,19,0,0,1,.65-2.57l.52-1.58,1.41,1a35.32,35.32,0,0,0,10.75,5.37l1,.31-.1,1a6.2,6.2,0,0,0,1.11,4.08A6.57,6.57,0,0,0,41,95.19a6,6,0,0,0,1.68-.74L70.11,76.94a5.76,5.76,0,0,0,2.59-3.83,6.09,6.09,0,0,0-1-4.6,6.58,6.58,0,0,0-7.06-2.62,6.21,6.21,0,0,0-1.69.74L52.43,73.31a19.88,19.88,0,0,1-5.58,2.45,21.82,21.82,0,0,1-23.43-8.68A20.2,20.2,0,0,1,20,51.8a19,19,0,0,1,8.56-12.7L56,21.59a19.88,19.88,0,0,1,5.58-2.45A21.81,21.81,0,0,1,85,27.82,20.2,20.2,0,0,1,88.47,43.1a19,19,0,0,1-.65,2.57l-.52,1.58-1.41-1a35.32,35.32,0,0,0-10.75-5.37l-1-.31.1-1a6.2,6.2,0,0,0-1.11-4.08,6.57,6.57,0,0,0-7.06-2.62,6,6,0,0,0-1.68.74L36.89,51.06a5.71,5.71,0,0,0-2.58,3.83,6,6,0,0,0,1,4.6,6.58,6.58,0,0,0,7.06,2.62,6.21,6.21,0,0,0,1.69-.74l10.48-6.68a19.88,19.88,0,0,1,5.58-2.45,21.82,21.82,0,0,1,23.43,8.68A20.2,20.2,0,0,1,87,76.2a19,19,0,0,1-8.56,12.7L51,106.41a19.88,19.88,0,0,1-5.58,2.45'
			/>
		</g>
	</svg>
{/if}

<label>
	<input type="checkbox" bind:checked={visible}>
	toggle me
</label>

<link href="https://fonts.googleapis.com/css?family=Overpass:100,400" rel="stylesheet">

<style>
	svg {
		width: 100%;
		height: 100%;
	}

	path {
		fill: white;
		opacity: 1;
	}

	label {
		position: absolute;
		top: 1em;
		left: 1em;
	}
</style>
```

실행시켜 보면 그림이 그려지는 것을 볼 수 있습니다. speed 속성을 0.1 ~ 1까지로 설정해 보시면 그려지는 속도가 달라지는 것도 확인할 수 있습니다. 

자 이것으로 svelte에서의 transition에 대해서 알아봤습니다. transition의 경우 필수 기능은 아니지만, 적절히 사용하면 앱의 완성도를 높일 수 있는 기능이입니다. 각각의 transition의 특징을 잘 기억해서 유용하게 사용하시면 좋겠습니다 .

그럼 또 다른 내용으로 또 찾아오겠습니다. 감사합니다.