프밍/CSS

DAY 28. CSS 애니메이션

태영(泰伶) 2022. 12. 30. 00:08

CSS 애니메이션 사용하면 자바스크립트를 사용하지 않고도

요소에 애니메이션을 추가할 수 있다..!!!

 

animation 속성은 특정 지점에서 스타일을 바꾸면서 애니메이션을 만든다.

그렇게 스타일이 바뀌는 바로 그 지점이 keyframe키프레임이다.

 

animation 관련 속성 요약
종류 설명
@keyframes 애니메이션이 바뀌는 지점 지정.
animation-name 복수의 애니메이션을 구별하기 위한 이름 설정.
animation-duration 애니메이션의 실행 시간 지정.
animation-delay 애니메이션의 시작 시간 지연을 지정.
animation-direction 애니메이션이 끝난 다음, 다시 실행할 때
처음과 같은 방향으로 시작할지, 역방향으로 시작할지 지정.
animation-iteration-count 애니메이션 반복 횟수 지정.
animation-timing-function 애니메이션의 진행 속도를 지정.
ex, 처음엔 빠르다가 점점 느리게, 처음엔 느리다가 점점 빠르게 등등 
animation 위의 모든 속성을 한꺼번에 묶어서 지정.

 

1. 애니메이션 지점&이름 설정: @keyframes, animation-name

     1) 애니메이션 지점 설정: @keyframes

     애니메이션으로의 시작 지점, 끝 지점과 같이 스타일이 바뀌는 그 지점, 즉 keyframe을 정의할 때

     @keyframes 속성을 이용한다.

@keyframes 이름 {
   선택자 {
      스타일
   }
}

     위와 같이 사용하는데,

     '이름': 아래에서 다루게 되는 animation-name 속성에 쓴 속성값을 넣는 곳.

     '선택자': 스타일 속성값이 바뀌는 지점.

     이다.

 

 

     그러니까,

     아래 동영상과 같이 어떤 요소의 움직임이

     - 시작하는 지점

     - 중간에 꺾이는 지점

     - 끝나는 지점

     이렇게 세 개 지점 모두가 keyframe이 될 수 있는 것이다.

아직 실력이 미천해서 코딩으로는 아직 이런 애니메이션을 만들기 어려워서 만만한 PPT를 이용했다..ㅎ....

     어떤 애니메이션을 만들 때, 이렇게 애니메이션이 변하는 지점이

     (시작과 끝을 제외하고도) 더 있을 수도 있지만, 없는 경우도 빈번하다.

     그러한 경우에는

     '0% 지점에서, 100% 지점에서'와 같이 구체적으로 지정하는 대신,

     from ... to ...를 사용하기만 해도 된다.

@keyframes 이름 {
   from { blah blah.... }
   to { blah blah.... }
}

     그래서 위와 같은 경우,

     from과 to가 선택자의 위치에 있게 되는 셈이다.

 

 

     2) 애니메이션 이름 설정: animation-name

     애니메이션을 @keyframes으로 지정할 때, 어떤 애니메이션을 사용할지 구분하는 데 사용한다.

     어떠한 기능을 한다기보다는 코드의 가독성을 높이는 느낌이다.

     그래서 보통은 이름을 지정할 때

     애니메이션이 모양을 변화(transform)시키는지

     회전(rotate)시키는지

     등등

     그 역할을 유추할 수 있는 짧은 단어로 지정한다.

.blah {
     animation-name: blahblah;
}

위와 같이 작성했다면,

@keyframes blahblah {
   from { 속성1: 속성값1; }
   to { 속성2: 속성값2; }
}

와 함께 쓰이게 된다.

(animation-name의 속성값 = @keyframes 옆에 쓰이는 이름)

 

 

 

2. 애니메이션 실행 시간 지정: animation-duration

애니메이션을 얼마의 시간동안 재생할 것인지 설정한다.

default값은 0이고, 단위는 초(s), 밀리초(ms)가 쓰인다.

#blah {
   animation-duration: _s;
}

언더바 부분에 숫자 넣으면 된다.

 

예제 1.

