@massimo-cassandro/minimo 1.18.1 → 1.18.2
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/charts/TODO charts/1a-vers DA RIFATTORIZZARE/index.js +92 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/hbars.js +356 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/pie.js +245 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/radial-bars.js +177 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/rating-display.js +835 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/settimanale-mensile-src/costruzione-assi.js +212 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/settimanale-mensile-src/costruzione-linee.js +101 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/settimanale-mensile-src/defaults.js +185 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/settimanale-mensile-src/display-current.js +27 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/settimanale-mensile-src/grid-areas.js +129 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/settimanale-mensile-src/parse-opts.js +64 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/settimanale-mensile-src/paths-setup.js +73 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/settimanale-mensile.js +126 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/signal-bars.js +290 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/week-utils.js +122 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/browser-test/src/hbars-test.js +52 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/browser-test/src/mcn-test.js +74 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/browser-test/src/pie-test.js +16 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/browser-test/src/radial-bars-test.js +48 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/browser-test/src/settimanale-mensile-dati-settimanale.js +426 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/browser-test/src/settimanale-mensile-test.js +260 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/browser-test/src/signal-bars-test.js +64 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/node-test/node-test.mjs +86 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/node-test/src/hBars-node-test.mjs +40 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/node-test/src/lines-node-test.mjs +73 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/node-test/src/mcn-node-test.mjs +64 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/node-test/src/pie-node-test.mjs +12 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/node-test/src/radialsBar-node-test.mjs +44 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/node-test/src/settimanale-mensile-node-test.mjs +258 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/node-test/src/signalBars-node-test.mjs +36 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/test-readme.md +24 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/textToPath-test.mjs +14 -0
- package/charts/TODO charts/???/InfoBox.js +456 -0
- package/charts/TODO charts/???/README-upg OLD/342/206/222NEW.md" +53 -0
- package/charts/TODO charts/???/README.md +1 -0
- package/charts/TODO charts/???/TODO.md +39 -0
- package/charts/TODO charts/???/base-cfg.js +66 -0
- package/charts/TODO charts/???/rating-displayOLD.js +837 -0
- package/charts/TODO charts/docs/TODO.md +1 -0
- package/charts/TODO charts/docs/costruzione display rating.md +145 -0
- package/charts/TODO charts/test/node-test.mjs +92 -0
- package/charts/TODO charts/test/test-readme.md +23 -0
- package/charts/TODO charts/test/test-src/rating-display-extra-test.js +132 -0
- package/charts/TODO charts/test/test-src/rating-display-test.js +155 -0
- package/charts/TODO charts/test/textToPath-test.mjs +14 -0
- package/charts/TODO.md +1 -1
- package/package.json +1 -1
- package/snippets/flash-messages.html.twig +34 -0
- package/src/components/unsplash-page/unsplash-page.js +3 -6
- package/src/components/unsplash-page/unsplash-page.module.css +11 -6
|
@@ -0,0 +1,835 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* rating display 1a vers
|
|
3
|
+
*
|
|
4
|
+
* Mostra un indicatore tipo contachilometri su una scala da 1 a 4 o 5
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
export async function ratingDisplay({
|
|
9
|
+
|
|
10
|
+
// SECTION args
|
|
11
|
+
|
|
12
|
+
/** container (selettore o elemento DOM), se null viene restituito il codice SVG */
|
|
13
|
+
container = null,
|
|
14
|
+
|
|
15
|
+
/** se true aggiunge width e height */
|
|
16
|
+
addSvgSize = true,
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
/** eventuali classi da aggiungere all'elemento svg */
|
|
20
|
+
svgClassName = null,
|
|
21
|
+
|
|
22
|
+
/** modalità debug, se attiva mostra dei riferimenti grafici */
|
|
23
|
+
debug = false,
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
valore da rappresentare
|
|
27
|
+
in base a questo viene assegnato il posizionamento rispetto alla scala:
|
|
28
|
+
1-1,99 : prima fascia
|
|
29
|
+
2-2,99 : seconda ...
|
|
30
|
+
La scala parte da 1
|
|
31
|
+
L'ultima porzione rappresenta tutti i valori >= 4 per la versione a 4 porzioni
|
|
32
|
+
e i valori >= 5 per l'altra
|
|
33
|
+
*/
|
|
34
|
+
displayValue = null,
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
Valore di partenza della scala
|
|
38
|
+
*/
|
|
39
|
+
displayScaleStartValue = 0,
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
se true, l'asticella viene posizionata al centro del colore corrispondente
|
|
43
|
+
se false, viene posizionata in proporzione al valore effettivo
|
|
44
|
+
*/
|
|
45
|
+
displayValueForceCenter = false,
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
fill, traccia e classe dello sfondo del display principale
|
|
49
|
+
oggetto analogo a
|
|
50
|
+
{
|
|
51
|
+
fill: null,
|
|
52
|
+
strokeWidth: null,
|
|
53
|
+
strokeColor: null,
|
|
54
|
+
className: null,
|
|
55
|
+
}
|
|
56
|
+
*/
|
|
57
|
+
displayArc = null,
|
|
58
|
+
|
|
59
|
+
/** numero di porzioni del tachimetro */
|
|
60
|
+
scale = 5, // 4 o 5
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
colori da applicare alle porzioni del tachimetro. Se non impostati vengono usati quelli di base
|
|
64
|
+
I colori vengono assegnati agli elementi della scala secondo il loro ordine, a partire dal proimo a sinistra
|
|
65
|
+
Se un colore non è presente viene usato il nero (#000)
|
|
66
|
+
*/
|
|
67
|
+
scaleColors = null,
|
|
68
|
+
|
|
69
|
+
/** eventuale classe da applicare agli elementi della scala */
|
|
70
|
+
scaleClassName = null,
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
segni di separazione degli elementi della scala
|
|
74
|
+
vengono aggiunti anche `stroke-width="1" fill="none" stroke-linecap="butt"`
|
|
75
|
+
se `scaleticksColor` è null, vengono usati gli stessi colori di `scaleColors`
|
|
76
|
+
*/
|
|
77
|
+
scaleticksColor = null,
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
asticella
|
|
81
|
+
*/
|
|
82
|
+
rodColor = '#000',
|
|
83
|
+
rodClassName = null,
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
etichetta principale
|
|
87
|
+
se presente è un array in cui ogni elemento corrisponde ad una riga (max 2)
|
|
88
|
+
dell'etichetta:
|
|
89
|
+
|
|
90
|
+
displayLabel: [
|
|
91
|
+
{
|
|
92
|
+
label: <text> || null,
|
|
93
|
+
font: obj || null, // oggetto analogo a this.defaults.font
|
|
94
|
+
fill: <color>,
|
|
95
|
+
fontFilePath: path // percorso al file del font, utilizzato se `this.textToPath === true`,
|
|
96
|
+
},
|
|
97
|
+
{...}
|
|
98
|
+
]
|
|
99
|
+
*/
|
|
100
|
+
displayLabel = null,
|
|
101
|
+
|
|
102
|
+
/** distanza della prima riga di etichetta dalla base dell'asticella */
|
|
103
|
+
displayLabelTopMargin = 4,
|
|
104
|
+
|
|
105
|
+
/** distanza tra le due righe dell'etichetta */
|
|
106
|
+
displayLabelRowGap = 2,
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
// =>> minidisplay
|
|
110
|
+
/**
|
|
111
|
+
minidisplay
|
|
112
|
+
se impostato è un array di uno o due elementi, in cui ognuno di questo
|
|
113
|
+
è un oggetto così impostato:
|
|
114
|
+
|
|
115
|
+
miniDisplay = [
|
|
116
|
+
{
|
|
117
|
+
position: 'sx' | 'dx' (aliases: left | right),
|
|
118
|
+
value: number,
|
|
119
|
+
type: 'gauge' || 'value' // gauge = mini tachimetro, value: mostra il valore indicato in value
|
|
120
|
+
typeValueFont: obj || null // oggetto analogo a quelli definito in displayLabel per la rappresentazione
|
|
121
|
+
// di `type: value`. Se typeValueFont.label non è presente, viene utilizzato
|
|
122
|
+
// `value` (arrotondato all'intero)
|
|
123
|
+
mdLabel: array || null // array di oggetti (uno per ogni riga di etichetta) analogo a quello
|
|
124
|
+
// indicato nel display principale (displayLabel)
|
|
125
|
+
|
|
126
|
+
mdArc: { // oggetto simile a displayArc, è relativo all'arco che avvolge il mini display
|
|
127
|
+
fill: null,
|
|
128
|
+
strokeWidth: null,
|
|
129
|
+
strokeColor: null,
|
|
130
|
+
className: null,
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
...
|
|
134
|
+
],
|
|
135
|
+
|
|
136
|
+
se
|
|
137
|
+
*/
|
|
138
|
+
miniDisplay = null,
|
|
139
|
+
|
|
140
|
+
/** distanza dalla base del display principale */
|
|
141
|
+
miniDisplayTopMargin = 0,
|
|
142
|
+
|
|
143
|
+
/** distanza della prima riga di etichette dalla base del minidisplay */
|
|
144
|
+
miniDisplayLabelTopMargin = 0,
|
|
145
|
+
|
|
146
|
+
/** distanza tra le due righe dell'etichetta */
|
|
147
|
+
miniDisplayLabelRowGap = 2,
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
animation = false,
|
|
151
|
+
// animation_ms = 100, // number
|
|
152
|
+
// animation_fps = 60, // number
|
|
153
|
+
|
|
154
|
+
// !SECTION
|
|
155
|
+
|
|
156
|
+
}) {
|
|
157
|
+
|
|
158
|
+
try {
|
|
159
|
+
|
|
160
|
+
scaleColors??= this.defaults.colors;
|
|
161
|
+
|
|
162
|
+
// 30 gradi in radianti
|
|
163
|
+
// ampiezza dell'angolo della parte eccedente il raggio della circonferenza che include l'arco di cerchio
|
|
164
|
+
const rad30 = this.utils.toRadians(30),
|
|
165
|
+
|
|
166
|
+
// assicura che il valore sia entro i limiti gestiti dal grafico
|
|
167
|
+
getSanitizedColorIndex = value => Math.max(
|
|
168
|
+
0,
|
|
169
|
+
Math.min(
|
|
170
|
+
scale - 1,
|
|
171
|
+
Math.floor(value) - displayScaleStartValue
|
|
172
|
+
)
|
|
173
|
+
),
|
|
174
|
+
getColorFromValue = value => scaleColors[getSanitizedColorIndex(value)]
|
|
175
|
+
;
|
|
176
|
+
|
|
177
|
+
// =>> sizes
|
|
178
|
+
|
|
179
|
+
const sizes = {
|
|
180
|
+
// display principale
|
|
181
|
+
mainDisplay: {
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
// TODO il raggio deve considerare lo spessore della traccia per la scala non è costruita dinamicamente
|
|
185
|
+
// ripristinare il raggio statico se la scala (e l'asticella) vengono generate dinamicamente
|
|
186
|
+
|
|
187
|
+
// r: 110,
|
|
188
|
+
get r() {
|
|
189
|
+
return 110 - ((displayArc?.strokeWidth??0) / 2);
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
get w() {
|
|
193
|
+
return this.r * 2 +
|
|
194
|
+
// spessore traccia arco esterno, se presente
|
|
195
|
+
(displayArc?.strokeWidth??0);
|
|
196
|
+
},
|
|
197
|
+
/*
|
|
198
|
+
altezza dell'area del display
|
|
199
|
+
è pari al raggio + la distanza corrispondente ad uno spostamento di 30°
|
|
200
|
+
(l'arco di cerchio dell'area display è di 240°),
|
|
201
|
+
distanza che corrisponde al centro di rotazione dell'asticella.
|
|
202
|
+
La base dell'area del display principale è quindi la corda posizionata agli estremi dell'arco
|
|
203
|
+
*/
|
|
204
|
+
get h() { return this.r + ( this.r * Math.sin(rad30) ) +
|
|
205
|
+
// spessore traccia arco esterno, se presente
|
|
206
|
+
((displayArc?.strokeWidth??0) / 2);
|
|
207
|
+
},
|
|
208
|
+
|
|
209
|
+
/*
|
|
210
|
+
centro di rotazione dell'asticella
|
|
211
|
+
corrisponde al centro della circonferenza che include l'arco dell'area display
|
|
212
|
+
viene considerato anche l'eventuale spessore dell'arco
|
|
213
|
+
*/
|
|
214
|
+
get cx() {
|
|
215
|
+
return this.r + ((displayArc?.strokeWidth??0) / 2);
|
|
216
|
+
},
|
|
217
|
+
get cy() {
|
|
218
|
+
return this.r + ((displayArc?.strokeWidth??0) / 2);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
// =>> dimensione dell'intero svg
|
|
224
|
+
sizes.mainSvg = {
|
|
225
|
+
w: sizes.mainDisplay.w,
|
|
226
|
+
h: sizes.mainDisplay.h // altezza provvisoria, andrà ricalcolata dopo il rendering dei miniDisplay
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
// =>> verifiche e impostazioni di base
|
|
230
|
+
if(displayValue == null || typeof displayValue !== 'number') {
|
|
231
|
+
throw '`displayValue` is requested and must be a number';
|
|
232
|
+
}
|
|
233
|
+
if([4,5].indexOf(scale) === -1) {
|
|
234
|
+
throw '`scale` must be 4 or 5';
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
displayValue = Math.min(displayValue, scale + .99);
|
|
238
|
+
|
|
239
|
+
/*
|
|
240
|
+
la scala parte da 1 e arriva a `scale` (viene tolta una piccola
|
|
241
|
+
porzione finale per maggiore precisione)
|
|
242
|
+
*/
|
|
243
|
+
const parsedDisplayValue = displayValueForceCenter? Math.floor(displayValue) + .499 : displayValue;
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
// =>> animazione e posizione iniziale dell'asticella (rod)
|
|
247
|
+
let rotazioneAsticella = 0;
|
|
248
|
+
|
|
249
|
+
if(animation) {
|
|
250
|
+
|
|
251
|
+
// TODO animazione
|
|
252
|
+
// const display_animation = () => {
|
|
253
|
+
// const runAnimation = () => {
|
|
254
|
+
|
|
255
|
+
// const animationStepValue = parsedDisplayValue / animation_ms;
|
|
256
|
+
|
|
257
|
+
// let fpsInterval = animation_ms / animation_fps,
|
|
258
|
+
// currentDisplayValue = displayScaleStartValue, // valore iniziale. La scala parte da 1
|
|
259
|
+
// startTimestamp = Date.now(),
|
|
260
|
+
// animationEnd = false;
|
|
261
|
+
|
|
262
|
+
// const step = () => {
|
|
263
|
+
// let now = Date.now(),
|
|
264
|
+
// elapsed = now - startTimestamp;
|
|
265
|
+
|
|
266
|
+
// currentDisplayValue = Math.min(currentDisplayValue, parsedDisplayValue);
|
|
267
|
+
|
|
268
|
+
// if(currentDisplayValue >= parsedDisplayValue) {
|
|
269
|
+
// animationEnd = true;
|
|
270
|
+
// }
|
|
271
|
+
|
|
272
|
+
// // request another frame
|
|
273
|
+
// const animationRequest = window.requestAnimationFrame(step);
|
|
274
|
+
|
|
275
|
+
// // if enough time has elapsed, draw the next frame
|
|
276
|
+
// if (elapsed >= fpsInterval) {
|
|
277
|
+
|
|
278
|
+
// // Get ready for next frame by setting startTimestamp=now, but...
|
|
279
|
+
// // Also, adjust for fpsInterval not being multiple of 16.67
|
|
280
|
+
// startTimestamp = now - (elapsed % fpsInterval);
|
|
281
|
+
|
|
282
|
+
// svgElement.style.setProperty(
|
|
283
|
+
// '--rd-rot',
|
|
284
|
+
// Math.max(0, ((currentDisplayValue - displayScaleStartValue) * 240) / (scale - .001))
|
|
285
|
+
// );
|
|
286
|
+
|
|
287
|
+
// if(animationEnd) {
|
|
288
|
+
// window.cancelAnimationFrame(animationRequest);
|
|
289
|
+
|
|
290
|
+
// } else {
|
|
291
|
+
// currentDisplayValue += animationStepValue;
|
|
292
|
+
// // easing out a 2/3 del valore
|
|
293
|
+
// // if(currentDisplayValue >= parsedDisplayValue * 2/3) {
|
|
294
|
+
// // fpsInterval += 1;
|
|
295
|
+
// // }
|
|
296
|
+
|
|
297
|
+
// }
|
|
298
|
+
// }
|
|
299
|
+
|
|
300
|
+
// };// end step
|
|
301
|
+
|
|
302
|
+
// step();
|
|
303
|
+
// }; // end animazione_arco
|
|
304
|
+
|
|
305
|
+
// runAnimation();
|
|
306
|
+
|
|
307
|
+
// }; // end display_animation
|
|
308
|
+
|
|
309
|
+
// // NB la mutazione non è rilevata se la card è già visibile nel viewport
|
|
310
|
+
// // per questo è presente l'if iniziale
|
|
311
|
+
// if(inViewport) {
|
|
312
|
+
// display_animation();
|
|
313
|
+
// }
|
|
314
|
+
|
|
315
|
+
} else {
|
|
316
|
+
rotazioneAsticella = Math.max(0, ((parsedDisplayValue - displayScaleStartValue) * 240) / (scale - .001));
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// container element
|
|
320
|
+
this.utils.parseContainer(container);
|
|
321
|
+
|
|
322
|
+
// =>> definizione SVG
|
|
323
|
+
const svgCanvas = this.createSvgCanvas(container);
|
|
324
|
+
svgCanvas
|
|
325
|
+
// .viewbox(0, 0, sizes.mainSvg.w, sizes.mainSvg.h)
|
|
326
|
+
// .size(sizes.mainSvg.w, sizes.mainSvg.h)
|
|
327
|
+
.fill('none')
|
|
328
|
+
;
|
|
329
|
+
|
|
330
|
+
if(svgClassName) {
|
|
331
|
+
svgCanvas.addClass(svgClassName);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
// =>> gruppo Display Principale
|
|
336
|
+
const mainDisplayGroup = svgCanvas.group()
|
|
337
|
+
.attr({
|
|
338
|
+
'data-debug-info': debug? 'Gruppo Display Principale' : null,
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
// =>> function getDisplayArcPath
|
|
343
|
+
const getDisplayArcPath = (radius, cx, cy) => {
|
|
344
|
+
const startPointX = cx - (radius * Math.cos(rad30)),
|
|
345
|
+
startPointY = cy + (radius * Math.sin(rad30)),
|
|
346
|
+
|
|
347
|
+
endPointX = cx + (radius * Math.cos(rad30)),
|
|
348
|
+
endPointY = cy + (radius * Math.sin(rad30));
|
|
349
|
+
|
|
350
|
+
return `M ${startPointX},${startPointY} ` +
|
|
351
|
+
// rx ry x-axis-angle large-arc-flag sweep-flag end-x end-y
|
|
352
|
+
`A ${radius} ${radius} 0 1 1 ${endPointX} ${endPointY}`;
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
// =>> display principale
|
|
356
|
+
mainDisplayGroup.path(
|
|
357
|
+
// 'M14.5589,164.7274C5.2967,148.6096,0,129.9234,0,110,0,49.2487,49.2487,0,110,0s110,49.2487,110,110c0,20.0586-5.3689,38.8632-14.748,55.0552l-190.6931-.3278Z'
|
|
358
|
+
getDisplayArcPath(sizes.mainDisplay.r, sizes.mainDisplay.cx, sizes.mainDisplay.cy)
|
|
359
|
+
)
|
|
360
|
+
.attr({
|
|
361
|
+
'data-debug-info': debug? 'area display principale' : null,
|
|
362
|
+
class: displayArc?.className, // se il valore è null o undefined l'attributo viene ignorato
|
|
363
|
+
fill: displayArc?.fill?? 'none',
|
|
364
|
+
stroke: displayArc?.strokeColor,
|
|
365
|
+
'stroke-width': displayArc?.strokeWidth,
|
|
366
|
+
'stroke-linecap': displayArc?.strokeWidth? 'butt' : null,
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
// TODO generare dinamicamente
|
|
371
|
+
// =>> scale & ticks
|
|
372
|
+
|
|
373
|
+
let ticks_paths, scale_paths;
|
|
374
|
+
if(scale === 4) {
|
|
375
|
+
ticks_paths = [
|
|
376
|
+
'M31.8145,64.3924l-12.5627-7.253',
|
|
377
|
+
'M110.2255,31.2336V4.6702',
|
|
378
|
+
'M174.4747,72.6224l26.6597-15.3919'
|
|
379
|
+
];
|
|
380
|
+
|
|
381
|
+
scale_paths = [
|
|
382
|
+
'M25.1449,65.1604l-7.8217-4.5158C1.0679,91.4936,.5203,129.7554,19.2431,162.1841l-.0406-.3084c-14.0813-33.5175-11.9978-69.7327,5.9424-96.7153Z',
|
|
383
|
+
'M106.2255,4.745c-16.5541,.6089-33.2051,5.1472-48.5497,14.0065-16.5527,9.5566-29.5166,22.9407-38.4241,38.3877l8.1965,4.7322c7.0425-9.5853,16.1881-17.8798,27.4637-24.2736,16.1538-9.16,33.9923-12.8843,51.3135-11.7545V4.745Z',
|
|
384
|
+
'M199.0645,53.8066C179.2813,22.2909,145.2283,4.7195,110.2255,4.6702V26.1936c26.4244,2.8778,51.228,17.0771,66.4696,40.528l22.3694-12.915Z',
|
|
385
|
+
'M201.1344,57.2305l-22.3293,12.8918c.0073,.0126,.0153,.0248,.0227,.0374,11.402,19.8312,12.2809,44.9971,.02,66.2336-1.9507,3.3787-4.1538,6.5209-6.5719,9.4163l28.9064,16.2815c18.0334-31.3837,19.3337-71.2517-.0479-104.8605Z'
|
|
386
|
+
];
|
|
387
|
+
|
|
388
|
+
} else { // 5
|
|
389
|
+
ticks_paths = [
|
|
390
|
+
'M22.1717,81.0456l-11.8401-3.8471',
|
|
391
|
+
'M76.5125,33.9593l-9.0032-20.2213',
|
|
392
|
+
'M140.9257,40.7459l12.0048-26.963',
|
|
393
|
+
'M180.4367,86.9106l29.6283-9.6269'
|
|
394
|
+
];
|
|
395
|
+
|
|
396
|
+
scale_paths = [
|
|
397
|
+
'M15.9428,83.2275l-6.7733-2.2007c-7.4723,26.3461-4.7006,55.5677,10.0736,81.1573l-.0406-.3084c-11.1296-26.4916-12.1697-54.674-3.2596-78.6482Z',
|
|
398
|
+
'M63.8892,15.4414c-2.0916,1.0298-4.1652,2.1275-6.2134,3.3101-23.385,13.5013-39.6072,34.641-47.3442,58.447l7.0957,2.3055c7.2439-17.1207,19.7513-31.8504,37.4847-41.9061,5.0895-2.886,10.3474-5.2258,15.7025-7.0513l-6.7253-15.1052Z',
|
|
399
|
+
'M149.2476,12.2204C123.5877,1.9537,94.1199,1.8658,67.5094,13.7379l6.9424,15.593c21.8262-6.3824,44.9893-4.3134,64.9426,5.0201l9.8533-22.1306Z',
|
|
400
|
+
'M184.0155,81.542l24.7449-8.04c-2.0469-5.5565-4.5906-11.0154-7.6519-16.3178-11.5244-19.9607-28.6157-34.6992-48.178-43.4012l-9.9482,22.3439c14.4784,7.5615,27.0454,19.0628,35.8455,34.0328,2.0891,3.6336,3.8213,7.4476,5.1877,11.3823Z',
|
|
401
|
+
'M185.2117,85.3591c4.668,16.5795,2.9308,34.935-6.364,51.0341-1.9507,3.3787-4.1538,6.5209-6.5719,9.4163l28.9064,16.2815c14.5532-25.327,18.2002-56.1781,8.8828-84.8073l-24.8533,8.0754Z'
|
|
402
|
+
];
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
const ticksGroup = mainDisplayGroup.group()
|
|
406
|
+
.attr({
|
|
407
|
+
'data-debug-info': debug? 'ticks' : null,
|
|
408
|
+
fill: 'none',
|
|
409
|
+
'stroke-width': .5,
|
|
410
|
+
'stroke-linecap': 'butt',
|
|
411
|
+
|
|
412
|
+
});
|
|
413
|
+
ticks_paths.forEach((p, idx) => {
|
|
414
|
+
ticksGroup.path(p)
|
|
415
|
+
.attr({
|
|
416
|
+
stroke: scaleticksColor? scaleticksColor : scaleColors?.[idx + 1]?? '#000',
|
|
417
|
+
});
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
const scaleGroup = mainDisplayGroup.group().attr({
|
|
421
|
+
'data-debug-info': debug? 'scales' : null,
|
|
422
|
+
class: scaleClassName,
|
|
423
|
+
stroke: 'none',
|
|
424
|
+
});
|
|
425
|
+
scale_paths.forEach((p, idx) => {
|
|
426
|
+
scaleGroup.path(p)
|
|
427
|
+
.attr({
|
|
428
|
+
fill: scaleColors?.[idx]?? '#000'
|
|
429
|
+
});
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
// =>> asticella
|
|
434
|
+
const rodGroup = mainDisplayGroup.group()
|
|
435
|
+
.attr({
|
|
436
|
+
'data-debug-info': debug? 'asticella' : null,
|
|
437
|
+
fill: rodColor,
|
|
438
|
+
class: rodClassName
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
// centro
|
|
442
|
+
|
|
443
|
+
// versione statica
|
|
444
|
+
// rodGroup.path('M120.5713,103.6898c3.3137,5.7395,1.3472,13.0786-4.3923,16.3923-5.7395,3.3137-13.0786,1.3472-16.3923-4.3923s-1.3472-13.0786,4.3923-16.3923c5.7395-3.3137,13.0786-1.3472,16.3923,4.3923Zm-13.8923-.0622c-3.348,1.933-4.4952,6.2141-2.5622,9.5622s6.2141,4.4952,9.5622,2.5622,4.4952-6.2141,2.5622-9.5622-6.2141-4.4952-9.5622-2.5622Z');
|
|
445
|
+
|
|
446
|
+
// versione con path calcolato
|
|
447
|
+
// https://www.smashingmagazine.com/2019/03/svg-circle-decomposition-paths/
|
|
448
|
+
const ringPath = ({cx, cy, outerRadius, innerRadius}) => {
|
|
449
|
+
|
|
450
|
+
return `M ${cx - outerRadius/2}, ${cy}`+
|
|
451
|
+
`a ${outerRadius/2},${outerRadius/2} 0 1,0 ${outerRadius},0 ` +
|
|
452
|
+
`a ${outerRadius/2},${outerRadius/2} 0 1,0 -${outerRadius},0 ` +
|
|
453
|
+
|
|
454
|
+
`M ${cx - innerRadius/2}, ${cy} ` +
|
|
455
|
+
`a ${innerRadius/2},${innerRadius/2} 0 1,0 ${innerRadius},0 ` +
|
|
456
|
+
`a ${innerRadius/2},${innerRadius/2} 0 1,0 -${innerRadius},0`;
|
|
457
|
+
};
|
|
458
|
+
|
|
459
|
+
rodGroup.path(ringPath({
|
|
460
|
+
cx: sizes.mainDisplay.cx,
|
|
461
|
+
cy: sizes.mainDisplay.cy,
|
|
462
|
+
outerRadius: 24,
|
|
463
|
+
innerRadius: 14
|
|
464
|
+
}))
|
|
465
|
+
.attr({'fill-rule': 'evenodd'});
|
|
466
|
+
|
|
467
|
+
// bbox del solo anello di base dell'asticella
|
|
468
|
+
// usato per il posizionamento delle etichette
|
|
469
|
+
const rodGroupBaseBbox = rodGroup.bbox();
|
|
470
|
+
|
|
471
|
+
// asta
|
|
472
|
+
// TODO generare dinamicamente
|
|
473
|
+
rodGroup.polygon('59.1813 139.0943 59.1813 139.0943 98.8572 108.491 105.5448 120.0899 59.1813 139.0943')
|
|
474
|
+
.transform({
|
|
475
|
+
|
|
476
|
+
origin: {
|
|
477
|
+
x: sizes.mainDisplay.cx,
|
|
478
|
+
y: sizes.mainDisplay.cy,
|
|
479
|
+
},
|
|
480
|
+
rotate: rotazioneAsticella
|
|
481
|
+
})
|
|
482
|
+
.attr({
|
|
483
|
+
'data-debug-info': debug? `Value: ${parsedDisplayValue}, color index: ${getSanitizedColorIndex(parsedDisplayValue)}, {Angolo: ${rotazioneAsticella}, Start value: ${displayScaleStartValue}` : null,
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
// =>> function setLabel
|
|
488
|
+
const setLabel = async ({
|
|
489
|
+
labelObj,
|
|
490
|
+
baseX,
|
|
491
|
+
baseY,
|
|
492
|
+
dy,
|
|
493
|
+
rowGap = 0, // ulteriore correzione tra le distanze delle due righe
|
|
494
|
+
parentEl = svgCanvas
|
|
495
|
+
}) => {
|
|
496
|
+
if(labelObj?.label) {
|
|
497
|
+
|
|
498
|
+
const [label_bbox, labelEl] = await this.createTextEl ({
|
|
499
|
+
text: labelObj.label,
|
|
500
|
+
textFill: labelObj.fill??= '#000',
|
|
501
|
+
fontAttr: labelObj.font??{},
|
|
502
|
+
fontFilePath: labelObj.fontFilePath,
|
|
503
|
+
parentElement: parentEl
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
// posizionamento Y
|
|
507
|
+
// dy è lo spostamento aggiuntivo pari all'altezza dell'eventuale riga precedente
|
|
508
|
+
const labelY = baseY + (dy? dy + rowGap : 0);
|
|
509
|
+
|
|
510
|
+
// posizionamento, al centro sotto l'asticella
|
|
511
|
+
labelEl.move(
|
|
512
|
+
baseX - label_bbox.width / 2,
|
|
513
|
+
labelY
|
|
514
|
+
)
|
|
515
|
+
.attr({
|
|
516
|
+
'data-debug-info': debug? `label “${labelObj.label}”` : null
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
return label_bbox.height;
|
|
520
|
+
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
|
|
524
|
+
// =>> displayLabel
|
|
525
|
+
if(displayLabelTopMargin != null && typeof displayLabelTopMargin !== 'number') {
|
|
526
|
+
throw '`displayLabelTopMargin` must be null or a number';
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
displayLabel??=[];
|
|
530
|
+
if(displayLabel.length > 2) {
|
|
531
|
+
throw 'No more than 2 `displayLabel` elements can be defined';
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
let prevLabelHeight = 0;
|
|
535
|
+
for await (const labelObj of displayLabel) {
|
|
536
|
+
|
|
537
|
+
prevLabelHeight = await setLabel({
|
|
538
|
+
labelObj: labelObj,
|
|
539
|
+
baseX: sizes.mainDisplay.cx,
|
|
540
|
+
baseY: rodGroupBaseBbox.y2 + (displayLabelTopMargin??0),
|
|
541
|
+
dy: prevLabelHeight,
|
|
542
|
+
rowGap: displayLabelRowGap,
|
|
543
|
+
parentEl: mainDisplayGroup
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// =>> ricalcolo altezza gruppo principale
|
|
548
|
+
const mainDisplayGroupBbox = mainDisplayGroup.bbox();
|
|
549
|
+
sizes.mainSvg.h = mainDisplayGroupBbox.y + mainDisplayGroupBbox.y2;
|
|
550
|
+
|
|
551
|
+
// SECTION miniDisplay
|
|
552
|
+
if(miniDisplayTopMargin != null && typeof miniDisplayTopMargin !== 'number') {
|
|
553
|
+
throw '`miniDisplayTopMargin` must be null or a number';
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
miniDisplay??=[];
|
|
557
|
+
if(miniDisplay.length > 2) {
|
|
558
|
+
throw 'No more than 2 `miniDisplay` elements can be defined';
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
let miniDisplayIdx = 1, miniDisplayMaxHeight = 0, mdArcHeight = null;
|
|
563
|
+
for await (const md of miniDisplay) {
|
|
564
|
+
|
|
565
|
+
|
|
566
|
+
const errorPrefix = `miniDisplay #${miniDisplayIdx}`;
|
|
567
|
+
|
|
568
|
+
// =>> controlli
|
|
569
|
+
['position', 'type', 'value'].forEach(item => {
|
|
570
|
+
if(md[item] == null) {
|
|
571
|
+
throw `${errorPrefix}: '${item}' is requested`;
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
if(['sx', 'dx', 'left', 'right'].indexOf(md.position) === -1) {
|
|
576
|
+
throw `${errorPrefix}: 'position' must be one of 'sx', 'dx', 'left' or 'right'`;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
if(typeof md.value !== 'number') {
|
|
580
|
+
throw `${errorPrefix}: 'value' must be a number`;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
if(['gauge', 'value'].indexOf(md.type) === -1) {
|
|
584
|
+
throw `${errorPrefix}: 'type' must be one of 'gauge' or 'value'`;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// default
|
|
588
|
+
md.mdArc ??= {};
|
|
589
|
+
md.mdArc.strokeWidth ??= 0;
|
|
590
|
+
|
|
591
|
+
|
|
592
|
+
// =>> dimensioni
|
|
593
|
+
const
|
|
594
|
+
// raggio circonferenza che include l'arco
|
|
595
|
+
mdRadius = 26,
|
|
596
|
+
|
|
597
|
+
mdWidrh = (mdRadius * 2) + (md.mdArc?.strokeWidth??0), // impegna sia la parte destra che la sinistra
|
|
598
|
+
|
|
599
|
+
// margine orizzontale dal bordo esterno dell'SVG
|
|
600
|
+
xMargin = 20,
|
|
601
|
+
|
|
602
|
+
// coordinate dell'origine del miniDisplay
|
|
603
|
+
mdOrigin = {
|
|
604
|
+
y: sizes.mainSvg.h + (miniDisplayTopMargin?? 0),
|
|
605
|
+
x: (md.position === 'sx' || md.position === 'left')
|
|
606
|
+
? xMargin
|
|
607
|
+
: sizes.mainSvg.w - xMargin - mdWidrh
|
|
608
|
+
}
|
|
609
|
+
;
|
|
610
|
+
|
|
611
|
+
|
|
612
|
+
// =>> mdGroup
|
|
613
|
+
const mdGroup = svgCanvas.group()
|
|
614
|
+
.attr({
|
|
615
|
+
'data-debug-info': debug? `miniDisplay #${miniDisplayIdx}` : null,
|
|
616
|
+
});
|
|
617
|
+
|
|
618
|
+
// =>> definizione arco
|
|
619
|
+
const
|
|
620
|
+
// coordinate del centro della circonferenza che include l'arco
|
|
621
|
+
mdArcCx= mdOrigin.x + mdRadius, // + md.mdArc.strokeWidth / 2,
|
|
622
|
+
mdArcCy= mdOrigin.y + mdRadius // + md.mdArc.strokeWidth / 2,
|
|
623
|
+
;
|
|
624
|
+
|
|
625
|
+
// minidisplay arc
|
|
626
|
+
mdGroup.path(getDisplayArcPath(mdRadius, mdArcCx, mdArcCy))
|
|
627
|
+
.attr({
|
|
628
|
+
'data-debug-info': debug? `miniDisplay #${miniDisplayIdx}: arco` : null,
|
|
629
|
+
class: md.mdArc.className, // se il valore è null o undefined l'attributo viene ignorato
|
|
630
|
+
fill: md.mdArc.fill?? 'none',
|
|
631
|
+
stroke: md.mdArc.strokeWidth > 0? md.mdArc.strokeColor : null,
|
|
632
|
+
'stroke-width': md.mdArc.strokeWidth > 0? md.mdArc.strokeWidth : null,
|
|
633
|
+
'stroke-linecap': md.mdArc.strokeWidth > 0? 'round' : null,
|
|
634
|
+
});
|
|
635
|
+
|
|
636
|
+
// altezza arco, per il posizionamento delle etichette
|
|
637
|
+
// viene misurato solo il primo arco, in modo che le etichette siano comq allineate
|
|
638
|
+
// se necessario, utilizzare il parametro miniDisplayLabelTopMargin per distanziare il testo dalla base dell'arco
|
|
639
|
+
if(mdArcHeight == null) {
|
|
640
|
+
mdArcHeight = mdGroup.bbox().height;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
|
|
644
|
+
// =>> modalità "value"
|
|
645
|
+
if(md.type === 'value') {
|
|
646
|
+
|
|
647
|
+
md.typeValueFont ??= {};
|
|
648
|
+
md.typeValueFont.label ??= String(Math.floor(md.value));
|
|
649
|
+
|
|
650
|
+
const [value_bbox, valueEl] = await this.createTextEl ({
|
|
651
|
+
text: md.typeValueFont.label,
|
|
652
|
+
textFill: md.typeValueFont.fill??= '#000',
|
|
653
|
+
fontAttr: md.typeValueFont.font??{},
|
|
654
|
+
fontFilePath: md.typeValueFont.fontFilePath,
|
|
655
|
+
parentElement: mdGroup
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
valueEl.move(
|
|
659
|
+
mdArcCx - value_bbox.w/2,
|
|
660
|
+
mdArcCy - value_bbox.h/2 - 2, // 2: spostamento basline verso l'alto
|
|
661
|
+
)
|
|
662
|
+
.attr({
|
|
663
|
+
'data-debug-info': debug? `miniDisplay #${miniDisplayIdx}: value` : null,
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
// =>> modalità "gauge"
|
|
667
|
+
} else {
|
|
668
|
+
|
|
669
|
+
// segmento indicatore colore
|
|
670
|
+
const segmentStrokeWidth = 6
|
|
671
|
+
// spazio segmento arco
|
|
672
|
+
,distanzaSegmentoArco = 2
|
|
673
|
+
// correzione raggio per dare spazio allo spessore della traccia
|
|
674
|
+
,segmentRadius = mdRadius - segmentStrokeWidth/2 - distanzaSegmentoArco
|
|
675
|
+
// ampiezza angolo che sottende il segmento circolare
|
|
676
|
+
// 30 è l'angolo del punto iniziale
|
|
677
|
+
,segmentAngle = this.utils.toRadians(240/scale - 30)
|
|
678
|
+
|
|
679
|
+
,startPointX = mdArcCx - (segmentRadius * Math.cos(rad30))
|
|
680
|
+
,startPointY = mdArcCy + (segmentRadius * Math.sin(rad30))
|
|
681
|
+
,endPointX = mdArcCx - (segmentRadius * Math.cos(segmentAngle))
|
|
682
|
+
,endPointY = mdArcCy - (segmentRadius * Math.sin(segmentAngle))
|
|
683
|
+
|
|
684
|
+
,segmentPath = `M ${startPointX},${startPointY} ` +
|
|
685
|
+
// rx ry x-axis-angle large-arc-flag sweep-flag end-x end-y
|
|
686
|
+
`A ${segmentRadius} ${segmentRadius} 0 0 1 ${endPointX} ${endPointY}`
|
|
687
|
+
|
|
688
|
+
,segmentGroup = mdGroup.group()
|
|
689
|
+
;
|
|
690
|
+
|
|
691
|
+
// =>> segmento mini display gauge
|
|
692
|
+
segmentGroup.path(segmentPath)
|
|
693
|
+
.attr({
|
|
694
|
+
stroke: getColorFromValue(md.value),
|
|
695
|
+
'stroke-width': segmentStrokeWidth,
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
// =>> anello mini asticella
|
|
699
|
+
const ringOuterRadius = 12;
|
|
700
|
+
mdGroup.path( ringPath({
|
|
701
|
+
cx: mdArcCx,
|
|
702
|
+
cy: mdArcCy,
|
|
703
|
+
outerRadius: ringOuterRadius,
|
|
704
|
+
innerRadius: 6
|
|
705
|
+
}))
|
|
706
|
+
.attr({'fill-rule': 'evenodd'})
|
|
707
|
+
.attr({
|
|
708
|
+
fill: rodColor,
|
|
709
|
+
class: rodClassName
|
|
710
|
+
});
|
|
711
|
+
|
|
712
|
+
// =>> mini asticella
|
|
713
|
+
// viene prima creata allineata con l'asse X del mini display e poi ruotata al centro della porzione d'inizio
|
|
714
|
+
// in seguito, la rotazione applicata al gruppo la porta nella posizione definitiva
|
|
715
|
+
segmentGroup.polygon(
|
|
716
|
+
`${mdArcCx - ringOuterRadius/2 + 2},${mdArcCy - 3} `+
|
|
717
|
+
`${mdArcCx - segmentRadius + 6},${mdArcCy} `+
|
|
718
|
+
`${mdArcCx - ringOuterRadius/2 + 2},${mdArcCy + 3}`
|
|
719
|
+
)
|
|
720
|
+
.attr({
|
|
721
|
+
fill: rodColor,
|
|
722
|
+
class: rodClassName
|
|
723
|
+
})
|
|
724
|
+
.transform({
|
|
725
|
+
origin: {
|
|
726
|
+
x: mdArcCx,
|
|
727
|
+
y: mdArcCy,
|
|
728
|
+
},
|
|
729
|
+
rotate: ((240/scale) / 2) - 30
|
|
730
|
+
})
|
|
731
|
+
;
|
|
732
|
+
|
|
733
|
+
segmentGroup.transform({
|
|
734
|
+
origin: {
|
|
735
|
+
x: mdArcCx,
|
|
736
|
+
y: mdArcCy,
|
|
737
|
+
},
|
|
738
|
+
rotate: (240/scale) * getSanitizedColorIndex(md.value) - displayScaleStartValue
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
// =>> label mini display
|
|
743
|
+
|
|
744
|
+
if(miniDisplayLabelTopMargin != null && typeof miniDisplayLabelTopMargin !== 'number') {
|
|
745
|
+
throw `${errorPrefix}: 'miniDisplayLabelTopMargin' must be null or a number`;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
md.mdLabel??=[];
|
|
749
|
+
if(md.mdLabel.length > 2) {
|
|
750
|
+
throw `${errorPrefix}: No more than 2 'mdLabel' elements can be defined`;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
|
|
754
|
+
let prevLabelHeight = 0;
|
|
755
|
+
for await (const labelObj of md.mdLabel) {
|
|
756
|
+
|
|
757
|
+
prevLabelHeight = await setLabel({
|
|
758
|
+
labelObj: labelObj,
|
|
759
|
+
baseX: mdArcCx,
|
|
760
|
+
baseY: mdOrigin.y + mdArcHeight + (miniDisplayLabelTopMargin??0),
|
|
761
|
+
dy: prevLabelHeight,
|
|
762
|
+
rowGap: miniDisplayLabelRowGap,
|
|
763
|
+
parentEl: mdGroup
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
// =>> indicatori per debug
|
|
770
|
+
if(debug) {
|
|
771
|
+
// centro mini display
|
|
772
|
+
const gap = 10;
|
|
773
|
+
const debug_group = mdGroup.group()
|
|
774
|
+
.attr({
|
|
775
|
+
'data-debug-info': 'centro mini display',
|
|
776
|
+
stroke: '#05923e',
|
|
777
|
+
fill: 'none',
|
|
778
|
+
'stroke-width': .5,
|
|
779
|
+
class: 'debug-info'
|
|
780
|
+
});
|
|
781
|
+
debug_group.line({x1: mdArcCx - gap, y1: mdArcCy, x2: mdArcCx + gap, y2: mdArcCy});
|
|
782
|
+
debug_group.line({x1: mdArcCx, y1: mdArcCy - gap, x2: mdArcCx, y2: mdArcCy + gap});
|
|
783
|
+
|
|
784
|
+
// origine mini display
|
|
785
|
+
// debug_group.line({x1: mdOrigin.x - gap, y1: mdOrigin.y, x2: mdOrigin.x + gap, y2: mdOrigin.y});
|
|
786
|
+
// debug_group.line({x1: mdOrigin.x, y1: mdOrigin.y - gap, x2: mdOrigin.x, y2: mdOrigin.y + gap});
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
// =>> ricalcolo miniDisplayMaxHeight
|
|
790
|
+
miniDisplayMaxHeight = Math.max(
|
|
791
|
+
miniDisplayMaxHeight,
|
|
792
|
+
mdGroup.bbox().h + (miniDisplayTopMargin?? 0) + md.mdArc.strokeWidth // strokeWidth: spessore traccia nel caso non ci sia testo
|
|
793
|
+
);
|
|
794
|
+
miniDisplayIdx++;
|
|
795
|
+
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
// !SECTION end miniDisplay
|
|
799
|
+
|
|
800
|
+
// =>> aggiornamento dimensioni SVG
|
|
801
|
+
sizes.mainSvg.h += miniDisplayMaxHeight;
|
|
802
|
+
// sizes.mainSvg.w = mainDisplayGroupBbox.w;
|
|
803
|
+
|
|
804
|
+
svgCanvas
|
|
805
|
+
.viewbox(0, 0, sizes.mainSvg.w, sizes.mainSvg.h);
|
|
806
|
+
|
|
807
|
+
if(addSvgSize) {
|
|
808
|
+
svgCanvas.size(sizes.mainSvg.w, sizes.mainSvg.h);
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
|
|
812
|
+
// indicatori per debug
|
|
813
|
+
if(debug) {
|
|
814
|
+
// centro display e rotazione asticella
|
|
815
|
+
const gap = sizes.mainDisplay.r;
|
|
816
|
+
const debug_group1 = svgCanvas.group()
|
|
817
|
+
.attr({
|
|
818
|
+
'data-debug-info': 'centro rotazione asticella',
|
|
819
|
+
stroke: '#e20613',
|
|
820
|
+
fill: 'none',
|
|
821
|
+
'stroke-width': .5,
|
|
822
|
+
class: 'debug-info'
|
|
823
|
+
});
|
|
824
|
+
debug_group1.line({x1: sizes.mainDisplay.cx - gap, y1: sizes.mainDisplay.cy, x2: sizes.mainDisplay.cx + gap, y2: sizes.mainDisplay.cy});
|
|
825
|
+
debug_group1.line({x1: sizes.mainDisplay.cx, y1: sizes.mainDisplay.cy - gap, x2: sizes.mainDisplay.cx, y2: sizes.mainDisplay.cy + gap});
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
if(!container) {
|
|
829
|
+
return svgCanvas.svg();
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
} catch(e) {
|
|
833
|
+
console.error( 'AdaCharts → ratingDisplay:', e ); // eslint-disable-line
|
|
834
|
+
}
|
|
835
|
+
}
|