저번 글에서 학습했던 transition은 확실한 트리거가 있어야 합니다.
click이나 hover 같은.. 그런 트리거가 없다면 아무 일도 일어나지 않죠.
하지만 보다 생동감 있는, 캐릭터에 살아있는 듯한 느낌을 주기 위해선 트리거 없이도 특정 모션을 취하도록 하는 것이 좋지 않을까요?
예를 들면 사람이 숨을 쉴 때마다 들썩거리는 몸통, 깜빡이는 눈, 흠칫하는 동작.. 이런 모션이 캐릭터에도 적용된다면 와.. 진짜 잘만들었다! 살아있는 것 같다! 라는 말을 들 을 수 있을 겁니다.
이런 점을 구현하기 위해선 transition으로는 부족합니다.
그래서 이번에 공부해 볼것이 바로 Animation!
Animation은 어떻게 쓰는지, 어떤 결과를 낼 수 있는지 살펴보고 제 그리니에게 어떤 움직임을 줄건지.. 고민해 봅시다.
Animation은 CSS 스타일 속성과 keyframes로 구성됩니다!
Transition과 비교했을 때 더 정밀한 모션, 애니메이션을 구현 가능합니다.
그말은 즉, 더 어려울것이다. 라고 이해하셔도 됩니다.
Animation의 특징은 다음과 같아요.
keyframes이 뭐지? 는 우선 넣어두고.. 이번에 Animation을 공부하는 이유는 두번째 특징에 있습니다.
저는 제가 컨트롤하지 않아도 스스로 움직이는 캐릭터를 구현하고 싶거든요.
스스로 들썩이거나 눈을 깜빡이는 모션을 구현할 때, 아주 유용할 겁니다.
다음은 토스 웹페이지의 애니메이션 타임라인인데요.
개발자 도구 > More tools > Animation
딱 보면 아시겠죠?
아..! 이 싱크를 내가 전부 맞춰야겠구나!
제가 계속 어렵다는 것을 강조하는 것 같지만, 사실 배워보면 별거 아닐 겁니다.
그러니까 쓰는 사람들이 있고, 사랑받는 속성 중 하나겠죠?
사실 사랑 받는지는 모릅니다.
암튼 가봅시다.
그거 아시나요? transition은 속성이 속기형 포함 5개였지만, animation에는 자그마치 9가지라는 사실..!
그만큼 얼마나 디테일한 표현이 가능할지 매우 기대가 됩니다.
간단히 표로 표현하면 다음과 같습니다.
속성 | 설명 | 기본 값 |
---|---|---|
animation-name | @keyframes 이름 설정 | |
animation-duration | 실행 시간 설정(필수) | 0s |
animation-timing-function | 가속, 감속 설정 | ease |
animation-delay | 실행 지연 시간 설정 | 0s |
animation-iteration-count | 애니메이션 재생 횟수 설정 | 1 |
animation-direction | 애니메이션 재생 방향 설정 | normal |
animation-fill-mode | 애니메이션 종료 후 상태 설정 | none |
animation-play-state | 애니메이션 재생/정지 설정 | running |
animation | 속기형 선언 |
벌써 복잡하시나요?
그래도 다행이건 자세히 보면 익숙한 이름들이 보입니다.
2~4번까지는 아무래도 익숙하죠? 맞습니다. transition에서도 다뤘던 속성입니다.
속기형도 뭔가 별거 없을거 같고..
직접 해봐야 알겠죠. 하나씩 살펴 봅시다.
말 그대로 애니메이션 이름입니다.
이걸 어따 써먹을까요?
바로 @keyframes의 이름을 정해줄 때 쓰입니다.
우선 예제 코드를 보시죠.
음.. 뭐가 많은데, 다른건 신경쓰지 말고 animation-name이랑 @keyframes만 봐볼까요?
뒤에서 자세히 다루겠지만 @keyframes에 대한 간략한 설명을 하자면 구간별로 어떤 움직임을 보일지 설정할 수 있는 속성이라고 생각하시면 됩니다.
위 코드에서 보면 50%에서는 left:200px, 100%에서는 left:0에 위치해라! 이런 의미입니다.
어때요? 이름이 'ani'로 동일하죠?
쉽게 말하면 애니메이션을 주고싶은 요소와 keyframes을 연결시켜준다고 생각하시면 됩니다.
만약 animation-name을 설정해 주지 않는다면?
당연스럽게 아무 움직임이 없습니다.
즉, keyframes을 동작시키기 위해서는 animation-name을 맞춰줘야 하고
필수라고 기재하진 않았지만 필수라고 할 수 있는.. 그런 속성입니다.
따라서 아예 적지 않거나 none을 기재하면 위에서 보이듯이 애니메이션이 동작하지 않을 것 입니다.
물론 animation-name은 네이밍을 하는 것이기 때문에 유효한 규칙이 있습니다.
다음과 같은 경우만 피해주시면 됩니다!
어렵지 않죠? 넘어갑시다.
드디어 익숙한 단어가 나왔습니다.
transition을 공부하신 분들은 다다음까지는 수월하게 이해하실 겁니다!
animation-duration은 애니메이션이 동작하는 시간을 설정합니다.
그래서 필수값! 이라는 거죠. 기재하지 않거나 0s를 입력한다면 동작하지 않을 겁니다.
들어갈 수 있는 값을 다음과 같습니다.
animation-duration: time | initial | inherit;
initial, inherit은.. 다들 아시는 속성값이라고 믿고 넘어가겠습니다.
time은?
time의 기본 값은 0s이고, 단위는 초(s), 1/1000초(ms)를 사용합니다.
어려운 내용은 아니지만, 차이를 봐야겠죠?
넘어가겠습니다.
기억나시나요? 'transition-timing-function'의 많은 속성들..
transition을 미리 공부하신 분들 한정으로 다행히 animation-timing-function도 동일합니다!
그렇다는 말은 따로 공부할 필요가 없다는 뜻이겠죠.
우선 어떤 속성이 있는지는 기재하겠습니다.
animation-timing-function: ease | linear | ease-in | ease-out | ease-in-out | step-start | step-end | steps( n, start | end ) | cubic-bezier( n, n, n, n ) | initial | inherit;
처음 보시는 분들이라면 cubic-bezier가 뭔지 steps가 뭔지.. 어려우실텐데
여기서 transition-timing-function을 찾아보시길 바랍니다!
절대 귀찮아서가 아닙니다.
같은 내용을 또 적는건 중복이기 때문에, 정보의 질을 위해서 그런겁니다 암튼
그래도 차이는 직접 봐봐야 겠죠.
cubic-bezier와 steps의 예시는 여러 이유로 생략하겠습니다! 이 부분도 위에 링크를 걸어둔 글에서 확인해주세요.
어때요? 차이가 보이시나요?
어떤 움직임이 어느 요소에 알맞는지 판단하고 적용하면 되겠죠!
이것 또한 어렵지 않습니다.
몇 초 동안 애니메이션을 멈출 것이냐! 이런 설정인데요.
우선 어떤 값을 넣을 수 있는지 봐야겠죠.
animation-delay: time | initial | inherit;
delay의 기본 값은 0s이고, 단위는 초(s), 1/1000초(ms)를 사용합니다.
time과 똑같죠? 맞습니다. 저도 위에서 설명 복붙해왔어요.
직접 봐봅시다.
여기서 주의 할 점은 제가 'animation-iteration-count'을 infinite로 해두었기에 무한으로 반복하는 애니메이션인데요.
무한이 아니더라도, 제한된 횟수가 있더라도 delay는 처음에만 적용된다는 점! 입니다.
드디어 처음보는게 나오네요.
사실 바로 앞에서 언급한 속성입니다. 어느정도 눈치채셨겠죠.
바로 애니메이션을 몇번이나 반복할지 정하는 속성입니다!
animation-iteration-count: number | infinite | initial | inherit;
정확히 어디까지 진행하는지 보기 위해 animation-timing-function를 'linear'로 설정했습니다.
근데 아마 글을 전부 읽으면서 내려오셨다면 4개중 앞의 3개는 멈춰있을 겁니다..
감사합니다. 그만큼 제 글을 꼼꼼히 읽으셨다는 거겠죠.
당황하지 않고 우측 하단의 'Rerun'을 클릭해 줍시다!
중요하게 볼 점은 정확히 해당 퍼센트 만큼 진행한다는 점!
그리고 끝이 났다면 초기 위치로 부드럽게 이동이 아닌 한순가에 팍..! 이동한다는 점 입니다.
전까지도 너무 쉬운 느낌이었죠?
이번에도 어려운 건 아닙니다. 재밌을 겁니다.
direction. 개발자 분들이라면 네이밍 할 때 한번 쯤은 써본 단어일 겁니다.
말그대로 애니메이션의 방향을 정하는데요.
들어갈 수 있는 속성은 다음과 같습니다.
animation-direction: normal | reverse | alternate | alternate-reverse | initial | inherit;
순방향..? 역방향? 어려운 말은 아니지만 글로 보기만 해서는 이해가 안갈 수 있죠.
그럼 역시 이번에도 직접 해봅시다.
0부터 400까지 편도로 가는 애니메이션이니 어렵지 않게 normal과 reverse를 이해할 수 있을 겁니다.
이것이 번갈아가는 alternate는 말 할것도 없고.
그러면 이건 어떨까요? 편도가 아니라 0과 200px을 왕복으로 움직이는 애니메이션입니다.
엥? 뭐지..? 타이밍이 다르기 하지만 방향 상관없이 같은 움직임을 하잖아..? 라는 생각이 가장 먼저든다면 정상입니다!
이유를 바로 생각해낸다면 천재니 개발자를 평생 직업으로 삼으십쇼.
위 처럼 나타내는 첫번째 이유는 0-200px-0 순서로 이동하기 때문에 순방향이든 역방향이든 움직이는 방향은 같을 겁니다.
근데 타이밍은 왜 다를까요?
바로 'animation-timing-function'에는 기본적으로 'ease' 속성이 적용되어 있기 때문!
ease의 속도의 변화를 그래프로 나타내면 다음과 같습니다.
출처: 내가 쓴 글 'CSS로 애니메이션을? Transition을 써보자!'
그래프를 보니 감이 오나요?
당연히 그래프가 중심을 기점으로 대칭이 아니기 때문에 순방향으로 가는 속도와 역방향으로 가는 속도의 차이가 날 수 밖에 없죠.
만약 믿기지 않으신다면 'animation-timing-function'의 값을 'linear'로 설정하고 실행해보세요.
아주 재밌는 결과가 나올 겁니다.
믿기시면 안하셔도 됩니다.
개인적으로 어렵다고 느낀 속성이었습니다.
간단히 말하자면 어떻게 시작할건지 끝난 뒤는 어떻게 될건지 설정하는 속성입니다.
우선 어떤 값이 들어가는지 봅시다.
animation-fill-mode: none | forwards | backwards | both | initial | inherit;
복잡하죠. 어떻게 돌아가는지 직접 확인해보고 하나하나 뜯어봅시다.
이번 속성은 'animation-iteration-count'을 'infinite'로 할 시 제대로 차이를 확인 할 수 없습니다.
때문에.. 한번에 차이를 캐치하지 못하셨다면 우측 하단의 Rerun을..! 양해 부탁드립니다.
기본적인 설정을 설명하자면, 4초동안 실행하며 기본 위치는 left:0 입니다.
그리고 @keyframes에 설정된 초기 위치는 left:200px, 종료 위치는 left:400px 입니다.
마지막으로 delay는 2초를 줬네요.
우선 delay 동안의 요소의 위치를 보면 초기 위치를 키프레임 기준으로 설정하는 backwards와 both만 left:200px로 위치한 것을 볼 수 있습니다.
물론 delay가 끝나고 시작할 때는 다같이 left:200px에서 출발하죠.
이제는 끝나고를 볼까요? 끝나고 위치를 유지하는 forwards와 both만 종료 키프레임 위치로 유지하고 나머지는 초기 위치로 돌아간 모습을 확인 할 수 있네요.
여기서 놓치기 쉬운 부분은 초기 위치를 키프레임 기준으로 삼은 backwards도 애니메이션이 종료되면 초기 키프레임이 아니라 순수히 자기 요소의 초기 값으로 돌아간다는 점 입니다.
어떤가요? 말이 어렵지 직접 보고나니 이해가 쏙쏙 되지 않나요?
아니면 죄송합니다. 설명을 쉽게 못한 제 탓입니다.
무튼 forwards와 backwards를 잘 이해한다면 both도 문제 없이 이해할 수 있을 겁니다.
사실 아직 저도 이 속성을 어디에 써먹어야 할지 감이 잡히지 않습니다만.. 확실한건 delay가 있거나 키프레임 설정 값과 요소의 설정 값이 다를 때..? 활용할 수 있을 것 같습니다.
드디어 쉬운게 나왔습니다.
play state라.. 말그대로 재생 상태를 결정합니다.
animation-play-state: running | paused | initial | inherit;
이 속성을 확인하기 위해선 살짝의 컨트롤 UI가 필요하겠네요.
잘되나요?
코드는 오늘 봤던 거중 가장 복잡하지만.. 물론 상대적으로
개념 자체는 쉬운편에 속해서 추가적인 설명이 필요 없을 것 같습니다.
애니메이션을 사용자에게 컨트롤 할 수있게 해야한다! 싶은 상황에 활용할 수 있겠네요.
드디어 마지막 속기형이네요.
animation: name | duration | timing-function | delay | iteration-count | direction | fill-mode | play-state | initial | inherit;
끝이 보이지 않는 속성들에.. 머리가 아픈듯 하지만 걱정 없습니다. 저희는 전부 학습했잖아요?
transition과 마찬가지로 같은 단위 값을 가지는 'duration'과 'delay'의 순서만 잘 지켜준다면 아무렇게나 적어도 상관없습니다.
하지만! 위에 나온 순서를 권장한다고 하니, 지켜서 나쁠건 없겠죠?
자고로 코드는.. 다른 누군가와 함께 작성하는거니까요!
끝난 줄 알았나요?
아직 다루지 않은 친구가 한명 있습니다. 바로 keyframes!
사실 주구장창 써왔지만 제대로된 설명이 없어서 답답했던 분도 있을 겁니다.
근데 설명을 들으면 실망할지도 몰라요. 정말 쉬운 친구거든요.
@keyframes size {
/* from === 0% */
from {
width: 100px;
height: 100px;
}
30% {
width: 200px;
height: 200px;
}
70% {
width: 300px;
height: 300px;
}
/* to === 100% */
to {
width: 400px;
height: 400px;
}
}
어때요? 설명이 필요 없죠??
그냥 구간 별로 속성을 설정할 수 있다는 점과, from과 to는 각각 0%, 100%를 의미한다는 것.
이 것만 알면 됩니다.
여기서 문제~
위 코드에서 70%의 width를 설정하지 않으면 어떻게 될까요?
좀 더 극적인 효과를 위해 까짓거 30%에도 width를 빼봅시다!
정답은 아래를 보시죠!
어떤가요? 생각했던 대로 움직이나요?
참고로 저는 width가 70%까지 100px를 유지할 줄 알았습니다.
하지만 이게 웬걸.. height가 어떻게 변하든 자기 갈 길 가버리네요?
맞습니다. 여기서 알 수 있는건 속성 값을 진행 분기마다 적어주지 않는다면, 전에 값을 유지하는 것이 아니라 다음 값을 향해 나아간다는 점 입니다.
이 부분 유의하시길!
진짜 끝난 줄 알았나요?
아직입니다. 뭔가 찝찝하지 않나요? 찝찝하진 않겠죠.
근데 뭔가 이상합니다.
저희가 animation-name을 통해 keyframes와 연결을 해줬는데, 애초에 keyframes이 하나만 있으면 이걸 연결해 줄 필요가 있나? 싶습니다.
물론 애니메이션 요소가 한 개만 있다고 가정하고요.
그렇다면..? 이름을 여러개 하면, 여러개의 keyframes을 설정할 수 있지 않을까..? 맞습니다. 바로 보시죠.
두개의 keyframes에 각각의 이름을 설정하고, animation 속기형 선언에서 쉼표(,)를 기준으로 구분하여 속성을 부여했습니다.
transition에서 각각의 property마다 부여하는 속성을 쉼표(,)로 구분하던 것과 유사하죠?
이렇듯 하나의 요소 안에서 분기가 다른 keyframes을 설정하여 더욱 복잡한 애니메이션도 구현할 수 있습니다!
Transition에 이어 Animation까지 정리해봤습니다.
그럼 두가지는 어떤 차이가 있을까? 다음과 같습니다.
Transition | Animation | |
---|---|---|
시간 함수 | 가능 | 가능 |
지연 재생 | 가능 | 가능 |
자동 실행 | 불가 | 가능 |
재생/멈춤 제어 | 불가 | 가능 |
반복 재생 | 불가 | 가능 |
동적 HTML | 불가 | 가능 |
아니..? 이게 뭐람. Transition 이거.. 완전 못하는거 투성이잖아?
라고 생각하실수도 있지만, Transition과 Animation은 쓰임새가 다를 뿐이지 어느게 더 좋고 나쁘고가 없습니다.
예를 들어 마우스를 hover하여 색상을 변하는 애니메이션을 구현하고 싶을 때, Transition은 CSS 몇줄만 추가하면 되지만, Animation은 JS까지 조작하며 DOM을 통해 style을 수정해줘야 합니다.
반대로 자동적으로 모션을 취해야 하는 부분은 Transition보다 Animation을 활용할 수 있겠죠?
결론은! 어느 애니메이션이든 구현하기 위해선 둘다 잘 알고 적재적소에 잘! 사용해야 한다는 점입니다.
Animation을 공부해 봤습니다.
속성이 많아서 중간중간 Transition과 겹쳤던 부분은 생략을 하면서 작성했는대도 꽤 글이 길어졌네요.
거의 없겠지만 끝까지 읽어주신 분들에게 감사할 따름입니다.
원래는 그리니의 모션을 어떤걸 설정해줘야 할까 고민하고 그에대한 설계도 정리하여 작성하려 했으나, 글도 너무 길어질거 같기도 하고.... 다른 이유는 더 이상 없습니다.
사실 제가 너무 힘이드네요.. 😂😂😂😂😂😂😂😂
아직 글쓰는 노하우가 부족해서 인지, 최대한 퀄리티 있는 글을 쓰려고 노력해서인지 글 한편 작성하는데 시간이 너무 많이 소요됩니다.
흠.. 언젠간 늘겠죠 뭐
이번 글을 기점으로 말투를 평어체에서 경어체로 바꿔보았는데,, 글쓰기가 훨씬 수월해 진 것 같습니다.
진짜 말하듯이 적으니 술술 적히기도 하고요.
근데 반말인 평어체에서 경어체로 바꾸니 글이 더 길어진 것 같기도 하고,, 그래서 시간이 오래걸렸나?
무튼 학습한 Transition과 Animation을 적절히 섞어서 그리니 애니메이션 설계로 돌아오겠습니다.
감사합니다.