<!DOCTYPE html>
   <html lang="ko">
      <head>
         <meta charset="UTF-8" />
         <title>animation - @keyframes, name, duration</title>
         <style>
            #container {
               width: 500px;
               margin: 20px auto;
            }
            .box {
               width: 100px;
               height: 100px;
               float: left;
               margin: 50px;
            }
            #box1 {
               background-color: #4cff00;		/* 연두색 박스 */
               border: 1px solid transparent;		/* 1px짜리 투명한 실선 테두리 */
               animation-name: shape;			/* 애니메이션 이름: shape */
               animation-duration: 3s;			/* 애니메이션 실행 시간: 3초 */
            }
            #box2 {
               background-color: #8f06b0;		/* 보라색 박스 */
               border: 1px solid transparent;		/* 1px짜리 투명한 실선 테두리 */
               animation-name: rotate;			/* 애니메이션 이름: rotate */
               animation-duration: 3s;			/* 애니메이션 실행 시간: 3초 */
            }
            @keyframes shape {				/* shape 애니메이션 정의 */
               from {
                  border: 1px solid transparent;	/* 1px짜리 투명한 실선 테두리에서 */
               }
               to {
                  border: 1px solid #000;		/* 검정색 테두리로 변경 */
                  border-radius: 50%;			/* 테두리를 둥글게 변경 */
               }
            }
            @keyframes rotate {				/* rotate 애니메이션 정의 */
               from {
                  transform: rotate(0deg);		/* 0도에서 시작해서 */
               }
               to {
                  transform: rotate(45deg);		/* 45도까지 회전하기 */
               }
            }
         </style>
      </head>
      <body>
         <div id="container">
            <div class="box" id="box1"></div>
            <div class="box" id="box2"></div>
         </div>
      </body>
   </html>

 

 

 

 

3. 애니메이션 시작 시간 지연: animation-delay

애니메이션의 시작 시간을 늦출 때 사용된다.

animation-duration에서와 마찬가지로 기본값은 0이며, 단위는 초(s), 밀리초(ms)를 사용할 수 있다.

 

(내가 만든) 예시 1.

<!DOCTYPE html>
   <html lang="ko">
      <head>
         <meta charset="UTF-8" />
         <title>animation - @keyframes, name, duration, delay</title>
         <style>
            #container {
               width: 500px;
               margin: 20px auto;
            }
            .circle {
               width: 100px;
               height: 100px;
               border: 1px solid transparent;
               border-radius: 50%;
               float: left;
               margin: 50px;
            }
            #circle1 {
               background-color: #ece0d1;		/* 연한 베이지색 */
               animation-name: color-gradation;		/* 애니메이션 이름: color-gradation */
               animation-duration: 5s;			/* 애니메이션 실행 시간: 5초 */
               animation-delay: 3s;			/* 애니메이션 시작 지연 시간: 3초 */
            }
            @keyframes color-gradation {		/* color-gradation 애니메이션 정의 */
               0% {
                  background-color: #ece0d1;
               }
               25% {
                  background-color: #dbc1ac;
                  width: 150px;
                  height: 150px;
               }
               50% {
                  background-color: #967259;
                  width: 200px;
                  height: 200px;
               }
               75% {
                  background-color: #634832;
                  width: 150px;
                  height: 150px;
               }
               100% {
                  background-color: #38220f;
                  width: 100px;
                  height: 100px;
               }
            }
         </style>
      </head>
      <body>
         <div id="container">
            <div class="circle" id="circle1"></div>
         </div>
      </body>
   </html>

 

애니메이션이 변하는 지점을 %로 여러 개 지정할 수 있다.

 

 

 

4. 애니메이션 방향 지정: animation-direction

애니메이션은 보통 @keyframes에서 지정한 from → to 방향으로 이루어진다.

그러나, animation-direction 속성으로 그 방향을 바꿀 수 있다.

animation-direction: normal | reverse | alternate | alternate-reverse ;

종류 설명
animation-direction: normal; 애니메이션 진행 방향이 from → to. default값임.
animation-direction: reverse; 애니메이션 진행 방향이 to → from.
animation-direction: alternate; 애니메이션 진행 방향이
  • 홀수 번째: normal처럼 from → to
  • 짝수 번째: reverse처럼 to → from
animation-direction: alternate-reverse; 애니메이션 진행 방향이
  • 홀수 번째: normal처럼 to → from
  • 짝수 번째: reverse처럼 from → to

 

(내가 만든) 예시 2.

