잔상(그림자) 애니메이션을 만들어보자!

gicomong·2021년 5월 29일
10

css animation

목록 보기
19/21
post-thumbnail

이번 시간에는 잔상을 남기는 비행기를 만들어보자!

1. preview

!codepen[kumjungmin/embed/oNZGaWN?height=498&theme-id=dark&default-tab=css,result]



2. 코드 분석

1) html

  • cloud는 배경으로 사용될 구름 이미지이며, 총 2개를 준비한다.(2개인 이유는 scss에서 알 수 있음)
  • shadow-box는 비행기의 잔상, 그러니까 그림자를 담기 위한 공간이다.
  • shadow-boxclass="shadow"img를 추가할 건데, 이건 js로 추가할 예정이다.
  • airplane는 메인 이미지인 비행기이다 ✈️
<div class="frame">
  <div class="center">
    <img class="cloud" src="" />
    <img class="cloud" src="" />
    <div class="shadow-box"></div>
    <img class="airplane" src=""/>
  </div>
</div>



2) js

  • 앞서 html파트에서 말했듯이, shadow-box에 자식으로 이미지 태그를 추가할 것이다.
  • 이 이미지 태그들은 airplane, shadow클래스를 가지며, 비행기의 그림자(잔상)역할을 한다.
const parent = document.querySelector('.shadow-box');  //[1]
const shadow = 5;

for (let i=0; i<shadow; i++) {                //[2]
  const img = document.createElement('img');  //[3]
  img.src = "...";                            //[4] 비행기 이미지 경로
  img.classList.add('airplane');              //[5]
  img.classList.add('shadow');                //[5]
  parent.appendChild(img);                    //[6]
}

[1] 먼저, document.querySelectorshadow-box을 가져온다.
[2] 우리는 5개의 그림자을 만들 것이기에 for문을 사용한다.
[3] document.createElement(img)으로 img 요소를 생성한다.
[4] img.src = "이미지경로"를 사용해 이미지 요소에 이미지 경로를 추가한다.
[5] dom.classList.add('className')으로 클래스를 정의한다.
[6] 마지막으로 parentDom.appendChild(dom)을 사용해 이미지 요소를 shadow-box의 자식으로 추가한다.

앞선 과정을 거치면, 총 5개의 이미지 요소가 shadow-box의 자식으로 추가된다!




3) scss

(1) 구름에는 어떤 scss를 적용할까?

A. 구름 이미지는 왜 2개일까?

구름 배치에 앞서, 우리는 왜 2개의 구름 이미지를 쓰는지 알아보자!

  • 그 이유...! 바로 부드러운 구름 애니메이션을 위해서이다.
  • 구름 이미지에 적용하는 애니메이션은 단순하게 위->아래로 이동하는 애니메이션이다.
  • 만약, 구름 이미지 하나에만 이 애니메이션을 주면, 아래 사진처럼 구름이 화면을 채우지 않는 순간이 온다.
    (저 빨간 박스처럼 구름이 비게 됨ㅠ)


  • 하지만 2개의 구름이미지와 각기 다른 애니메이션 지연 시간을 주면 화면을 계속 채우게 할 수 있다.

|초기 위치|애니메이션 시|
|---|---|
|||
|- 처음에는 화면 밖에서 시작한다.
- 화면 밖에서 시작하게 하면, 애니메이션이 끝나고 초기 위치로 돌아가는 액션이 안보여서 자연스럽다.|- 구름2에는 애니메이션 지연 시간을 준다.
- 그러면, 구름1의 애니메이션이 끝나고 초기 위치로 돌아가는 동안,
구름2 애니메이션이 진행되므로 계속 구름이 이동하는 것처럼 보인다.|

이제 이 설명을 코드로 확인해보자 :)


B. 구름 배치시키기

.cloud {
  position: absolute;      //[1]
  width: 400px;
  transform: translate(-50%, -150%);         //[2]
}
  • [1] positionabsolute로 설정하여, 다른 요소들과 겹칠 수 있게 한다.
  • [2] transform: translate(x, y)로 초기 위치를 설정한다.

C. 구름 이동 애니메이션 만들기

  • @keyframes를 사용해 위 -> 아래로 이동하는 애니메이션을 만든다.
@keyframes cloudMoving { 
  100% {
    transform: translate(-50%, 50%);  //translate(x, y)
  }
}

