File size: 2,591 Bytes
3bcb678
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
class ProgressRing extends HTMLElement {
    constructor() {
        super();
        this.attachShadow({ mode: 'open' });
    }

    static get observedAttributes() {
        return ['value', 'color', 'size'];
    }

    connectedCallback() {
        this.animateValue();
    }

    attributeChangedCallback(name, oldValue, newValue) {
        if (oldValue !== newValue && this.shadowRoot) {
            this.render();
            this.animateValue();
        }
    }

    render() {
        const value = this.getAttribute('value') || 0;
        const color = this.getAttribute('color') || '#10b981';
        const size = this.getAttribute('size') || 150;

        this.shadowRoot.innerHTML = `
            <style>
                :host {
                    display: inline-block;
                }
                .progress-ring {
                    transform: rotate(-90deg);
                }
                .progress-ring__circle {
                    transition: stroke-dashoffset 0.5s ease-in-out;
                    transform-origin: 50% 50%;
                }
            </style>
            <svg class="progress-ring" width="${size}" height="${size}">
                <circle
                    class="progress-ring__circle-bg"
                    stroke="#1e293b"
                    stroke-width="12"
                    fill="transparent"
                    r="${size/2 - 12}"
                    cx="${size/2}"
                    cy="${size/2}"
                />
                <circle
                    class="progress-ring__circle"
                    stroke="${color}"
                    stroke-width="12"
                    stroke-linecap="round"
                    fill="transparent"
                    r="${size/2 - 12}"
                    cx="${size/2}"
                    cy="${size/2}"
                    style="stroke-dasharray: ${2 * Math.PI * (size/2 - 12)}; stroke-dashoffset: ${2 * Math.PI * (size/2 - 12)}"
                />
            </svg>
        `;
    }

    animateValue() {
        const circle = this.shadowRoot.querySelector('.progress-ring__circle');
        const value = parseInt(this.getAttribute('value') || 0);
        const radius = circle.r.baseVal.value;
        const circumference = radius * 2 * Math.PI;

        circle.style.strokeDasharray = `${circumference} ${circumference}`;
        const offset = circumference - (value / 100) * circumference;
        
        setTimeout(() => {
            circle.style.strokeDashoffset = offset;
        }, 100);
    }
}

customElements.define('progress-ring', ProgressRing);