<!DOCTYPE html>
   <html lang="ko">
      <head>
         <meta charset="UTF-8" />
         <title>animation-direction</title>
         <style>
            #container {
               width: 100%;
               margin: 20px auto;
            }
            .oval {
               width: 150px;
               height: 75px;
               border: 1px solid transparent;
               border-radius: 50%;
               float: left;
               margin: 50px;
            }
            div {
               text-align: center;
               letter-spacing: 30px;
               line-height: 75px;
            }
            #oval1 {
               background-color: #ffb3ba;		/* 파스텔 빨강색 */
               animation-name: rotate;			/* 애니메이션 이름: rotate */
               animation-duration: 5s;			/* 애니메이션 실행 시간: 5초 */
               animation-direction: normal;		/* 애니메이션 진행 방향: from → to */
            }
            #oval2 {
               background-color: #ffffba;		/* 파스텔 노랑색 */
               animation-name: rotate;			/* 애니메이션 이름: rotate */
               animation-duration: 5s;			/* 애니메이션 실행 시간: 5초 */
               animation-delay: 5s;			/* 애니메이션 시작 지연 시간: 5초 */
               animation-direction: reverse;		/* 애니메이션 진행 방향: to → from */
            }
            #oval3 {
               background-color: #baffc9;		/* 파스텔 초색 */
               animation-name: rotate;			/* 애니메이션 이름: rotate */
               animation-duration: 5s;			/* 애니메이션 실행 시간: 5초 */
               animation-delay: 10s;			/* 애니메이션 시작 지연 시간: 10초 */
               animation-direction: alternate;		/* 애니메이션 진행 방향: from → to, to → from */
               animation-iteration-count: 2;		/* 애니메이션 반복 횟수: 2번 */
            }
            #oval4 {
               background-color: #bae1ff;		/* 파스텔 파랑색 */
               animation-name: rotate;			/* 애니메이션 이름: rotate */
               animation-duration: 5s;			/* 애니메이션 실행 시간: 5초 */
               animation-delay: 20s;			/* 애니메이션 시작 지연 시간: 20초 */
               animation-direction: alternate-reverse;	/* 애니메이션 진행 방향: to → from, from → to */
               animation-iteration-count: 2;		/* 애니메이션 반복 횟수: 2번 */
            }
            @keyframes rotate {				/* rotate 애니메이션 정의 */
               from {
                  transform: rotate(0deg);
               }
               to {
                  transform: rotate(360deg);
               }
            }
         </style>
      </head>
      <body>
         <div id="container">
            <div class="oval" id="oval1">&nbsp;L&nbsp;R&nbsp;</div>
            <div class="oval" id="oval2">&nbsp;L&nbsp;R&nbsp;</div>
            <div class="oval" id="oval3">&nbsp;L&nbsp;R&nbsp;</div>
            <div class="oval" id="oval4">&nbsp;L&nbsp;R&nbsp;</div>
         </div>
      </body>
   </html>

 

 

 

5. 애니메이션 반복 횟수 지정: animation-iteration-count

* iteration: (계산·컴퓨터 처리 절차의) 반복

 

애니메이션을 반복해서 보여줘야 할 때, 그 반복 횟수를 정하는 속성이다.

단어에 무슨 역할인지 그 의미가 다 나와있다.. 영어 실력이 짧은 나는 몰랐을 뿐이고..ㅠㅠ

animation-iteration-count: 숫자 | infinite ;

종류 설명
animation-iteration-count: 숫자; 애니메이션이 숫자(횟수)만큼 반복됨.
animation-iteration-count: infinite; 애니메이션이 무한 반복됨.

 

사실 위에서 animation-direction 예시 만들 때 animation-iteration-count도 사용했다. 위의 예시 참고..ㅎㅎ

 

 

 

6. 애니메이션 속도 곡선 지정: animation-timing-function

 

종류 설명
animation-timing-function: linear; 시작부터 끝까지 똑같은 속도로 진행함.
animation-timing-function: ease; 처음엔 천천히 시작함 → 점점 빨라짐 → 마지막엔 천천히 끝남.
default값.
animation-timing-function: ease-in; 느리게 시작함.
animation-timing-function: ease-out; 느리게 끝냄.
animation-timing-function: ease-in-out; 느리게 시작하고 느리게 끝냄.
animation-timing-function: cubic-bezier(x1, y1, x2, y2); 베지에 함수를 정의해서 사용함.
0 ≤ x1, y1, x2, y2  1

 

(내가 만든) 예시 3.

