https://www.youtube.com/watch?v=HIrDMR6CaHY
데모 사이트 : https://ohikmyeong.github.io/hpp-counter
HTML
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
|
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>If Dr. Seuss Made Programming Tutorials</title>
<link rel="stylesheet" href="./css/main.css">
<script src="./js/main.js" type="module"></script>
</head>
<body>
<a href="https://www.youtube.com/watch?v=HIrDMR6CaHY" target="_blank">If Dr. Seuss Made Programming Tutorials</a>
<section class="counter-wrap">
<p class="counter-title">CASH PRIZE</p>
<div id="counter">
<div class="counter-dollar">$</div>
<div class="counter-number-wrap"></div>
<div class="counter-rest"></div>
<div class="counter-number-wrap"></div>
<div class="counter-number-wrap"></div>
<div class="counter-number-wrap"></div>
<div class="counter-rest"></div>
<div class="counter-number-wrap"></div>
<div class="counter-number-wrap"></div>
<div class="counter-number-wrap"></div>
</div><!-- counter -->
<div class="counter-bg"></div>
</section><!-- wrap -->
<form id="frm">
<input type="color" name="counter-color" value="#4fe388">
<input type="number" name="cash-prize" min="0" max="9999999">
<button type="submit" id="btn-restart" title="restart">restart</button>
</form>
</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
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
@charset "utf-8";
/* wrap */
.counter-wrap{
--_bg:#343434;
--counter-wrap-color :rgb(79,227,136);
display:flex;flex-flow:column nowrap;
justify-content:center; align-items:center;
position:relative;
width:min(1200px, 90%); min-width:1000px;
padding:80px 20px 100px;
background:var(--_bg);
border:12px solid #555;
border-radius:4px;
text-align:center; font-weight:bold;color:var(--counter-wrap-color);
user-select:none;
}
/* title */
.counter-title{
position:relative;
font-size:30px;
}
.counter-title::before,
.counter-title::after{
content : "*";
}
.counter-title::before{margin-right:1em;}
.counter-title::after{margin-left:1em;}
/* counter */
#counter{
display:flex;flex-flow:row nowrap;
justify-content:center; align-items:flex-end;
gap:10px;
position:relative;
width:100%;
font-size:100px;
}
/* dollar */
.counter-dollar{
margin-right:20px;
font-weight:normal;
font-size:.8em;
}
/* rest */
.counter-rest{
width:12px; height:18px;
background:var(--counter-wrap-color);
}
/* number */
.counter-number-wrap{
position:relative; overflow:hidden;
width:1ch; height:1.35ch;
border-bottom:1px solid var(--counter-wrap-color);
text-align:center; font-weight:bold;
}
/* number-list */
.counter-number-list{
position:absolute;
top:0; left:0;
width:100%;
}
/* number-list-item */
.counter-number-list-item{
width:100%; height:1.35ch;
}
/* background */
.counter-bg{
position:absolute; overflow:hidden;
top:0;left:0;
width:100%; height:100%;
pointer-events:none;
background:repeating-linear-gradient(var(--_bg), var(--_bg) 3px, transparent 3px, transparent 9px);
background-size:100% 200%;
animation: move-background 60s linear 0s infinite;
}
.counter-bg::after{
content:'';display:block;position:absolute;
top:0;left:0;
width:100%;height:100%;
background:radial-gradient(transparent, rgba(0,0,0,.5), rgba(0,0,0,1));
animation: breath-background 1s ease-in-out 0s infinite alternate;
}
@keyframes move-background {
to{background-position-y:100%;}
}
@keyframes breath-background {
to{ scale:1.5; }
}
|
cs |
main.js
1
2
3
4
5
6
7
8
9
|
import { Counter } from "./Counter.js";
const cashPrize = 9_876_543;
document.getElementsByName('cash-prize')[0].value = cashPrize;
new Counter()
.set_cash_prize(cashPrize)
.init();
|
cs |
Counter.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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
export class Counter {
#cashPrize;
constructor() {
this.$counterWrap = null;
this.$$numberWrap = null;
this.$form = null;
this.clssList = {
numberWrap: "counter-number-wrap",
numberList: "counter-number-list",
numberItem: "counter-number-list-item",
target: 'number-target',
}
}//constructor
set_cash_prize(cashPrize) {
this.#cashPrize = String(cashPrize) ?? 0;
console.log("this.#cashPrize",this.#cashPrize, typeof this.#cashPrize);
return this;
}//set_cash_prize
init() {
/* DOM */
this.$counterWrap = document.getElementsByClassName('counter-wrap')[0];
this.$$numberWrap = Array.from(this.$counterWrap.getElementsByClassName(this.clssList.numberWrap));
this.$form = document.getElementById('frm');
/* DOM + animation */
this.restart();
/* (EVENT) */
this.$form.addEventListener('submit', this.on_submit_form);
}//init
restart() {
/* DOM */
this.fill_number_wrap();
/* (FUNC) */
this.animate_number_wrap();
}//restart
fill_number_wrap() {
const lenWrap = this.$$numberWrap.length;
const lenNum = this.#cashPrize.length;
let startIdx = lenWrap - lenNum;
let targetNumIdx = 0;
if (startIdx < 0) { return console.error('액수가 너무 큼') }
this.$$numberWrap.forEach(($numberWrap, idx) => {
/* reset */
$numberWrap.innerHTML = "";
/* list */
const $list = document.createElement('UL');
$list.classList.add(this.clssList.numberList);
$numberWrap.appendChild($list);
/* 반복횟수 */
const iterCount = idx + 1;
/* fill list */
for (let i = 0; i < iterCount; i++) {
for (let num = 0; num <= 9; num++) {
const $item = document.createElement('LI');
$item.classList.add(this.clssList.numberItem);
$item.textContent = num;
$list.appendChild($item);
if (i !== iterCount - 1) continue;
if (startIdx !== idx) continue;
const answer = this.#cashPrize.at(targetNumIdx);
if (answer !== String(num)) continue;
$item.classList.add(this.clssList.target);
startIdx++;
targetNumIdx++;
}//for-num
}//for-iterCount
});//forEach
};
/**
* @url https://easings.net/ko#easeOutBack
*/
animate_number_wrap() {
const len = this.$$numberWrap.length;
for (let i = 0; i < len; i++) {
const $numberWrap = this.$$numberWrap[i];
const $list = $numberWrap.getElementsByClassName(this.clssList.numberList)[0];
const $target = $numberWrap.getElementsByClassName(this.clssList.target)[0];
if(!$target){continue;}
const top = $target.offsetTop * -1;
$list.animate([
{ transform: `translateY(${top}px)` }
], {
duration: 4000,
fill: "both",
easing: "cubic-bezier(0.34, 1.25, 0.7, 1)",
delay : (len - i) * 100
});
}//for
}//animate_number_wrap
/**
* form 제출시
* @param {Event} e
*/
on_submit_form = e => {
e.preventDefault();
const valueColor = e.currentTarget.querySelector("[name='counter-color']").value;
const cashPrize = e.currentTarget.querySelector("[name='cash-prize']").value;
this.$counterWrap.style.setProperty('--counter-wrap-color', valueColor);
if(String(cashPrize) === this.#cashPrize) return;
this.set_cash_prize(cashPrize);
this.restart();
}//on_submit_form
}//Counter
|
cs |
'CSS&JS > 👀Study and Copy' 카테고리의 다른 글
[ZeroCho]인간 JS엔진 되기 1-6 this는 호출 때 결정된다. (1) | 2024.01.04 |
---|---|
[별코딩]Promise.all .allSettled .any .race 예제로 비교하기 (0) | 2024.01.03 |
[Kevin Powell]CSS,JS로 marquee 태그 같은 무한 스크롤 애니메이션 구현하기 (0) | 2023.10.04 |
[OnlineTutorials] 3d Carousel Slider(drag,touch,button) (0) | 2023.09.07 |
[WDS] 마크다운 문법 (1) | 2023.08.24 |