유튜브 쇼츠 : https://youtube.com/shorts/CghGn-glw28?si=4LfGyNdcicBsYOwE
See the Pen CSS+JS Loading requestanimationframe by Oh Ikmyeong (@dpffpself) on CodePen.
HTML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS LOADING DOT</title>
<link rel="stylesheet" href="./style.css" type="text/css"/>
<script src="./loader.js" defer></script>
</head>
<body>
<a href="https://youtube.com/shorts/CghGn-glw28?si=b7Npva9mkIS39dCO" target="_blank">CSS LOADING DOT SHORTS</a>
<div class="loader">
<span class="dot"></span>
<span class="dot"></span>
<span class="dot"></span>
<span class="dot"></span>
<span class="dot"></span>
</div>
</body>
</html>
|
cs |
CSS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
*{margin:0;padding:0;box-sizing:border-box;}
html,body{
width:100%;min-height:100vh;
background:#000;
}
body{
display:flex; flex-flow:column nowrap;
gap:30px;
justify-content:center; align-items:center;
}
a{
display:inline-block;
padding:5px 10px;
text-decoration:none;
background:#fafafc;
border-radius:4px;
font-size:12px;
}
.loader{
--_size:20px;
--_gap:10px;
position:relative;
width:calc(var(--_size) * 5 + var(--_gap) * 4);
height:var(--_size);
}
.dot{
display:block;
position:absolute;
top:0;
width:var(--_size);
aspect-ratio:1/1;
background:#fff;
border-radius:50%;
}
|
cs |
JS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
const $$dot = document.querySelectorAll(".dot");
const SIZE = 20;
const GAP = 10;
const COUNT = 5;
/* 1차 정렬 */
for (let i = 0; i < $$dot.length; i++) {
const $dot = $$dot[i];
const startPx = SIZE * i + GAP * i
$dot.style.transform = `translate(${startPx}px,0px)`;
$dot.dataset.remember = startPx;
move_dots($dot);
}
function move_dots($dot) {
const remember = parseInt($dot.dataset.remember);
if (remember <= 0) {
const cnt = COUNT - 1;
const next = (cnt * SIZE) + (cnt * GAP);
$dot.dataset.remember = next;
const ani = $dot.animate([
{
transform: `translate(0px, 0px)`
},
{
transform: `translate(0px, -50px)`,
background: "red"
},
{
transform: `translate(${next}px, -50px)`,
background: "red"
},
{
transform: `translate(${next}px, 0px)`,
background: "#fff"
}
], {
fill: "both",
duration: 1200,
easing: "ease-out"
});
ani.addEventListener("finish", () => {
requestAnimationFrame(() => {
move_dots($dot);
});
}, { once: true });
} else {
const next = remember - (SIZE + GAP);
$dot.dataset.remember = next;
const ani = $dot.animate([
{
transform: `translate(${next}px, 0px)`
}
], {
fill: "both",
duration: 1200,
easing: "ease-in"
});
ani.addEventListener("finish", () => {
requestAnimationFrame(() => {
move_dots($dot);
});
}, { once: true });
}
}//move_dots
|
cs |
animate와
animate가 종료되면 쓸 수 있는 이벤트리스너 finish
requestAnimationFrame으로 콜백하기
사실 css만으로도 구현할 수 있긴 할텐데.... 그게 더 귀찮다
하지만 실제 프로젝트에는 css만으로 구현할 수 있는 방안이 훨씬 좋을것이다
'CSS&JS > 👀Study and Copy' 카테고리의 다른 글
[JS+CSS]Madia님 영상보다가 디자인 예쁜거 구현해보기 (고객의 소리 부분) (0) | 2024.10.04 |
---|---|
[CSS]inverted border-radius 안쪽으로 파인 효과 (0) | 2024.09.30 |
[JS]Trello 스타일의 drag & drop 구현하기 (1) | 2024.09.27 |
[LunDev]CSS only marquee slider (0) | 2024.09.19 |
[CSS/JS]Lun Dev 쇼핑몰 이미지 줌 효과 (1) | 2024.09.13 |