이전 애니메이션 | 마우스 호버 시 따라다니는 언더라인 만들기
미리보기
이번 포스트를 따라오시면 아래와 같은 로딩 스피너를 구현하실 수 있는 능력을 얻게 됩니다. 순수 HTML/CSS 를 사용하여 구현되었고, 응용에 따라서는 각 도트가 제자리에 있는 상태에서 투명도만 조절하여 순차적으로 파도타기가 되는 애니메이션 등을 구현해보실 수 있습니다. 무엇이든 응용에 달렸습니다. 간단한 원리를 파악하시고 여러분만의 애니메이션을 구현해보세요!.
HTML
<div class="dot_wrapper">
<div class="dot" style="--i:1"></div>
<div class="dot" style="--i:2"></div>
<div class="dot" style="--i:3"></div>
<div class="dot" style="--i:4"></div>
<div class="dot" style="--i:5"></div>
<div class="dot" style="--i:6"></div>
<div class="dot" style="--i:7"></div>
<div class="dot" style="--i:8"></div>
<div class="dot" style="--i:9"></div>
<div class="dot" style="--i:10"></div>
</div>
우선 각 도트에 해당하는 요소들을 화면 상에서 수직/수평 중앙 정렬하기 위한 용도인 div에 .dot_wrapper 값으로 class 속성을 추가해줍니다.
그 뒤에 각각의 도트 역할을 하는 div 태그를 10개 정도 추가하고, 각각에 class 속성의 값으로 .dot 를 넣어줍니다. 또한, 향후 로딩 스피너가 중앙을 기준으로 360deg를 돌아가며 회전할 수 있도록 하는데 필요한 --i:1 ~ 10 이라는 사용자 정의 변수를 style 속성에 입력해줍니다.
여기 까지만 하면 더 이상 HTML 을 건드릴 필요가 없습니다. 바로 CSS 작업으로 넘어 갑시다.
CSS
CSS Reset 설정
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
우선 margin 과 padding 을 0으로 지정하여 브라우저에 기본적으로 적용된 여백을 제거해줍니다. 그 후 box-sizing 속성을 border-box 로 지정하여 콘텐츠 요소의 넓이를 계산 시 margin과 padding 의 설정값도 계산에 포함되도록 해줍니다.
.dot_wrapper 작업
그 다음에는 도트 역할을 하는 div 요소의 랩퍼 역할을 하는 div 요소를 작업해줍니다
.dot_wrapper {
width: 100%;
height: 100vh;
position: relative;
}
전체 뷰포트에 .dot_wrapper 요소가 가득차도록 width 를 100%으로 height를 100vh 으로 설정해줍니다.
그 후 position을 relative 로 지정함으로써 향후 자식 요소에 absolute 값을 position 으로 설정할 시 절대좌표의 기준점이 .dot_wrapper 가 되도록 해줍니다(지정하지 않는 경우 각 .dot 요소의 절대좌표 기준은 html 이 됩니다).
여기까지 다 하셨다면, 이제 .dot 요소들에 대한 작업으로 넘어가봅니다.
.dot 작업
class 의 값으로 dot 가 부여된 모든 div 요소들은 클래스명 그대로 도트 로딩스피너의 도트에 해당하는 역할을 합니다. 앞서 미리보기 영상의 파란색 막대기라고 보면 됩니다.
.dot {
position: absolute;
left: 50%;
top: 41%;
transform: translate(-50%, -50%) rotate(calc(var(--i) * 45deg));
transform-origin: 40px;
width: 15px;
height: 5px;
border-radius: 30px;
background: #3396ff;
animation-delay: calc(var(--i) * -2s);
animation: 1.5s infinite linear rotation;
}
도트 중앙정렬
.dot {
position: absolute;
left: 50%;
top: 41%;
transform: translate(-50%, -50%);
}
우선 도트 요소를 화면의 중앙으로 정렬하기 위해서 우선적으로 position 속성을 absolute 로 하여 현재 DOM 트리의 흐름에서 벗어나도록 설정해줍니다. 그 후 left 를 50%, top은 50% 으로 지정해주고, transform의 translate(-50%,-50%) 으로 지정하여 해당 요소들이 중앙에 정렬되도록 해줍니다.
도트 배치
.dot {
transform: translate(-50%, -50%) rotate(calc(var(--i) * 45deg));
transform-origin: 40px;
}
그 다음에는 도트를 화면의 중앙을 기준으로 360도 일정간격에 따라 도트를 위치시키기 위해 transform 의 rotate 함수를 사용하는데, 이 때 함수의 인자로 calc(var(--i) *45deg)를 입력해줍니다.
여기서 calc 는 css 에서 사용되는 계산기 같은 함수로서 전달 받은 표현식을 계산하여 그 결과를 반환해줍니다.
var() 함수의 경우에는 전달받은 사용자 정의 속성에 담긴 값을 반환해주는 역할을 합니다. 예를 들어 var(--i) 이고, --i : 5 라고 가정하는 경우 var(--i) 의 자리에는 5 가 남게 됩니다. 이러한 원리에 따라서 calc(5*45deg) 가 되고, 5 * 45 = 225deg 가 그 자리에 남게 됩니다.
앞서 우리는 i:1 부터 :10 까지 각 .dot 요소에 적용하였으므로 각 도는 1*45deg ~ 2*45deg ~ ... 10*45deg 가 계산된 값이 rotate(00deg) 에 차례대로 적용됩니다.
도트 거리 띄우기
transform-origin: 40px;
도트 배치 파트 까지 하셨다면, 아마 도트가 점의 형태로 중앙에 옹기종기 모여있는 형태일 겁니다. 즉, 서로 다른 각도를 바라보고 있으나 중앙에 모여 있으니 제대로 배치가 되었는지 보이지 않습니다.
이 때 추가적으로 적용해줘야 하는 속성이 transform-origin 이라는 속성입니다. 해당 속성은 transform 애니메이션이 적용될 때 기준점이 되는 위치를 설정할 때 사용됩니다. 아무런 속성을 지정하지 않으면 애니메이션이 적용된 요소의 중앙을 기준으로 잡고 있습니다. 여기서 transform-origin: 40px 를 지정하게 되면, 요소의 중앙을 기준으로 우측(x축)으로 40px 하단(y축)으로 40px 이동한 지점을 transform 애니메이션이 적용되는 기준이 되도록 합니다.
여기 까지 적용하신다면 이제 각 도트는 각자의 각도를 유지한 상태로 중앙을 기준으로 140px 가 떨어진 위치에 거리를 유지한 채 위치하게 됩니다.
참고로, 아래 영상을 확인하시면 보다 정확한 동작 원리를 파악하실 수 있습니다.
도트 모양 꾸미기 및 애니메이션 속성 적용
.dot {
width: 15px;
height: 5px;
border-radius: 30px;
background: #3396ff;
animation-delay: calc(var(--i) * -2s);
animation: 1.5s infinite linear rotation;
}
이제 도트의 길이와 넓이 색상을 정하고, 애니메이션 속성을 적용해줘야 합니다.
우선 wdith: 15px, height: 5px, border-radius: 30px 로 지정하여 양쪽 끝 모서리는 둥글고, 길이는 짧고 뭉뚱한 형태의 도트를 만들어줍니다. 여기서 background를 #3396ff 로 지정하면 연한 파란색이 적용됩니다.
그 다음에는 animation : 1.5s infinite liear rotation; 을 지정하여 애니메이션이 일정한 속도(linear) 를 유지한 채 1.5초(1.5s) 간 진행되며, 해당 반복은 무한으로(infinite) 설정해줍니다. 그리고 @keyframes 지정시 키프레임명으로 사용하기 위해 rotation 을 입력해줍니다(이는 사용자 작명입니다)
.dot 애니메이션 키프레임 추가
마지막으로 @keyframems rotation 을 추가해줍니다.
@keyframes rotation {
0% {
opacity: 0.6;
transform: translate(-50%, -50%) rotate(calc(var(--i) * -45deg));
}
}
참고로 0% { } 혹은 from { } 만 지정하고 100%나 to 를 명시하지 않으면 animation 이 적용된 .dot 요소의 속성에 입력된 값들을 끝 지점으로 인식합니다.
즉, 여기서 애니메이션의 시작점이 되는 속성을 0% { } 내에 입력해준다고 보면 됩니다. 현재 예시에서 적용된 transform: translate(-50%,-50%) 은 애니메이션이 적용되는 .dot 의 시작위치를 중앙으로 하기 위해서입니다. 만일 아무런 값을 지정하지 않는다면 해당 요소는 중앙이 아닌 약간 어긋난 거리에서 애니메이션이 진행될 수 있으므로 주의해야 합니다.
rotate의 경우에는 앞서 .dot 에 적용한 속성과 차이가 없습니다. 다만 기존 45deg 에 -45deg 를 지정함으로써 애니메이션의 시작 각도를 끝나는 지점의 정반대로 지정하여 시작과 끝이 마지막에는 동일한 위치가 되도록 설정해준 것입니다.
앞서 다 설명한 부분이기에 크게 설명할 부분은 없었습니다. 이 부분은 한 번 적용해보시고, 스스로의 스타일에 맞게 변형해보시면 됩니다. 저의 경우 opacity를 0.6으로 지정하여 반투명 보다 약간 더 불투명한 느낌을 주었습니다.
구현 결과
앞서 과정에서 구현된 모든 코드를 확인해보세요. 스스로 구현해본 결과와 비슷한지 살펴보고, 더 응용하거나 새로운 기능이 떠올랐다면 직접 구현해보시는 계기가 되었으면 좋겠습니다. 고생하셨습니다!.
See the Pen Untitled by youngwan2 (@youngwan2) on CodePen.
참고자료
다음 애니메이션 | 스파크 애니메이션
'UI 디자인 애니메이션 연구소' 카테고리의 다른 글
HTML+CSS+JS 를 이용한 써클 프로그래스 애니메이션을 만들어 봅시다 (0) | 2024.05.20 |
---|---|
CSS +JS 를 이용한 톡톡 튀는 폭죽(스파크) 애니메이션 만들기 (0) | 2024.05.09 |
HTML/CSS 를 이용하여 실제 같은 페이퍼 만들기 (1) | 2024.05.05 |
바닐라 JS/HTML/CSS 로 재밌는 애니메이션 효과 만들기 (3탄) (0) | 2024.05.05 |
HTML/CSS 만으로 재밌는 마우스 호버 애니메이션 구현하기(var 함수 활용)(2탄) (0) | 2024.05.04 |