CSS&JS/👀Study and Copy

Online Tutorials의 Circular ProgressBar

arancia_ 2022. 7. 1. 17:58

강의영상 : https://www.youtube.com/watch?v=V_G1WzPjb4o

 

깃허브 미리보기 : https://ohikmyeong.github.io/ot_clrProgress/

 

Animated Circular Progress Bar Using Html CSS Only | Dynamic SVG Progress Bar

 

ohikmyeong.github.io

 

 

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
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Animated Circular Progress Bar Using Html CSS Only | Dynamic SVG Progress Bar</title>
    <link rel="stylesheet" type="text/css" href="./css/style.css"/>
    <script src="./js/main.js" type="module"></script>
</head>
<body>
    <!-- https://www.youtube.com/watch?v=V_G1WzPjb4o -->
 
    <div class="container">
        <template>
            <article class="card">
                <div class="percent" style="--clr:#f404fc;--num:80;">
                    <div class="dot"></div>
                    <svg>
                        <circle cx="73" cy="75" r="68"></circle>
                        <circle cx="73" cy="75" r="68"></circle>
                    </svg>
                    <div class="number">
                        <h2>80</h2>
                        <p>Html</p>
                    </div>
                </div><!-- percent -->
            </article>
        </template>
    </div>
<script>
    
</script>
</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
96
97
98
99
100
101
102
103
104
@charset "utf-8";
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700;900&display=swap');
 
*{margin:0;padding:0;box-sizing:border-box;}
html,body{
    font-family: 'Roboto', sans-serif;
    color:#fff;
}
 
body{
    display:flex; flex-flow:column nowrap;
    justify-content:center; align-items:center;
    width:100%;min-height:100vh;
    background:#222; color:#fff;
}
 
.container{
    display:flex; flex-flow:row wrap;
    justify-content:center; align-items:center;
    gap:40px;
    position:relative;
    width:min(calc(100% - 40px), 520px);
}
 
.card{
    display:flex; flex-flow:row wrap;
    justify-content:center; align-items:center;
    position:relative;
    /* width:max(220px,calc(50% - 40px));  */
    /* aspect-ratio:1/1.13; */
    width:220px; height:260px;
    background:#2a2a2a;
}
 
.percent{
    position:relative;
    width:66%; aspect-ratio:1/1;
    /* background:#fff; */
}
 
.percent svg{
    position:relative;
    /* width:100%;height:100%; */
    width:150px;height:150px;
    transform:rotate(270deg);
}
 
.percent svg circle{
    width:100%;height:100%;
    fill:transparent;
    stroke-width:2;
    stroke:#191919;
}
 
.percent svg circle:last-child{
    stroke:var(--clr);
    stroke-dasharray:440;
    stroke-dashoffset: 440; /* 아무것도 안보이게 */
    stroke-dashoffset: calc(440 - (440 * var(--num)) / 100);
    animation: fadeIn .5s 2.5s linear both;
}
 
.dot{
    position:absolute; z-index:10;
    inset:5px;
    /* 360deg / 100 = 3.6 */
    animation: aniDot 2s linear forwards;
}
.dot::before{
    content:'';display:block;position:absolute;
    left:52%;
    width:10px; aspect-ratio:1/1;
    background:var(--clr);
    border-radius:50%;
    box-shadow: 0 0 10px var(--clr),
                0 0 30px var(--clr);
}
 
.number{
    position:absolute;
    inset:0;
    display:flex;flex-flow:column nowrap;
    justify-content:center; align-items:center;
    text-align:center;
    animation: fadeIn 1s 2.8s linear both;
}
 
.number h2{font-size:2.5rem;}
 
.number h2::after{content:'%'; font-size:.5em; font-weight:300;}
 
.number p{font-size:0.875rem; text-transform:uppercase; margin-top:.25em;  opacity:.75;}
 
@keyframes aniDot {
    from{transform:rotate(0deg)}
    to{transform:rotate(calc( 3.6deg * var(--num) ));}
}
 
@keyframes fadeIn {
    from{opacity:0;}
    to{opacity:1;}
}
 
 
cs

JS-main.js

1
2
3
4
5
6
7
8
9
10
11
import { ClrProgress } from "./clrProgress.js";
 
const DATA = [
    {name:"html",per:80,clr:"#04fc43"},
    {name:"css",per:90,clr:"#04d7fc"},
    {name:"js",per:85,clr:"#f0fc04"},
    {name:"design",per:70,clr:"#f404fc"},
];
 
const clrProgress = new ClrProgress(DATA);
 
cs

JS-clrProgress.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
export class ClrProgress{
    constructor(data){
        this.DATA = data;
        this.$container = document.querySelector('.container');
 
        //실행
        this.init();
    }//constructor
 
    init(){
        const $frag = document.createDocumentFragment();
        for(let obj of this.DATA){
            const $card = this.make_elem('ARTICLE','card');
 
            const $percent = this.append_percent(obj);
            
            this.append_dot($percent);
            this.append_circle($percent);
            this.append_number($percent, obj);
            
 
            $card.appendChild($percent);
            $frag.appendChild($card);
        }
 
        this.$container.appendChild($frag)
    }//init
 
    
    make_elem(elemType, className){
        const $res = document.createElement(elemType);
        className && $res.classList.add(className);
        return $res
    }//make_elem
 
    add_text($elem,text){ $elem.textContent = text;}
 
    append_percent(obj){
        const{clr,per} = obj;
        const $elem = this.make_elem('DIV','percent');
        $elem.style.setProperty('--clr',clr);
        $elem.style.setProperty('--num',per);
        return $elem;
    }//append_percent
 
    append_dot($parent){
        const $elem = this.make_elem('DIV','dot');
        $parent.appendChild($elem);
    }//append_dot
 
    append_circle($parent){
        const $svg = document.createElementNS("http://www.w3.org/2000/svg""svg");
        const $clr_1 = document.createElementNS("http://www.w3.org/2000/svg""circle");
        const $clr_2 = document.createElementNS("http://www.w3.org/2000/svg""circle");
        const clr_data = {cx:73, cy:75, r:68};
        this.set_circle($clr_1,clr_data);
        this.set_circle($clr_2,clr_data);
        $svg.appendChild($clr_1);
        $svg.appendChild($clr_2);
        $parent.appendChild($svg);
    }//append_circle
 
    append_number($parent,obj){
        const {per,name= obj;
        const $number = this.make_elem('DIV','number');
 
        this.appendPerName("H2",per,$number);
        this.appendPerName("P",name,$number);
 
        $parent.appendChild($number);
    }//append_number
 
    appendPerName(elemType,text,$parent){
        const $elem = this.make_elem(elemType);
        this.add_text($elem, text);
        $parent.appendChild($elem);
    }//appendPerName
 
    set_circle($clr,data){
        for(let key in data){ $clr.setAttribute(key, data[key]);}
    }//set_circle
}//ClrProgress
cs

'CSS&JS > 👀Study and Copy' 카테고리의 다른 글

WDS- Sortable Drag & Drop List  (0) 2022.08.09
[WDS] CSS + JS Review Card  (0) 2022.08.08
[vanilla JS] 자바스크립트로 테트리스 만들기 (1)  (0) 2022.06.10
2048 클론코딩  (0) 2022.06.07
getter,setter  (0) 2022.06.03