<!DOCTYPE html>
   <html lang="ko">
      <head>
         <meta charset="UTF-8" />
         <title></title>
         <style>
            #container {
               width: 300px;
               height: 300px;
               border-radius: 20%;
               background-color: #bdd9a3;
               position: relative;
               top: 60px;
               left: 60px;
            }
            .heart {
               width: 50px;
               height: 50px;
               background-color: #56a20d;
               position: relative;
               transform: rotate(45deg);
               border-radius: 10%;
               top: 60px;
               left: 60px;
            }
            .heart::before {
               content: "";
               width: 50px;
               height: 50px;
               position: absolute;
               left: -50%;
               border-radius: 50%;
               background-color: #56a20d;
            }
            .heart::after {
               content: "";
               width: 50px;
               height: 50px;
               position: absolute;
               top: -50%;
               border-radius: 50%;
               background-color: #56a20d;
            }
            #top {
               position: relative;
               top: 85px;
               left: 128px;
               transform: rotate(45deg);
               animation-name: rotate1;
               animation-duration: 3s;
               animation-delay: 5s;
               animation-timing-function: ease-in-out;
               animation-iteration-count: infinite;
            }
            #right {
               position: relative;
               top: 75px;
               left: 168px;
               transform: rotate(135deg);
               animation-name: rotate2;
               animation-duration: 3s;
               animation-delay: 5s;
               animation-timing-function: ease-in-out;
               animation-iteration-count: infinite;
            }
            #bottom {
               position: relative;
               top: 65px;
               left: 128px;
               transform: rotate(225deg);
               animation-name: rotate3;
               animation-duration: 3s;
               animation-delay: 5s;
               animation-timing-function: ease-in-out;
               animation-iteration-count: infinite;
            }
            #left {
               position: relative;
               top: -25px;
               left: 88px;
               transform: rotate(315deg);
               animation-name: rotate4;
               animation-duration: 3s;
               animation-delay: 5s;
               animation-timing-function: ease-in-out;
               animation-iteration-count: infinite;
            }
            @keyframes rotate1 {
               0% {
                  transform: rotate(45deg);
                  top: 85px;
                  left: 127px;
               }
               25% {
                  transform: rotate(135deg);
                  top: 125px;
                  left: 167px;
               }
               50% {
                  transform: rotate(225deg);
                  top: 165px;
                  left: 127px;
               }
               100% {
                  transform: rotate(315deg);
                  top: 125px;
                  left: 87px;
               }
            }
            @keyframes rotate2 {
               0% {
                  transform: rotate(135deg);
                  top: 75px;
                  left: 167px;
               }
               25% {
                  transform: rotate(225deg);
                  top: 115px;
                  left: 127px;
               }
               50% {
                  transform: rotate(315deg);
                  top: 75px;
                  left: 87px;
               }
               100% {
                  transform: rotate(400deg);
                  top: 35px;
                  left: 127px;
               }
            }
            @keyframes rotate3 {
               0% {
                  transform: rotate(225deg);
                  top: 65px;
                  left: 127px;
               }
               25% {
                  transform: rotate(315deg);
                  top: 25px;
                  left: 87px;
               }
               50% {
                  transform: rotate(405deg);
                  top: -15px;
                  left: 127px;
               }
               100% {
                  transform: rotate(495deg);
                  top: 25px;
                  left: 167px;
               }
            }
            @keyframes rotate4 {
               0% {
                  transform: rotate(315deg);
                  top: -25px;
                  left: 87px;
               }
               25% {
                  transform: rotate(405deg);
                  top: -65px;
                  left: 127px;
               }
               50% {
                  transform: rotate(495deg);
                  top: -25px;
                  left: 167px;
               }
               100% {
                  transform: rotate(585deg);
                  top: 15px;
                  left: 127px;
               }
            }
         </style>
      </head>
      <body>
         <div id="container">
            <div class="heart" id="top"></div>
            <div class="heart" id="right"></div>
            <div class="heart" id="bottom"></div>
            <div class="heart" id="left"></div>
         </div>
      </body>
   </html>

 

하... 갑자기 왜 하필 하트 모양에 꽂혀가지고...ㅋㅋㅋㅋ 아무튼 무한회전 성공이다!

 

 

 

7. 애니메이션 속성 한꺼번에 표기: animation

위에서 연습한 모든 애니메이션 속성을 한꺼번에 animation으로 표현할 수 있다.

animation: <animation-name> | <animation-duration> | <animation-timing-function> | <animation-delay> | <animation-iteration-count> | <animation-direction> ; 

중요한 것은 animation-duration을 꼭!꼭!꼭! 지정해주어야 한다는 점이다.

(왜냐면 기본값이 0이기 때문에 지정하지 않으면 아예 실행이 안 된다..ㅋㅋㅋ)

 

그래서,

.box {
   animation-name: moving;
   animation-duration: 3s;
   animation-timing-function: ease-in;
   animation-direction: alternate;
   animation-iteration-count: infinite;
}

││

.box {
   animation: moving 3s alternate infinite ease-in;
}

 

위의 코드 두 가지가 같은 의미이다.

 

 

 

예제 2.

<!DOCTYPE html>
   <html lang="ko">
      <head>
         <meta charset="UTF-8" />
         <title>Animation</title>
         <style>
            .box {
               width: 100px;
               height: 100px;
               margin: 60px auto;
               animation: rotate 1.5s infinite, background 1.5s infinite alternate;
            }
            @keyframes rotate {
               from {
                  transform: perspective(120px)
                             rotateX(0deg)
                             rotateY(0deg);
               }
               50% {
                  transform: perspective(120px)
                             rotateX(-180deg)
                             rotateY(0deg);
               }
               to {
                  transform: perspective(120px)
                             rotateX(-180deg)
                             rotateY(-180deg);
               }
            }
            @keyframes background {
               from {
                  background-color: red;
               }
               50% {
                  background-color: green;
               }
               to {
                  background-color: blue;
               }
            }
         </style>
      </head>
      <body>
         <div class="box"></div>
      </body>
   </html>