@zumer/orbit 0.6.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/orbit.js CHANGED
@@ -1,7 +1,7 @@
1
1
 
2
2
  /*
3
3
  * orbit
4
- * v.0.6.0
4
+ * v.1.1.0
5
5
  * Author Juan Martin Muda - Zumerlab
6
6
  * License MIT
7
7
  **/
@@ -14,211 +14,155 @@
14
14
  this.shadowRoot.innerHTML = `
15
15
  <style>
16
16
  :host {
17
- display: block;
18
- }
19
- svg {
17
+ --o-fill: var(--o-gray-light);
18
+ --o-stroke: var(--o-fill);
19
+ --o-stroke-width: 1;
20
+ --o-back-fill: transparent;
21
+ --o-back-stroke: none;
22
+ --o-back-stroke-width: 1;
23
+ }
24
+ :host(:hover){
25
+ --o-fill: var(--o-gray-light);
26
+ --o-stroke: var(--o-fill);
27
+ --o-stroke-width: 1;
28
+ --o-back-fill: transparent;
29
+ --o-back-stroke: none;
30
+ --o-back-stroke-width: 1;
31
+ }
32
+ svg {
20
33
  width: 100%;
21
34
  height: 100%;
22
35
  overflow: visible;
23
36
  pointer-events: none;
24
37
  }
25
38
  svg * {
26
- pointer-events: stroke;
39
+ pointer-events: visiblePainted;
27
40
  }
28
41
  .progress-bar {
29
- fill: transparent;
30
- stroke: var(--o-progress-color);
31
- transition: stroke 0.3s;
42
+ fill: var(--o-fill);
43
+ stroke: var(--o-stroke);
44
+ stroke-width: var(--o-stroke-width);
45
+ transition: all 0.3s;
46
+ stroke-linejoin: round;
32
47
  }
33
48
  .progress-bg {
34
- stroke: var(--o-bg-color, transparent);
35
- }
36
- :host(:hover) .progress-bar {
37
- stroke: var(--o-hover-progress-color, var(--o-progress-color));
38
-
49
+ fill: var(--o-back-fill);
50
+ stroke: var(--o-back-stroke);
51
+ stroke-width: var(--o-back-stroke-width);
39
52
  }
40
53
  </style>
41
54
  <svg viewBox="0 0 100 100">
42
- <defs></defs>
43
- <path class="progress-bg"></path>
44
- <path class="progress-bar"></path>
55
+ <path class="progress-bg" shape-rendering="geometricPrecision" vector-effect="non-scaling-stroke"></path>
56
+ <path class="progress-bar" shape-rendering="geometricPrecision" vector-effect="non-scaling-stroke"></path>
45
57
  </svg>
46
58
  `;
47
59
  }