D. 구름 이동 애니메이션 적용하기

  • 그 다음, cloud에 앞서 생성한 cloudMoving 애니메이션을 적용한다.
.cloud {
  ...
  animation: cloudMoing 5s linear infinite;  
//animation: 애니메이션명, 재생시간, 부드럽게재생, 무한재생
}
  • 앞서 설명에 따르면, 2번째 구름 이미지에 애니메이션 지연을 준다고 했다.
  • 두 번째 cloudanimation-delay를 주자!
  • 이때, A:nth-of-type(n)을 사용하면 A의 n번째 형제인 요소에 접근 할 수 있다.
    (단, 같은 부모 & 같은 태그여야함)
.cloud:nth-of-type(2) {   //2번째 cloud에 접근
  animation-delay: 2s;
}



(2) 비행기&비행기 그림자에는 어떤 scss를 적용할까?

비행기와 그림자는 같은 이미지이지만, 차이점은 바로 투명도와 애니메이션 지연시간임을 명심하자!

A. 비행기&그림자 배치를 하자!

  • 메인 비행기와 여러 비행기 그림자가 겹칠 수 있게 position: absolute를 설정한다.
.airplane {
  width: 100px;    //크기
  height: 100px;   //크기
  position: absolute;  
}

B. 비행기&그림자 이동 애니메이션 만들기

  • 비행기&그림자에는 좌<->우로 움직이는 애니메이션을 주고자한다.
  • translate(x, y)를 사용해 0%일 때 좌측 끝, 100%일 때는 우측 끝으로 이동하게 하자.
    rotate의 경우, 비행기 이미지 자체가 기울어져 있어 정면을 향하게 하려고 적용한 것
@keyframes playing{ 
  0% {  //애니메이션 시작 시점
    transform: translate(-180px, 0) rotate(-45deg);   //왼쪽 끝
  }
  100% { //애니메이션 끝날 시점
    transform: translate(80px, 0) rotate(-45deg);    //오른쪽 끝 
  }
}

C. 비행기&그림자에 이동 애니메이션 적용하기

.airplane {
  ...
  transform: translate(-180px, 0) rotate(-45deg);       //[1]
  animation: playing 5s ease-in-out alternate infinite; //[2]
//animation: 애니메이션명, 재생시간, 천천히시작&천천히끝내기, 애니메이션방향, 무한재생
  
}
  • [1] 비행기&그림자의 초기 위치를 설정한다.
  • [2] 앞서 생성한 playing 애니메이션을 적용한다.



(2) 비행기 그림자(잔상)에 추가 애니메이션 설정을 하자!

A. 잠깐, 여기서 쓰인 scss 문법은 뭐지?

비행기 그림자(잔상)에 애니메이션을 주기에 앞서, 여기서 scss의 문법을 알고 시작하자.

$variable
: 변수를 만들 수 있다.
: 사용할 때는 $variable 그대로 쓰면 된다.

$variable : value;    

@for $i from 1 through $total
: 반복문이다.
: 범위는 1 <= i <= total 이다.
: 속성이 아닌 요소 이름에 쓸 때는 #{$i}로 쓴다.
: 속성에서 쓸 때는 $i로 쓰면 된다.

@for $i from 1 through $shadow {
  .airplane.shadow:nth-of-type(#{$i}) {
    opacity: $i / 10;
  } 

B. 그림자에 애니메이션을 적용하자!

  • 그림자에는 서로 다른 애니메이션 지연시간, 투명도를 줘야한다.
  • animation-delay를 사용해, 그림자에 다른 애니메이션 지연 시간을 준다.
  • opacity를 주어, 메인 비행기 이미지 이외에는 투명도를 주어 잔상처럼 보이게 한다.
$shadow : 5;    //요소 개수
$delay : 0.3;   //기준 지연시간
@for $i from 1 through $shadow {
  .airplane.shadow:nth-of-type(#{$i}) {
    animation-delay: $delay - ($i / 17) + s;  
    opacity: $i / 10;
  }
}





출처
아래 출처로 이동하면 더 많이 알 수 있다고? 좋다 좋아~ 👏👏

profile
⚠ 이 블로거는 퇴근 후 극심한 피로감 + 강렬한 휴식 욕구로 인해 일주일 이상 포스팅이 없을 수 있습니다. 하지만 항상 좋은 내용을 담고자 합니다🙇🏼

관심 있을 만한 포스트

0개의 댓글