@massimo-cassandro/minimo 1.1.3 → 1.3.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/charts/README.md +42 -0
- package/charts/TODO.md +2 -0
- package/charts/index.js +21 -0
- package/charts/src/bars.js +377 -0
- package/charts/src/goal.js +311 -0
- package/charts/src/helpers/cartesian-axis.js +254 -0
- package/charts/src/helpers/chart-utils.js +174 -0
- package/charts/src/helpers/core.js +25 -0
- package/charts/src/helpers/create-svg-canvas.js +25 -0
- package/charts/src/helpers/create-text-element.js +54 -0
- package/charts/src/helpers/default-chart-colors.js +17 -0
- package/charts/src/helpers/legenda.js +96 -0
- package/charts/src/helpers/parse-std-axis-opts.js +95 -0
- package/charts/src/helpers/svg-text-to-path.js +45 -0
- package/charts/src/lines.js +383 -0
- package/charts/src/rating-display/debug-tools.js +124 -0
- package/charts/src/rating-display/index.js +849 -0
- package/charts/src/rating-display/ratindDisplayAnimation.js +56 -0
- package/charts/src/rating-display/ratingDisplayUtils.js +102 -0
- package/package.json +3 -2
- package/src/css/dimensions.css +7 -0
- package/src/css/display.css +56 -0
- package/src/css/margin-padding.css +99 -0
- package/src/css/overflow.css +4 -0
- package/src/css/position.css +4 -0
- package/src/css/text.css +12 -2
- package/src/css/visibility.css +50 -0
- package/src/minimo.css +7 -1
- package/src/css/utilities.css +0 -210
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
import { parseStdAxisOpts } from './helpers/parse-std-axis-opts.js';
|
|
2
|
+
import { parseContainer } from './helpers/chart-utils.js';
|
|
3
|
+
import { cartesianAxis } from './helpers/cartesian-axis.js';
|
|
4
|
+
import { legenda } from './helpers/legenda.js';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
const default_lines_attrs = {
|
|
8
|
+
stroke: '#999',
|
|
9
|
+
'stroke-width': 1,
|
|
10
|
+
'shape-rendering': 'crispEdges',
|
|
11
|
+
'stroke-linecap': 'round',
|
|
12
|
+
fill: 'none'
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const default_font_attrs = {
|
|
16
|
+
// family: 'sans-serif',
|
|
17
|
+
size: 14,
|
|
18
|
+
// stretch: 'normal',
|
|
19
|
+
// style: 'normal',
|
|
20
|
+
// variant: 'normal',
|
|
21
|
+
weight: 400,
|
|
22
|
+
fill: '#999'
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const default_params = {
|
|
26
|
+
|
|
27
|
+
/** mostra info utili per il debug */
|
|
28
|
+
debug: false,
|
|
29
|
+
|
|
30
|
+
/** container (selettore o elemento DOM), se null viene restituito il codice SVG */
|
|
31
|
+
container: null,
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
larghezza e altezza del grafico (px),
|
|
35
|
+
Se il container è presente e i parametro `width` e `height` sono `null`,
|
|
36
|
+
vengono utilizzate le dimensioni del container.
|
|
37
|
+
Se uno dei due valori non è impostato o ricavabile, viene generato un errore.
|
|
38
|
+
NB: il padding del container viene considerato nelle dimensioni del grafico,
|
|
39
|
+
è preferibile non impostarlo.
|
|
40
|
+
Il valore 'auto' di height fa sì che l'altezza dell'svg sia calcolata sulla base
|
|
41
|
+
del numero di barre e dei valori `barsGap` e `barsHeight`
|
|
42
|
+
*/
|
|
43
|
+
width: null, // null || <value>
|
|
44
|
+
height: 300, // <value> || null || 'auto'
|
|
45
|
+
|
|
46
|
+
/** attributi facoltativi per l'svg (classe, ecc) */
|
|
47
|
+
svgAttrs: {},
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
valori numerici per la definizione delle linee
|
|
51
|
+
è un array di array, in cui ogni subarray contiene i valori di una singola linea
|
|
52
|
+
l'ordine di rapprsentazione delle linee segue il loro ordine nell'array,
|
|
53
|
+
ovvero l'ultima serie corrisponde alla linea rappresentata per ultima e quindi sopra le altre
|
|
54
|
+
*/
|
|
55
|
+
values: [],
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
etichette corrispondenti ai vari valori. Sono posizionate sull'asse X
|
|
59
|
+
*/
|
|
60
|
+
xLabels: [],
|
|
61
|
+
|
|
62
|
+
/** spazio extra attorno al bordo */
|
|
63
|
+
padding: 10,
|
|
64
|
+
|
|
65
|
+
/** suddivisioni asse Y */
|
|
66
|
+
stepY_count: 4,
|
|
67
|
+
|
|
68
|
+
/** px, altezza o larghezza ticks (secondo l'orientamento) */
|
|
69
|
+
ticksLength: 8,
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
opzioni per legenda come da componente legenda sono impostati automaticamente)
|
|
73
|
+
NB: l'elemento `items` viene generato dinamicamente:
|
|
74
|
+
`shape` è sempre impostato su line
|
|
75
|
+
`attrs` è ricavato dagli attributi delle linee dati
|
|
76
|
+
|
|
77
|
+
Per utilizzare le impostazioni di default, è sufficiente impostare i valori `items.text`
|
|
78
|
+
*/
|
|
79
|
+
legenda: {},
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
larghezza area etichette asse y
|
|
83
|
+
*/
|
|
84
|
+
yAxisLabelWidth: 60,
|
|
85
|
+
|
|
86
|
+
/** altezza area etichette asse x */
|
|
87
|
+
xAxisLabelHeight: 50,
|
|
88
|
+
|
|
89
|
+
/** titoli assi */
|
|
90
|
+
yAxisTitle: null,
|
|
91
|
+
yAxisTitleAttrs: {...default_font_attrs, size: 18},
|
|
92
|
+
yAxisTitleFontFilePath: null,
|
|
93
|
+
|
|
94
|
+
xAxisTitle: null,
|
|
95
|
+
xAxisTitleAttrs: {...default_font_attrs, size: 18},
|
|
96
|
+
xAxisTitleFontFilePath: null,
|
|
97
|
+
|
|
98
|
+
/** valori minimi e massimi per l'asse Y, se null vengono calcolati automaticamente */
|
|
99
|
+
max_value: null,
|
|
100
|
+
min_value: null,
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
classi e attributi dei vari elementi.
|
|
104
|
+
Per gli attributi, ogni variabile è un oggetto di attributi svg.js, es =
|
|
105
|
+
|
|
106
|
+
{
|
|
107
|
+
stroke: '#414141',
|
|
108
|
+
'stroke-width': 1,
|
|
109
|
+
'shape-rendering': 'crispEdges',
|
|
110
|
+
class: 'xxxx'
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
*/
|
|
114
|
+
axisAttrs: {...default_lines_attrs, 'stroke-width': 2},
|
|
115
|
+
ticksAttrs: default_lines_attrs,
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
griglia assi x e y, in corrispondenza dei ticks
|
|
119
|
+
*/
|
|
120
|
+
showXgrid: true, // griglia verticale
|
|
121
|
+
showYgrid: true, // griglia orizzontale
|
|
122
|
+
gridLinesAttrs: default_lines_attrs,
|
|
123
|
+
|
|
124
|
+
labelXAttrs: default_font_attrs, // contiene gli attributi fonts (come in MinimoCharts.defaults.font) e l'attributo `fill`
|
|
125
|
+
labelXFontFilePath: null, // percorso font per textToPath
|
|
126
|
+
|
|
127
|
+
labelYAttrs: default_font_attrs, // contiene gli attributi fonts (come in MinimoCharts.defaults.font) e l'attributo `fill`
|
|
128
|
+
labelYFontFilePath: null, // percorso font per textToPath
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
attributi delle varie linee dati
|
|
132
|
+
se l'oggetto `pointsAttrs`, dove presente, non è vuoto,
|
|
133
|
+
viene aggiunto un cerchio ad ogni punto della linea
|
|
134
|
+
(NB non aggiungere `cx` o cy`)
|
|
135
|
+
il valore `r` può essere un numero (valore uguale per tutti i punti) o un array
|
|
136
|
+
in cui ogni valore si apllica alla linea con lo stesso indice
|
|
137
|
+
*/
|
|
138
|
+
data_lines_attrs: {
|
|
139
|
+
...default_lines_attrs,
|
|
140
|
+
'stroke-width': 2
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
data_points_attrs: {
|
|
144
|
+
r: 4
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
/** colori delle linee */
|
|
148
|
+
data_colors: null,
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
spessori delle linee
|
|
152
|
+
Se null, viene utilizzato per tutte le linee il valore definito in data_lines_attrs,
|
|
153
|
+
altrimenti è un array, in cui ogni valore corrisponde allo spessore da assegnare
|
|
154
|
+
alla linea con lo stesso indice.
|
|
155
|
+
I valori `undefined` o `null` vengono ricondotti al default `data_lines_attrs['stroke-width']`
|
|
156
|
+
(in sua mancanza a `1`)
|
|
157
|
+
*/
|
|
158
|
+
data_lines_widths: null,
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
Funzione per formattare le etichette dei valori dell'asse Y.
|
|
164
|
+
Null per nessuna eleborazione.
|
|
165
|
+
La funzione di default assume che il valore sia di tipo numerico
|
|
166
|
+
*/
|
|
167
|
+
labelYFormatter: etiValue => Math.ceil(etiValue / 1e3)
|
|
168
|
+
.toLocaleString('it-IT', {
|
|
169
|
+
minimumFractionDigits: 0,
|
|
170
|
+
maximumFractionDigits: 0
|
|
171
|
+
}) +
|
|
172
|
+
(etiValue > 0? '\u2009K' : ''), // \u2009: thin space (https://www.compart.com/en/unicode/U+2009)
|
|
173
|
+
|
|
174
|
+
};
|
|
175
|
+
export async function lines(params) {
|
|
176
|
+
|
|
177
|
+
const chartInstance = this;
|
|
178
|
+
|
|
179
|
+
params = {...default_params, ...params};
|
|
180
|
+
params.data_colors??= chartInstance.defaults.colors;
|
|
181
|
+
|
|
182
|
+
try {
|
|
183
|
+
|
|
184
|
+
// controllo values
|
|
185
|
+
params.values.forEach(subarray => {
|
|
186
|
+
if(!Array.isArray(subarray)) {
|
|
187
|
+
throw 'L’elemento `values` deve essere un array di soli array';
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
const flatValues = params.values.flat(); // utilizzato anche in seguito
|
|
192
|
+
if(flatValues.filter(v => isNaN(v)).length) {
|
|
193
|
+
throw 'Tutti i valori dei sub-array di `values` devono essere numerici';
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
// container
|
|
198
|
+
[, params.width, params.height] = parseContainer({ container: params.container, width: params.width, height: params.height });
|
|
199
|
+
|
|
200
|
+
if(!params.width || !params.height) {
|
|
201
|
+
throw `width e/o height mancanti: width: ${params.width}, height: ${params.height}`;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// =>> ricalcolo data_lines_attrs (utilizzato anche per le linee della legenda)
|
|
205
|
+
const default_line_width = params.data_lines_attrs['stroke-width']?? 1;
|
|
206
|
+
|
|
207
|
+
// il ciclo è basato su params.values per essere certi che il numero di elementi coincida
|
|
208
|
+
params.data_lines_attrs = params.values.map((_, idx) => {
|
|
209
|
+
const thisColor = params.data_colors[idx],
|
|
210
|
+
thisLineWidth = (params.data_lines_widths??[])[idx]?? default_line_width;
|
|
211
|
+
|
|
212
|
+
return {
|
|
213
|
+
...default_lines_attrs,
|
|
214
|
+
...params.data_lines_attrs[idx]?? {},
|
|
215
|
+
stroke: thisColor,
|
|
216
|
+
'stroke-width': thisLineWidth
|
|
217
|
+
};
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
// =>> legenda
|
|
222
|
+
// costruzione delle opzioni per la legenda
|
|
223
|
+
const opts_legenda = {
|
|
224
|
+
|
|
225
|
+
...{
|
|
226
|
+
/** altezza legenda */
|
|
227
|
+
height: 20,
|
|
228
|
+
|
|
229
|
+
/** spazio tra gli elementi della legenda */
|
|
230
|
+
elements_gap: 25,
|
|
231
|
+
|
|
232
|
+
/** dimensioni delle forme della legenda (NB: solo linee) */
|
|
233
|
+
lines_width: 20,
|
|
234
|
+
|
|
235
|
+
/** attributi svg.js dei font del testo della legenda (null utilizza default) */
|
|
236
|
+
fontAttrs: {
|
|
237
|
+
fill: '#333',
|
|
238
|
+
'font-size': 14,
|
|
239
|
+
'font-weight': 400
|
|
240
|
+
},
|
|
241
|
+
fontFilePath: null,
|
|
242
|
+
},
|
|
243
|
+
|
|
244
|
+
...params.legenda
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
// legenda.items (elementi della legenda)
|
|
248
|
+
// il ciclo viene eseguito su params.data_lines_attrs per essere certi che il numero di elementi coincida
|
|
249
|
+
// è utilizzato in ordine inverso in modo che il primo elmento della legenda corrisponda alla linea in primo piano
|
|
250
|
+
opts_legenda.items = params.data_lines_attrs.toReversed().map((line_attr, idx) => {
|
|
251
|
+
const thisLegendaItem = params.legenda.items.toReversed()[idx]?? {};
|
|
252
|
+
return {
|
|
253
|
+
...thisLegendaItem,
|
|
254
|
+
shape: 'line',
|
|
255
|
+
attrs: {
|
|
256
|
+
...(thisLegendaItem.attrs?? {}),
|
|
257
|
+
...line_attr
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
// numero di step dell'asse X
|
|
264
|
+
const stepX_count = params.values.reduce((prev, curr) => Math.max(prev, curr.length), 0);
|
|
265
|
+
|
|
266
|
+
const svgCanvas = chartInstance.createSvgCanvas(params.container, params.debug)
|
|
267
|
+
.size(params.width, params.height)
|
|
268
|
+
.viewbox(0, 0, params.width, params.height)
|
|
269
|
+
.attr({...params.svgAttrs});
|
|
270
|
+
|
|
271
|
+
// pre-elaborazione e calcolo di alcuni elementi (chartArea)
|
|
272
|
+
// nuove variabili definite da parseStdAxisOpts
|
|
273
|
+
const {
|
|
274
|
+
max_value,
|
|
275
|
+
min_value,
|
|
276
|
+
chart_area,
|
|
277
|
+
stepY_value,
|
|
278
|
+
stepY_size,
|
|
279
|
+
stepX_size
|
|
280
|
+
} = parseStdAxisOpts({
|
|
281
|
+
max_value: params.max_value,
|
|
282
|
+
min_value: params.min_value,
|
|
283
|
+
values: flatValues,
|
|
284
|
+
legenda: opts_legenda,
|
|
285
|
+
padding: params.padding,
|
|
286
|
+
width: params.width,
|
|
287
|
+
height: params.height,
|
|
288
|
+
eti_asseX_height: params.xAxisLabelHeight,
|
|
289
|
+
eti_asseY_width: params.yAxisLabelWidth,
|
|
290
|
+
stepY_count: params.stepY_count,
|
|
291
|
+
stepX_count: stepX_count,
|
|
292
|
+
ticksLength: params.ticksLength,
|
|
293
|
+
}); // elaborazione standard
|
|
294
|
+
|
|
295
|
+
// =>> costruzione assi e griglia.
|
|
296
|
+
// Gli argomenti di cartesianAxis sono uguali a quelli di lines
|
|
297
|
+
// con l'aggiunta di quelli calcolati da parseStdAxisOpts
|
|
298
|
+
// non tutti sono necessari ma vengono passati lo stesso per comodità
|
|
299
|
+
const cartesianAxisGroup = await cartesianAxis(chartInstance, {
|
|
300
|
+
...params,
|
|
301
|
+
...{
|
|
302
|
+
max_value,
|
|
303
|
+
min_value,
|
|
304
|
+
chart_area,
|
|
305
|
+
stepY_value,
|
|
306
|
+
stepY_size,
|
|
307
|
+
stepX_size,
|
|
308
|
+
stepX_count
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
svgCanvas.add(cartesianAxisGroup);
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
// =>> disegno linee
|
|
316
|
+
const linesGroup = svgCanvas.group()
|
|
317
|
+
.attr({ 'data-debug-info': params.debug? 'Gruppo Linee' : null });
|
|
318
|
+
|
|
319
|
+
params.values.forEach((lineDataArray, idx) => {
|
|
320
|
+
const thisLineGroup = linesGroup.group()
|
|
321
|
+
.attr({ 'data-debug-info': params.debug? `Gruppo Linea ${idx}` : null }),
|
|
322
|
+
coords = []; // array delle coordinate
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
lineDataArray.forEach((pointValue, pointIdx) => {
|
|
326
|
+
// trasformazione valore in coordinate
|
|
327
|
+
|
|
328
|
+
const x = chart_area.left + stepX_size * pointIdx,
|
|
329
|
+
y = chart_area.top + chart_area.height - (((pointValue - min_value) * chart_area.height) / (max_value - min_value));
|
|
330
|
+
|
|
331
|
+
coords.push([x,y]);
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
thisLineGroup.polyline(coords).attr(params.data_lines_attrs[idx]);
|
|
335
|
+
|
|
336
|
+
// punti
|
|
337
|
+
const radius = Array.isArray(params.data_points_attrs.r)
|
|
338
|
+
? params.data_points_attrs.r[idx]
|
|
339
|
+
: params.data_points_attrs.r;
|
|
340
|
+
|
|
341
|
+
coords.forEach((point, coord_idx) => {
|
|
342
|
+
|
|
343
|
+
thisLineGroup.circle()
|
|
344
|
+
.attr({
|
|
345
|
+
...params.data_points_attrs,
|
|
346
|
+
r: radius,
|
|
347
|
+
fill: params.data_lines_attrs[idx].stroke,
|
|
348
|
+
cx: point[0],
|
|
349
|
+
cy: point[1],
|
|
350
|
+
'data-debug-info': params.debug? `Valore: ${params.values[idx][coord_idx]}` : null
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
// =>> Legenda
|
|
359
|
+
const legendaEl = await legenda(chartInstance, opts_legenda);
|
|
360
|
+
legendaEl.attr({ 'data-cfg.debug-info': params.debug? 'Legenda' : null });
|
|
361
|
+
const legendaBbox = legendaEl.bbox();
|
|
362
|
+
|
|
363
|
+
legendaEl.dmove(
|
|
364
|
+
(params.width - legendaBbox.width) / 2,
|
|
365
|
+
params.padding
|
|
366
|
+
);
|
|
367
|
+
legendaEl.y(params.padding);
|
|
368
|
+
|
|
369
|
+
legendaEl.x((params.width - legendaBbox.width) / 2);
|
|
370
|
+
|
|
371
|
+
svgCanvas.add(legendaEl);
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
if(!params.container) {
|
|
375
|
+
return svgCanvas.svg();
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
} catch(e) {
|
|
380
|
+
console.error( '[MinimoCharts → lines]', e ); // eslint-disable-line
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { G } from '@svgdotjs/svg.js';
|
|
2
|
+
import { polarToCartesian, polarToCartesianString } from '../../chart-utils.js';
|
|
3
|
+
|
|
4
|
+
export function run({
|
|
5
|
+
mainDisplayCenter,
|
|
6
|
+
width,
|
|
7
|
+
height,
|
|
8
|
+
mainRadius,
|
|
9
|
+
// centerGap,
|
|
10
|
+
// scaleEndThickness,
|
|
11
|
+
centroSx,
|
|
12
|
+
rSx,
|
|
13
|
+
centroDx,
|
|
14
|
+
rDx
|
|
15
|
+
}) {
|
|
16
|
+
|
|
17
|
+
const debug_group = new G();
|
|
18
|
+
// centro display e rotazione asticella
|
|
19
|
+
debug_group.attr({
|
|
20
|
+
'data-debug-info': 'centro rotazione asticella',
|
|
21
|
+
stroke: '#585151',
|
|
22
|
+
fill: 'none',
|
|
23
|
+
'stroke-width': .5,
|
|
24
|
+
class: 'debug-info'
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// assi orizzontali e verticali
|
|
28
|
+
debug_group.line({
|
|
29
|
+
x1: 0,
|
|
30
|
+
y1: mainDisplayCenter.y,
|
|
31
|
+
x2: width,
|
|
32
|
+
y2: mainDisplayCenter.y}
|
|
33
|
+
)
|
|
34
|
+
.attr({'data-debug-info': 'Asse orizzontale'});
|
|
35
|
+
debug_group.line({
|
|
36
|
+
x1: mainDisplayCenter.x,
|
|
37
|
+
y1: 0,
|
|
38
|
+
x2: mainDisplayCenter.x,
|
|
39
|
+
y2: height}
|
|
40
|
+
)
|
|
41
|
+
.attr({'data-debug-info': 'Asse verticale'});
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
debug_group.path(
|
|
45
|
+
`M${polarToCartesianString(210, mainDisplayCenter.x, mainDisplayCenter.y, mainRadius)}`+
|
|
46
|
+
`L${mainDisplayCenter.x},${mainDisplayCenter.y}` +
|
|
47
|
+
`L${polarToCartesianString(330, mainDisplayCenter.x, mainDisplayCenter.y, mainRadius)}`
|
|
48
|
+
).attr({'data-debug-info': 'Raggi 210° e 330°'});
|
|
49
|
+
|
|
50
|
+
debug_group.path(
|
|
51
|
+
`M${mainDisplayCenter.x},${mainDisplayCenter.y}` +
|
|
52
|
+
`L${polarToCartesianString(30, mainDisplayCenter.x, mainDisplayCenter.y, mainRadius)}`
|
|
53
|
+
).attr({'data-debug-info': 'raggio 30°'});
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
// centri circonferenze
|
|
57
|
+
const braccioCrocino = 20;
|
|
58
|
+
const radiusAttrs = {
|
|
59
|
+
'stroke-width': 2,
|
|
60
|
+
'stroke-dasharray': '8 3'
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
debug_group.path(
|
|
64
|
+
`M${centroSx.x - braccioCrocino},${centroSx.y}`+
|
|
65
|
+
`L${centroSx.x + braccioCrocino},${centroSx.y}` +
|
|
66
|
+
`M${centroSx.x},${centroSx.y - braccioCrocino}`+
|
|
67
|
+
`L${centroSx.x},${centroSx.y + braccioCrocino}`
|
|
68
|
+
).attr({'data-debug-info': 'Centro C', stroke: '#2C7D06'});
|
|
69
|
+
|
|
70
|
+
// circonferenza verde e raggio
|
|
71
|
+
debug_group
|
|
72
|
+
.circle(rSx * 2)
|
|
73
|
+
.move(centroSx.x - rSx, centroSx.y - rSx)
|
|
74
|
+
.attr({
|
|
75
|
+
'data-debug-info': 'Circ. c',
|
|
76
|
+
stroke: '#3C8A00',
|
|
77
|
+
'stroke-width': 2,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
debug_group
|
|
81
|
+
.path(
|
|
82
|
+
`M${centroSx.x},${centroSx.y}`+
|
|
83
|
+
`L${polarToCartesianString(120, centroSx.x, centroSx.y, rSx)}`
|
|
84
|
+
)
|
|
85
|
+
.attr({
|
|
86
|
+
'data-debug-info': 'Raggio circ. c',
|
|
87
|
+
stroke: '#3C8A00',
|
|
88
|
+
...radiusAttrs
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
// circonferenza rossa e raggio
|
|
94
|
+
debug_group.path(
|
|
95
|
+
`M${centroDx.x - braccioCrocino},${centroDx.y}`+
|
|
96
|
+
`L${centroDx.x + braccioCrocino},${centroDx.y}` +
|
|
97
|
+
`M${centroDx.x},${centroDx.y - braccioCrocino}`+
|
|
98
|
+
`L${centroDx.x},${centroDx.y + braccioCrocino}`
|
|
99
|
+
).attr({'data-debug-info': 'Centro B', stroke: '#c00'});
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
debug_group
|
|
103
|
+
.circle(rDx * 2)
|
|
104
|
+
.move(centroDx.x - rDx, centroDx.y - rDx)
|
|
105
|
+
.attr({
|
|
106
|
+
'data-debug-info': 'Circ. b',
|
|
107
|
+
stroke: '#c00',
|
|
108
|
+
'stroke-width': 2,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
debug_group
|
|
112
|
+
.path(
|
|
113
|
+
`M${centroDx.x},${centroDx.y}`+
|
|
114
|
+
`L${polarToCartesianString(60, centroDx.x, centroDx.y, rDx)}`
|
|
115
|
+
)
|
|
116
|
+
.attr({
|
|
117
|
+
'data-debug-info': 'Raggio circ. b',
|
|
118
|
+
stroke: '#c00',
|
|
119
|
+
...radiusAttrs
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
return debug_group;
|
|
124
|
+
}
|