48
60
  connectedCallback() {
49
61
  this.update();
50
- const observer = new MutationObserver((mutations) => {
62
+ this.observer = new MutationObserver((mutations) => {
63
+ this.observer.disconnect();
51
64
  mutations.forEach((mutation) => {
52
65
  this.update();
53
66
  });
67
+ this.observer.observe(this, { attributes: true, childList: true });
54
68
  });
55
- observer.observe(this, { attributes: true, childList: true });
69
+ this.observer.observe(this, { attributes: true, childList: true });
56
70
  }
57
71
  update() {
58
- const { shape } = this.getAttributes();
59
- const svg = this.shadowRoot.querySelector("svg");
60
- const defs = this.createDefs();
61
- if (shape !== "none") {
62
- defs.appendChild(this.createMarker("head", "end"));
63
- defs.appendChild(this.createMarker("tail", "start"));
64
- }
65
72
  const progressBg = this.shadowRoot.querySelector(".progress-bg");
66
73
  const progressBar = this.shadowRoot.querySelector(".progress-bar");
67
74
  this.updateArc(progressBg, true);
68
75
  this.updateArc(progressBar, false);
69
- svg.querySelector("defs").replaceWith(defs);
70
- }
71
- createSVGElement() {
72
- const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
73
- svg.setAttribute("viewBox", "0 0 100 100");
74
- svg.setAttribute("width", this.getAttribute("width") || "100%");
75
- svg.setAttribute("height", this.getAttribute("height") || "100%");
76
- return svg;
77
76
  }
78
77
  updateArc(arc, full) {
79
- const {
80
- strokeWidth,
81
- realRadius,
82
- ellipseX,
83
- ellipseY,
84
- progressBarColor,
85
- progressBgColor,
86
- maxAngle,
87
- shape
88
- } = this.getAttributes();
89
- const angle = this.getProgressAngle(maxAngle, full);
90
- const { d } = this.calculateArcParameters(angle, realRadius, ellipseX, ellipseY);
78
+ const { d } = this.calculateArcParameters(full);
91
79
  arc.setAttribute("d", d);
92
- arc.setAttribute("stroke", full ? progressBgColor : progressBarColor);
93
- arc.setAttribute("fill", "transparent");
94
- if (shape !== "none") {
95
- arc.setAttribute("marker-end", "url(#head)");
96
- arc.setAttribute("marker-start", "url(#tail)");
97
- }
98
- arc.setAttribute("stroke-width", strokeWidth);
99
- arc.setAttribute("vector-effect", "non-scaling-stroke");
100
80
  }
101
81
  getAttributes() {
102
- const orbitRadius = parseFloat(
103
- getComputedStyle(this).getPropertyValue("r") || 0
104
- );
105
- const range = parseFloat(
106
- getComputedStyle(this).getPropertyValue("--o-range") || 360
107
- );
108
- const ellipseX = parseFloat(
109
- getComputedStyle(this).getPropertyValue("--o-ellipse-x") || 1
110
- );
111
- const ellipseY = parseFloat(
112
- getComputedStyle(this).getPropertyValue("--o-ellipse-y") || 1
113
- );
114
- const progress = parseFloat(
115
- getComputedStyle(this).getPropertyValue("--o-progress") || this.getAttribute("value") || 0
116
- );
82
+ const orbitRadius = parseFloat(getComputedStyle(this).getPropertyValue("r") || 0);
83
+ let orbitNumber = parseFloat(getComputedStyle(this).getPropertyValue("--o-orbit-number"));
84
+ let size = parseFloat(getComputedStyle(this).getPropertyValue("--o-size-ratio"));
85
+ const range = parseFloat(getComputedStyle(this).getPropertyValue("--o-range") || 360);
86
+ const progress = parseFloat(getComputedStyle(this).getPropertyValue("--o-progress") || this.getAttribute("value") || 0);
117
87
  const shape = this.getAttribute("shape") || "none";
118
- const progressBarColor = this.getAttribute("bar-color");
119
- const progressBgColor = this.getAttribute("bgcolor") || "transparent";
120
- const strokeWidth = parseFloat(
121
- getComputedStyle(this).getPropertyValue("stroke-width") || 1
122
- );
123
- let strokeWithPercentage = strokeWidth / 2 * 100 / orbitRadius / 2;
124
- let innerOuter = strokeWithPercentage;
88
+ const strokeWidth = parseFloat(getComputedStyle(this).getPropertyValue("--o-stroke-width"));
89
+ const arcHeight = orbitRadius / orbitNumber * size - strokeWidth + 0.3;
90
+ const arcHeightPercentage = arcHeight / 2 * 100 / orbitRadius / 2;
91
+ const maxAngle = range;
92
+ const maxValue = parseFloat(this.getAttribute("max")) || 100;
93
+ let innerOuter;
125
94
  if (this.classList.contains("outer-orbit")) {
126
- innerOuter = strokeWithPercentage * 2;
127
- }
128
- if (this.classList.contains("quarter-outer-orbit")) {
129
- innerOuter = strokeWithPercentage * 1.75;
130
- }
131
- if (this.classList.contains("inner-orbit")) {
95
+ innerOuter = arcHeightPercentage;
96
+ } else if (this.classList.contains("quarter-outer-orbit")) {
97
+ innerOuter = arcHeightPercentage * -0.5;
98
+ } else if (this.classList.contains("inner-orbit")) {
99
+ innerOuter = arcHeightPercentage * -1;
100
+ } else if (this.classList.contains("quarter-inner-orbit")) {
101
+ innerOuter = arcHeightPercentage * 0.5;
102
+ } else {
132
103
  innerOuter = 0;
133
104
  }
134
- if (this.classList.contains("quarter-inner-orbit")) {
135
- innerOuter = strokeWithPercentage * 0.75;
136
- }
137
- const realRadius = 50 + innerOuter - strokeWithPercentage;
138
- const maxAngle = range;
105
+ const realRadius = 50 + innerOuter;
139
106
  return {
140
107
  orbitRadius,
141
- ellipseX,
142
- ellipseY,
143
108
  progress,
144
- progressBarColor,
145
- progressBgColor,
146
109
  strokeWidth,
147
110
  realRadius,
148
111
  maxAngle,
149
- shape
112
+ maxValue,
113
+ shape,
114
+ arcHeightPercentage,
115
+ orbitNumber
150
116
  };
151
117
  }
152
- getProgressAngle(maxAngle, full) {
153
- const progress = parseFloat(
154
- getComputedStyle(this).getPropertyValue("--o-progress") || this.getAttribute("value") || 0
155
- );
156
- const maxValue = parseFloat(this.getAttribute("max")) || 100;
118
+ getProgressAngle(full) {
119
+ const { maxAngle, progress, maxValue } = this.getAttributes();
157
120
  return full ? (maxValue - 1e-5) / maxValue * maxAngle : progress / maxValue * maxAngle;
158
121
  }
159
- calculateArcParameters(angle, realRadius, ellipseX, ellipseY) {
160
- const radiusX = realRadius / ellipseX;
161
- const radiusY = realRadius / ellipseY;
162
- const startX = 50 + radiusX * Math.cos(-Math.PI / 2);
163
- const startY = 50 + radiusY * Math.sin(-Math.PI / 2);
164
- const endX = 50 + radiusX * Math.cos((angle - 90) * Math.PI / 180);
165
- const endY = 50 + radiusY * Math.sin((angle - 90) * Math.PI / 180);
166
- const largeArcFlag = angle <= 180 ? 0 : 1;
167
- const d = `M ${startX},${startY} A ${radiusX},${radiusY} 0 ${largeArcFlag} 1 ${endX},${endY}`;
168
- return { startX, startY, endX, endY, largeArcFlag, d };
169
- }
170
- createDefs() {
171
- const defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");
172
- return defs;
173
- }
174
- createMarker(id, position = "end") {
175
- const { shape } = this.getAttributes();
176
- const marker = document.createElementNS("http://www.w3.org/2000/svg", "marker");
177
- marker.setAttribute("id", id);
178
- marker.setAttribute("viewBox", "0 0 10 10");
179
- if (position === "start" && shape !== "circle") {
180
- marker.setAttribute("refX", "2");
181
- } else if (position === "start" && shape === "circle") {
182
- marker.setAttribute("refX", "5");
183
- } else {
184
- marker.setAttribute("refX", "0.1");
185
- }
186
- marker.setAttribute("refY", "5");
187
- marker.setAttribute("markerWidth", "1");
188
- marker.setAttribute("markerHeight", "1");
189
- marker.setAttribute("orient", "auto");
190
- marker.setAttribute("markerUnits", "strokeWidth");
191
- marker.setAttribute("fill", "context-stroke");
192
- const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
193
- const shapes = {
194
- arrow: {
195
- head: "M 0 0 L 2 5 L 0 10 z",
196
- tail: "M 2 0 L 0 0 L 1 5 L 0 10 L 2 10 L 2 5 z"
197
- },
198
- slash: {
199
- head: "M 0 0 L 0 0 L 1 5 L 2 10 L 0 10 L 0 5 z",
200
- tail: "M 2 0 L 0 0 L 1 5 L 2 10 L 2 10 L 2 5 z"
201
- },
202
- backslash: {
203
- head: "M 0 0 L 2 0 L 1 5 L 0 10 L 0 10 L 0 5 z",
204
- tail: "M 2 0 L 2 0 L 1 5 L 0 10 L 2 10 L 2 5 z"
205
- },
206
- circle: {
207
- head: "M 0 0 C 7 0 7 10 0 10 z",
208
- tail: "M 6 0 C -1 0 -1 10 6 10 z"
209
- },
210
- zigzag: {
211
- head: "M 1 0 L 0 0 L 0 5 L 0 10 L 1 10 L 2 7 L 1 5 L 2 3 z",
212
- tail: "M 0 0 L 2 0 L 2 5 L 2 10 L 0 10 L 1 7 L 0 5 L 1 3 z"
213
- }
214
- };
215
- if (position === "end") {
216
- path.setAttribute("d", shapes[shape].head);
217
- } else {
218
- path.setAttribute("d", shapes[shape].tail);
219
- }
220
- marker.appendChild(path);
221
- return marker;
122
+ calculateArcParameters(full) {
123
+ const arcAngle = this.getProgressAngle(full);
124
+ const { realRadius, arcHeightPercentage, orbitNumber, shape, strokeWidth } = this.getAttributes();
125
+ const radius = realRadius;
126
+ let startX, startY, endX, endY, largeArcFlag, startX1, startY1, endX1, endY1, dShape, pointX, pointX1, pointY, pointY1;
127
+ let offset = Math.PI / 2;
128
+ let stroke = strokeWidth;
129
+ let fangle = arcAngle * Math.PI / 180;
130
+ let bigRadius = radius + arcHeightPercentage;
131
+ let smallRadius = radius - arcHeightPercentage !== 0 ? radius - arcHeightPercentage : radius;
132
+ let bigGap = stroke * 2 / orbitNumber / 2 / bigRadius;
133
+ let smallGap = stroke * 2 / orbitNumber / 2 / smallRadius;
134
+ let startAngle = bigGap - offset;
135
+ let endAngle = fangle - bigGap - offset;
136
+ let startAngle1 = smallGap - offset;
137
+ let endAngle1 = fangle - smallGap - offset;
138
+ startX = 50 + bigRadius * Math.cos(startAngle);
139
+ startY = 50 + bigRadius * Math.sin(startAngle);
140
+ endX = 50 + bigRadius * Math.cos(endAngle);
141
+ endY = 50 + bigRadius * Math.sin(endAngle);
142
+ pointX = 50 + bigRadius * Math.cos(endAngle + 3 * Math.PI / 180);
143
+ pointY = 50 + bigRadius * Math.sin(endAngle + 3 * Math.PI / 180);
144
+ startX1 = 50 + smallRadius * Math.cos(startAngle1);
145
+ startY1 = 50 + smallRadius * Math.sin(startAngle1);
146
+ endX1 = 50 + smallRadius * Math.cos(endAngle1);
147
+ endY1 = 50 + smallRadius * Math.sin(endAngle1);
148
+ pointX1 = 50 + smallRadius * Math.cos(endAngle1 + 3 * Math.PI / 180);
149
+ pointY1 = 50 + smallRadius * Math.sin(endAngle1 + 3 * Math.PI / 180);
150
+ largeArcFlag = arcAngle <= 180 ? 0 : 1;
151
+ let d = `M ${startX},${startY} A ${bigRadius},${bigRadius} 0 ${largeArcFlag} 1 ${endX},${endY}`;
152
+ if (shape === "arrow")
153
+ d += `L ${(pointX + pointX1) / 2} ${(pointY + pointY1) / 2} `;
154
+ if (shape === "circle" || shape === "bullet")
155
+ d += `A ${arcHeightPercentage}, ${arcHeightPercentage} 0 0 1 ${endX1},${endY1} `;
156
+ d += `L ${endX1} ${endY1}`;
157
+ d += `A ${smallRadius},${smallRadius} 0 ${largeArcFlag} 0 ${startX1},${startY1}`;
158
+ if (shape === "circle")
159
+ d += `A ${arcHeightPercentage}, ${arcHeightPercentage} 0 0 1 ${startX},${startY} `;
160
+ if (shape === "bullet")
161
+ d += `A ${arcHeightPercentage}, ${arcHeightPercentage} 0 0 0 ${startX},${startY} `;
162
+ if (shape === "arrow")
163
+ d += `L ${startX1 + 3} ${(startY + startY1) / 2} `;
164
+ d += `Z`;
165
+ return { d };
222
166
  }
223
167
  };
224
168
 
@@ -226,229 +170,78 @@
226
170
  var template = document.createElement("template");
227
171
  template.innerHTML = `
228
172
  <style>
229
- :host {
230
- display: inline-block;
231
- }
232
- svg {
233
- width: 100%;
234
- height: 100%;
235
- overflow: visible;
236
- pointer-events: none;
237
- }
238
- svg * {
239
- pointer-events: stroke;
240
- }
241
- .arc {
242
- stroke: var(--o-arc-color, var(--o-cyan-light));
243
- stroke-width: calc(var(--o-radius) / var(--o-orbit-number) * var(--o-size-ratio, 1));
244
- transition: stroke 0.3s;
245
- }
246
-
247
- :host(:hover) .arc {
248
- stroke: var(--o-hover-arc-color, var(--o-arc-color));
249
-
250
- }
251
- </style>
252
- <svg viewBox="0 0 100 100">
253
- <defs></defs>
254
- <path class="arc" vector-effect="non-scaling-stroke" fill="transparent"></path>
255
- </svg>
256
- `;
257
- var OrbitArc = class extends HTMLElement {
258
- constructor() {
259
- super();
260
- this.attachShadow({ mode: "open" });
261
- this.shadowRoot.appendChild(template.content.cloneNode(true));
262
- }
263
- connectedCallback() {
264
- this.update();
265
- const observer = new MutationObserver((mutations) => {
266
- mutations.forEach((mutation) => {
267
- this.update();
268
- });
269
- });
270
- observer.observe(this, { attributes: true, childList: true });
271
- }
272
- update() {
273
- const { shape } = this.getAttributes();
274
- const svg = this.shadowRoot.querySelector("svg");
275
- const path = this.shadowRoot.querySelector("path");
276
- const defs = this.shadowRoot.querySelector("defs");
277
- if (shape !== "none") {
278
- defs.innerHTML = "";
279
- defs.appendChild(this.createMarker("head", "end"));
280
- defs.appendChild(this.createMarker("tail", "start"));
281
- path.setAttribute("marker-end", "url(#head)");
282
- path.setAttribute("marker-start", "url(#tail)");
173
+ :host {
174
+ --o-fill: var(--o-gray-light);
175
+ --o-stroke: var(--o-fill);
176
+ --o-stroke-width: 1;
177
+ --o-color: currentcolor;
283
178
  }
284
- const { realRadius, arcColor, gap } = this.getAttributes();
285
- const angle = this.calculateAngle();
286
- const { d } = this.calculateArcParameters(angle, realRadius, gap);
287
- path.setAttribute("d", d);
288
- path.setAttribute("stroke", arcColor);
289
- }
290
- getAttributes() {
291
- const orbitRadius = parseFloat(getComputedStyle(this).getPropertyValue("r") || 0);
292
- const gap = parseFloat(getComputedStyle(this).getPropertyValue("--o-gap") || 1e-3);
293
- const shape = this.getAttribute("shape") || "none";
294
- const arcColor = this.getAttribute("arc-color");
295
- const rawAngle = getComputedStyle(this).getPropertyValue("--o-angle");
296
- const strokeWidth = parseFloat(getComputedStyle(this).getPropertyValue("stroke-width") || 1);
297
- const strokeWithPercentage = strokeWidth / 2 * 100 / orbitRadius / 2;
298
- let innerOuter = strokeWithPercentage;
299
- if (this.classList.contains("outer-orbit")) {
300
- innerOuter = strokeWithPercentage * 2;
179
+ :host(:hover){
180
+ --o-fill: var(--o-gray-light);
181
+ --o-stroke: var(--o-fill);
182
+ --o-stroke-width: 1;
183
+ --o-color: currentcolor;
301
184
  }
302
- if (this.classList.contains("quarter-outer-orbit")) {
303
- innerOuter = strokeWithPercentage * 1.75;
185
+ svg {
186
+ width: 100%;
187
+ height: 100%;
188
+ overflow: visible;
189
+ pointer-events: none;
304
190
  }
305
- if (this.classList.contains("inner-orbit")) {
306
- innerOuter = 0;
191
+ svg * {
192
+ pointer-events: visiblePainted;
307
193
  }
308
- if (this.classList.contains("quarter-inner-orbit")) {
309
- innerOuter = strokeWithPercentage * 0.75;
194
+ #orbitShape {
195
+ fill: var(--o-fill);
196
+ stroke: var(--o-stroke);
197
+ stroke-width: var(--o-stroke-width);
198
+ transition: all 0.3s;
199
+ stroke-linejoin: round;
310
200
  }
311
- const realRadius = 50 + innerOuter - strokeWithPercentage;
312
- const arcAngle = calcularExpresionCSS(rawAngle);
313
- return {
314
- orbitRadius,
315
- strokeWidth,
316
- realRadius,
317
- arcColor,
318
- gap,
319
- arcAngle,
320
- shape
321
- };
322
- }
323
- calculateAngle() {
324
- const { arcAngle, gap } = this.getAttributes();
325
- return arcAngle - gap;
326
- }
327
- calculateArcParameters(angle, realRadius) {
328
- const radiusX = realRadius / 1;
329
- const radiusY = realRadius / 1;
330
- const startX = 50 + radiusX * Math.cos(-Math.PI / 2);
331
- const startY = 50 + radiusY * Math.sin(-Math.PI / 2);
332
- const endX = 50 + radiusX * Math.cos((angle - 90) * Math.PI / 180);
333
- const endY = 50 + radiusY * Math.sin((angle - 90) * Math.PI / 180);
334
- const largeArcFlag = angle <= 180 ? 0 : 1;
335
- const d = `M ${startX},${startY} A ${radiusX},${radiusY} 0 ${largeArcFlag} 1 ${endX},${endY}`;
336
- return { startX, startY, endX, endY, largeArcFlag, d };
337
- }
338
- createMarker(id, position = "end") {
339
- const { shape } = this.getAttributes();
340
- const marker = document.createElementNS("http://www.w3.org/2000/svg", "marker");
341
- marker.setAttribute("id", id);
342
- marker.setAttribute("viewBox", "0 0 10 10");
343
- position === "start" && shape !== "circle" ? marker.setAttribute("refX", "2") : position === "start" && shape === "circle" ? marker.setAttribute("refX", "5") : marker.setAttribute("refX", "0.1");
344
- marker.setAttribute("refY", "5");
345
- marker.setAttribute("markerWidth", "1");
346
- marker.setAttribute("markerHeight", "1");
347
- marker.setAttribute("orient", "auto");
348
- marker.setAttribute("markerUnits", "strokeWidth");
349
- marker.setAttribute("fill", "context-stroke");
350
- const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
351
- const shapes = {
352
- arrow: {
353
- head: "M 0 0 L 2 5 L 0 10 z",
354
- tail: "M 2 0 L 0 0 L 1 5 L 0 10 L 2 10 L 2 5 z"
355
- },
356
- slash: {
357
- head: "M 0 0 L 0 0 L 1 5 L 2 10 L 0 10 L 0 5 z",
358
- tail: "M 2 0 L 0 0 L 1 5 L 2 10 L 2 10 L 2 5 z"
359
- },
360
- backslash: {
361
- head: "M 0 0 L 2 0 L 1 5 L 0 10 L 0 10 L 0 5 z",
362
- tail: "M 2 0 L 2 0 L 1 5 L 0 10 L 2 10 L 2 5 z"
363
- },
364
- circle: {
365
- head: "M 0 0 C 7 0 7 10 0 10 z",
366
- tail: "M 6 0 C -1 0 -1 10 6 10 z"
367
- },
368
- zigzag: {
369
- head: "M 1 0 L 0 0 L 0 5 L 0 10 L 1 10 L 2 7 L 1 5 L 2 3 z",
370
- tail: "M 0 0 L 2 0 L 2 5 L 2 10 L 0 10 L 1 7 L 0 5 L 1 3 z"
371
- }
372
- };
373
- position === "end" ? path.setAttribute("d", shapes[shape].head) : path.setAttribute("d", shapes[shape].tail);
374
- marker.appendChild(path);
375
- return marker;
376
- }
377
- };
378
- function calcularExpresionCSS(cssExpression) {
379
- const match = cssExpression.match(/calc\(\s*([\d.]+)deg\s*\/\s*\(\s*(\d+)\s*-\s*(\d+)\s*\)\s*\)/);
380
- if (match) {
381
- const value = parseFloat(match[1]);
382
- const divisor = parseInt(match[2]) - parseInt(match[3]);
383
- if (!isNaN(value) && !isNaN(divisor) && divisor !== 0) {
384
- return value / divisor;
201
+ text {
202
+ fill: var(--o-color);
385
203
  }
386
- }
387
- }
388
-
389
- // src/js/orbit-text.js
390
- var OrbitText = class extends HTMLElement {
204
+ #orbitPath {
205
+ fill: transparent;
206
+ stroke: none;
207
+ stroke-width: 0;
208
+ }
209
+ </style>
210
+ <svg viewBox="0 0 100 100">
211
+ <path id="orbitShape" shape-rendering="geometricPrecision" vector-effect="non-scaling-stroke"></path>
212
+ <path id="orbitPath" shape-rendering="geometricPrecision" vector-effect="non-scaling-stroke" ></path>
213
+ <text>
214
+ <textPath href="#orbitPath" alignment-baseline="middle"></textPath>
215
+ </text>
216
+ </svg>
217
+ `;
218
+ var OrbitArc = class extends HTMLElement {
391
219
  constructor() {
392
220
  super();
393
221
  this.attachShadow({ mode: "open" });
394
- const template2 = document.createElement("template");
395
- template2.innerHTML = `
396
- <svg viewBox="0 0 100 100" >
397
- <path id="orbitPath" fill="none" vector-effect="non-scaling-stroke"></path>
398
- <text>
399
- <textPath href="#orbitPath" alignment-baseline="middle"></textPath>
400
- </text>
401
- </svg>
402
- <style>
403
- :host {
404
- display: inline-block;
405
-
406
- }
407
- svg {
408
- width: 100%;
409
- height: 100%;
410
- overflow: visible;
411
- pointer-events: none;
412
-
413
- }
414
- svg * {
415
- pointer-events: stroke;
416
- }
417
-
418
- path {
419
- fill: transparent;
420
- stroke: var(--o-text-color);
421
- transition: stroke 0.3s;
422
- }
423
-
424
- :host(:hover) path {
425
- stroke: var(--o-hover-text-color, var(--o-text-color));
426
-
427
- }
428
-
429
-
430
- </style>
431
- `;
432
- this.shadowRoot.appendChild(template2.content.cloneNode(true));
222
+ this.shadowRoot.appendChild(template.content.cloneNode(true));
433
223
  }
434
224
  connectedCallback() {
435
225
  this.update();
436
- const observer = new MutationObserver((mutations) => {
226
+ this.observer = new MutationObserver((mutations) => {
227
+ this.observer.disconnect();
437
228
  mutations.forEach((mutation) => {
438
229
  this.update();
439
230
  });
231
+ this.observer.observe(this, { attributes: true, childList: true });
440
232
  });
441
- observer.observe(this, { attributes: true, childList: true });
233
+ this.observer.observe(this, { attributes: true, childList: true });
442
234
  }
443
235
  update() {
444
- const path = this.shadowRoot.getElementById("orbitPath");
236
+ const { length, fontSize, textAnchor, fitRange } = this.getAttributes();
237
+ const orbitPath = this.shadowRoot.getElementById("orbitPath");
238
+ const orbitShape = this.shadowRoot.getElementById("orbitShape");
445
239
  const text = this.shadowRoot.querySelector("text");
446
240
  const textPath = this.shadowRoot.querySelector("textPath");
447
- const { d, strokeWidth, lineCap } = this.getPathAttributes();
448
- path.setAttribute("d", d);
449
- path.setAttribute("stroke-width", strokeWidth);
450
- path.setAttribute("stroke-linecap", lineCap);
451
- const { length, fontSize, textAnchor, fitRange } = this.getTextAttributes();
241
+ const { dShape } = this.calculateArcParameters();
242
+ const { dPath } = this.calculateTextArcParameters();
243
+ orbitShape.setAttribute("d", dShape);
244
+ orbitPath.setAttribute("d", dPath);
452
245
  if (textAnchor === "start") {
453
246
  textPath.setAttribute("startOffset", "0%");
454
247
  textPath.setAttribute("text-anchor", "start");
@@ -459,91 +252,151 @@
459
252
  textPath.setAttribute("startOffset", "100%");
460
253
  textPath.setAttribute("text-anchor", "end");
461
254
  }
462
- if (fitRange) {
463
- textPath.parentElement.setAttribute("textLength", path.getTotalLength());
464
- }
255
+ if (fitRange)
256
+ textPath.parentElement.setAttribute("textLength", orbitPath.getTotalLength());
465
257
  text.style.fontSize = `calc(${fontSize} * (100 / (${length}) * (12 / var(--o-orbit-number) ))`;
466
- textPath.textContent = this.textContent.trim();
467
- }
468
- getPathAttributes() {
469
- const { realRadius, gap, textBgColor, flip, lineCap, strokeWidth } = this.getAttributes();
470
- const angle = this.calculateAngle();
471
- const { d } = this.calculateArcParameters(angle, realRadius, gap, flip);
472
- return { d, strokeWidth, textBgColor, lineCap };
473
- }
474
- getTextAttributes() {
475
- const { length, fontSize, textAnchor, fitRange } = this.getAttributes();
476
- return { length, fontSize, textAnchor, fitRange };
258
+ textPath.textContent = this.textContent;
477
259
  }
478
260
  getAttributes() {
261
+ let rawAngle, arcAngle, orbitNumber, size, innerOuter;
262
+ const strokeWidth = parseFloat(getComputedStyle(this).getPropertyValue("--o-stroke-width"));
479
263
  const orbitRadius = parseFloat(getComputedStyle(this).getPropertyValue("r") || 0);
480
- const flip = this.hasAttribute("flip");
481
- const fitRange = this.hasAttribute("fit-range");
482
- const lineCap = getComputedStyle(this).getPropertyValue("--o-linecap") || "butt";
483
- const gap = parseFloat(getComputedStyle(this).getPropertyValue("--o-gap") || 1e-3);
264
+ const shape = this.getAttribute("shape") || "none";
265
+ const flip = this.hasAttribute("flip") || this.classList.contains("flip");
266
+ const fitRange = this.hasAttribute("fit-range") || this.classList.contains("fit-range") || false;
484
267
  const length = parseFloat(getComputedStyle(this).getPropertyValue("--o-force"));
485
268
  const textAnchor = this.getAttribute("text-anchor") || "middle";
486
269
  const fontSize = getComputedStyle(this).getPropertyValue("font-size") || getComputedStyle(this).getPropertyValue("--font-size");
487
- const rawAngle = getComputedStyle(this).getPropertyValue("--o-angle");
488
- const strokeWidth = parseFloat(getComputedStyle(this).getPropertyValue("stroke-width") || 1);
489
- let strokeWithPercentage = strokeWidth / 2 * 100 / orbitRadius / 2;
490
- let innerOuter = strokeWithPercentage;
491
- if (this.classList.contains("outer-orbit")) {
492
- innerOuter = strokeWithPercentage * 2;
493
- }
494
- if (this.classList.contains("quarter-outer-orbit")) {
495
- innerOuter = strokeWithPercentage * 1.75;
270
+ const range = parseFloat(getComputedStyle(this).getPropertyValue("--o-range") || 360);
271
+ const value = parseFloat(this.getAttribute("value"));
272
+ if (value) {
273
+ arcAngle = this.getProgressAngle(range, value);
274
+ const prevElement = this.previousElementSibling;
275
+ const stackOffset = prevElement ? parseFloat(getComputedStyle(prevElement).getPropertyValue("--o_stack")) : 0;
276
+ this.style.setProperty("--o_stack", stackOffset + arcAngle);
277
+ if (stackOffset >= 0 && flip)
278
+ this.style.setProperty("--o-angle-composite", parseFloat(stackOffset) + "deg");
279
+ if (stackOffset > 0 && !flip)
280
+ this.style.setProperty("--o-angle-composite", parseFloat(stackOffset) + "deg");
281
+ } else {
282
+ rawAngle = getComputedStyle(this).getPropertyValue("--o-angle");
283
+ arcAngle = calcularExpresionCSS(rawAngle);
496
284
  }
497
- if (this.classList.contains("inner-orbit")) {
285
+ orbitNumber = parseFloat(getComputedStyle(this).getPropertyValue("--o-orbit-number"));
286
+ size = parseFloat(getComputedStyle(this).getPropertyValue("--o-size-ratio"));
287
+ const arcHeight = orbitRadius / orbitNumber * size - strokeWidth + 0.3;
288
+ const arcHeightPercentage = arcHeight / 2 * 100 / orbitRadius / 2;
289
+ const gap = parseFloat(getComputedStyle(this).getPropertyValue("--o-gap"));
290
+ if (this.classList.contains("outer-orbit")) {
291
+ innerOuter = arcHeightPercentage;
292
+ } else if (this.classList.contains("quarter-outer-orbit")) {
293
+ innerOuter = arcHeightPercentage * -0.5;
294
+ } else if (this.classList.contains("inner-orbit")) {
295
+ innerOuter = arcHeightPercentage * -1;
296
+ } else if (this.classList.contains("quarter-inner-orbit")) {
297
+ innerOuter = arcHeightPercentage * 0.5;
298
+ } else {
498
299
  innerOuter = 0;
499
300
  }
500
- if (this.classList.contains("quarter-inner-orbit")) {
501
- innerOuter = strokeWithPercentage * 0.75;
502
- }
503
- const realRadius = 50 + innerOuter - strokeWithPercentage;
504
- const textAngle = calcularExpresionCSS2(rawAngle);
301
+ const realRadius = 50 + innerOuter;
505
302
  return {
506
303
  orbitRadius,
507
- strokeWidth,
304
+ arcHeight,
508
305
  realRadius,
306
+ gap,
307
+ arcAngle,
308
+ shape,
509
309
  length,
510
310
  fontSize,
511
- gap,
512
- textAngle,
513
311
  flip,
312
+ fitRange,
514
313
  textAnchor,
515
- lineCap,
516
- fitRange
314
+ arcHeightPercentage,
315
+ innerOuter,
316
+ orbitNumber,
317
+ size,
318
+ strokeWidth
517
319
  };
518
320
  }
519
- calculateAngle() {
520
- const { textAngle, gap } = this.getAttributes();
521
- return textAngle - gap;
321
+ getProgressAngle(maxAngle, value) {
322
+ const progress = value;
323
+ const maxValue = parseFloat(this.getAttribute("max")) || 100;
324
+ return progress / maxValue * maxAngle;
325
+ }
326
+ calculateArcParameters() {
327
+ const { arcAngle, realRadius, gap, arcHeightPercentage, orbitNumber, shape, strokeWidth } = this.getAttributes();
328
+ const radius = realRadius;
329
+ let startX, startY, endX, endY, largeArcFlag, startX1, startY1, endX1, endY1, dShape, pointX, pointX1, pointY, pointY1;
330
+ let offset = Math.PI / 2;
331
+ let stroke = strokeWidth;
332
+ let fangle = arcAngle * Math.PI / 180;
333
+ let bigRadius = radius + arcHeightPercentage;
334
+ let smallRadius = radius - arcHeightPercentage !== 0 ? radius - arcHeightPercentage : radius;
335
+ let bigGap = (gap * 2 + stroke * 2) / orbitNumber / 2 / bigRadius;
336
+ let smallGap = (gap * 2 + stroke * 2) / orbitNumber / 2 / smallRadius;
337
+ let startAngle = bigGap - offset;
338
+ let endAngle = fangle - bigGap - offset;
339
+ let startAngle1 = smallGap - offset;
340
+ let endAngle1 = fangle - smallGap - offset;
341
+ startX = 50 + bigRadius * Math.cos(startAngle);
342
+ startY = 50 + bigRadius * Math.sin(startAngle);
343
+ endX = 50 + bigRadius * Math.cos(endAngle);
344
+ endY = 50 + bigRadius * Math.sin(endAngle);
345
+ pointX = 50 + bigRadius * Math.cos(endAngle + 3 * Math.PI / 180);
346
+ pointY = 50 + bigRadius * Math.sin(endAngle + 3 * Math.PI / 180);
347
+ startX1 = 50 + smallRadius * Math.cos(startAngle1);
348
+ startY1 = 50 + smallRadius * Math.sin(startAngle1);
349
+ endX1 = 50 + smallRadius * Math.cos(endAngle1);
350
+ endY1 = 50 + smallRadius * Math.sin(endAngle1);
351
+ pointX1 = 50 + smallRadius * Math.cos(endAngle1 + 3 * Math.PI / 180);
352
+ pointY1 = 50 + smallRadius * Math.sin(endAngle1 + 3 * Math.PI / 180);
353
+ largeArcFlag = arcAngle <= 180 ? 0 : 1;
354
+ dShape = `M ${startX},${startY} A ${bigRadius},${bigRadius} 0 ${largeArcFlag} 1 ${endX},${endY}`;
355
+ if (shape === "arrow")
356
+ dShape += `L ${(pointX + pointX1) / 2} ${(pointY + pointY1) / 2} `;
357
+ if (shape === "circle" || shape === "bullet")
358
+ dShape += `A ${arcHeightPercentage}, ${arcHeightPercentage} 0 0 1 ${endX1},${endY1} `;
359
+ dShape += `L ${endX1} ${endY1}`;
360
+ dShape += `A ${smallRadius},${smallRadius} 0 ${largeArcFlag} 0 ${startX1},${startY1}`;
361
+ if (shape === "circle")
362
+ dShape += `A ${arcHeightPercentage}, ${arcHeightPercentage} 0 0 1 ${startX},${startY} `;
363
+ if (shape === "bullet")
364
+ dShape += `A ${arcHeightPercentage}, ${arcHeightPercentage} 0 0 0 ${startX},${startY} `;
365
+ if (shape === "arrow")
366
+ dShape += `L ${startX1 + 3} ${(startY + startY1) / 2} `;
367
+ dShape += `Z`;
368
+ return { dShape };
522
369
  }
523
- calculateArcParameters(angle, realRadius, gap, flip) {
524
- const radiusX = realRadius / 1;
525
- const radiusY = realRadius / 1;
526
- let startX, startY, endX, endY, largeArcFlag, d;
370
+ calculateTextArcParameters() {
371
+ const { arcAngle, realRadius, gap, flip } = this.getAttributes();
372
+ const radius = realRadius;
373
+ let startX, startY, endX, endY, largeArcFlag, dPath, sweepFlag;
374
+ let adjustedGap = gap * 0.5;
375
+ sweepFlag = flip ? 0 : 1;
376
+ largeArcFlag = arcAngle <= 180 ? 0 : 1;
377
+ let coordX1 = 50 + radius * Math.cos((-90 + adjustedGap) * (Math.PI / 180));
378
+ let coordY1 = 50 + radius * Math.sin((-90 + adjustedGap) * (Math.PI / 180));
379
+ let coordX2 = 50 + radius * Math.cos((arcAngle - 90 - adjustedGap) * Math.PI / 180);
380
+ let coordY2 = 50 + radius * Math.sin((arcAngle - 90 - adjustedGap) * Math.PI / 180);
527
381
  if (flip) {
528
- startX = 50 - gap + radiusX * Math.cos(-Math.PI / 2);
529
- startY = 50 + radiusY * Math.sin(-Math.PI / 2);
530
- endX = 50 + radiusX * Math.cos((270 - angle) * Math.PI / 180);
531
- endY = 50 + radiusY * Math.sin((270 - angle) * Math.PI / 180);
532
- largeArcFlag = angle <= 180 ? 0 : 1;
533
- d = `M ${startX},${startY} A ${radiusX},${radiusY} 0 ${largeArcFlag} 0 ${endX},${endY}`;
382
+ startX = coordX2;
383
+ startY = coordY2;
384
+ endX = coordX1;
385
+ endY = coordY1;
534
386
  } else {
535
- startX = 50 + gap + radiusX * Math.cos(-Math.PI / 2);
536
- startY = 50 + radiusY * Math.sin(-Math.PI / 2);
537
- endX = 50 + radiusX * Math.cos((angle - 90) * Math.PI / 180);
538
- endY = 50 + radiusY * Math.sin((angle - 90) * Math.PI / 180);
539
- largeArcFlag = angle <= 180 ? 0 : 1;
540
- d = `M ${startX},${startY} A ${radiusX},${radiusY} 0 ${largeArcFlag} 1 ${endX},${endY}`;
387
+ startX = coordX1;
388
+ startY = coordY1;
389
+ endX = coordX2;
390
+ endY = coordY2;
541
391
  }
542
- return { startX, startY, endX, endY, largeArcFlag, d };
392
+ dPath = `M ${startX},${startY} A ${radius},${radius} 0 ${largeArcFlag} ${sweepFlag} ${endX},${endY}`;
393
+ return { dPath };
543
394
  }
544
395
  };
545
- function calcularExpresionCSS2(cssExpression) {
546
- const match = cssExpression.match(/calc\(\s*([\d.]+)deg\s*\/\s*\(\s*(\d+)\s*-\s*(\d+)\s*\)\s*\)/);
396
+ function calcularExpresionCSS(cssExpression) {
397
+ const match = cssExpression.match(
398
+ /calc\(\s*([\d.]+)deg\s*\/\s*\(\s*(\d+)\s*-\s*(\d+)\s*\)\s*\)/
399
+ );
547
400
  if (match) {
548
401
  const value = parseFloat(match[1]);
549
402
  const divisor = parseInt(match[2]) - parseInt(match[3]);
@@ -570,7 +423,6 @@
570
423
  childElements.forEach((childElement) => {
571
424
  let gravityForce = getComputedStyle(childElement).getPropertyValue("--o-force");
572
425
  let forceRatio = width / 500;
573
- console.log(gravityForce, forceRatio, parseFloat(gravityForce) * forceRatio);
574
426
  childElement.style.setProperty("--o-force-ratio", `${forceRatio}`);
575
427
  });
576
428
  } else {
@@ -583,8 +435,11 @@
583
435
  };
584
436
 
585
437
  // src/orbit.js
586
- customElements.define("o-progress", OrbitProgress);
587
- customElements.define("o-arc", OrbitArc);
588
- customElements.define("o-text", OrbitText);
438
+ if (!customElements.get("o-progress")) {
439
+ customElements.define("o-progress", OrbitProgress);
440
+ }
441
+ if (!customElements.get("o-arc")) {
442
+ customElements.define("o-arc", OrbitArc);
443
+ }
589
444
  window.Orbit = Orbit;
590
445
  })();