@meonode/canvas 2.0.2 → 2.0.4
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/cjs/{src/canvas → canvas}/canvas.helper.d.ts +1 -20
- package/dist/cjs/canvas/canvas.helper.d.ts.map +1 -0
- package/dist/cjs/canvas/canvas.helper.js +0 -230
- package/dist/cjs/canvas/canvas.helper.js.map +1 -1
- package/dist/{esm/src → cjs}/canvas/canvas.type.d.ts +1 -12
- package/dist/cjs/canvas/canvas.type.d.ts.map +1 -0
- package/dist/cjs/{src/canvas → canvas}/chart.canvas.d.ts +1 -1
- package/dist/cjs/canvas/chart.canvas.d.ts.map +1 -0
- package/dist/cjs/canvas/chart.canvas.js +70 -144
- package/dist/cjs/canvas/chart.canvas.js.map +1 -1
- package/dist/cjs/canvas/grid.canvas.d.ts.map +1 -0
- package/dist/cjs/canvas/grid.canvas.js.map +1 -1
- package/dist/{esm/src → cjs}/canvas/image.canvas.d.ts +1 -1
- package/dist/cjs/canvas/image.canvas.d.ts.map +1 -0
- package/dist/cjs/canvas/image.canvas.js +2 -2
- package/dist/cjs/canvas/image.canvas.js.map +1 -1
- package/dist/{esm/src → cjs}/canvas/layout.canvas.d.ts +2 -2
- package/dist/cjs/canvas/layout.canvas.d.ts.map +1 -0
- package/dist/cjs/canvas/layout.canvas.js +6 -6
- package/dist/cjs/canvas/layout.canvas.js.map +1 -1
- package/dist/{esm/src → cjs}/canvas/root.canvas.d.ts +3 -2
- package/dist/cjs/canvas/root.canvas.d.ts.map +1 -0
- package/dist/cjs/canvas/root.canvas.js +23 -117
- package/dist/cjs/canvas/root.canvas.js.map +1 -1
- package/dist/cjs/{src/canvas → canvas}/text.canvas.d.ts +1 -1
- package/dist/cjs/canvas/text.canvas.d.ts.map +1 -0
- package/dist/cjs/canvas/text.canvas.js +2 -2
- package/dist/cjs/canvas/text.canvas.js.map +1 -1
- package/dist/cjs/constant/common.const.d.ts.map +1 -0
- package/dist/cjs/constant/common.const.js.map +1 -1
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/util/disk.cache.d.ts.map +1 -0
- package/dist/cjs/util/disk.cache.js.map +1 -1
- package/dist/cjs/worker/comlink.pool.d.ts +30 -0
- package/dist/cjs/worker/comlink.pool.d.ts.map +1 -0
- package/dist/cjs/worker/comlink.pool.js +164 -0
- package/dist/cjs/worker/comlink.pool.js.map +1 -0
- package/dist/cjs/worker/comlink.setup.d.ts +4 -0
- package/dist/cjs/worker/comlink.setup.d.ts.map +1 -0
- package/dist/cjs/worker/comlink.setup.js +53 -0
- package/dist/cjs/worker/comlink.setup.js.map +1 -0
- package/dist/cjs/worker/render.worker.d.ts.map +1 -0
- package/dist/cjs/worker/render.worker.js +58 -61
- package/dist/cjs/worker/render.worker.js.map +1 -1
- package/dist/cjs/worker/worker.types.d.ts +13 -0
- package/dist/cjs/worker/worker.types.d.ts.map +1 -0
- package/dist/esm/{src/canvas → canvas}/canvas.helper.d.ts +1 -20
- package/dist/esm/canvas/canvas.helper.d.ts.map +1 -0
- package/dist/esm/canvas/canvas.helper.js +1 -230
- package/dist/{cjs/src → esm}/canvas/canvas.type.d.ts +1 -12
- package/dist/esm/canvas/canvas.type.d.ts.map +1 -0
- package/dist/esm/{src/canvas → canvas}/chart.canvas.d.ts +1 -1
- package/dist/esm/canvas/chart.canvas.d.ts.map +1 -0
- package/dist/esm/canvas/chart.canvas.js +71 -145
- package/dist/esm/canvas/grid.canvas.d.ts.map +1 -0
- package/dist/{cjs/src → esm}/canvas/image.canvas.d.ts +1 -1
- package/dist/esm/canvas/image.canvas.d.ts.map +1 -0
- package/dist/esm/canvas/image.canvas.js +2 -2
- package/dist/{cjs/src → esm}/canvas/layout.canvas.d.ts +2 -2
- package/dist/esm/canvas/layout.canvas.d.ts.map +1 -0
- package/dist/esm/canvas/layout.canvas.js +6 -6
- package/dist/{cjs/src → esm}/canvas/root.canvas.d.ts +3 -2
- package/dist/esm/canvas/root.canvas.d.ts.map +1 -0
- package/dist/esm/canvas/root.canvas.js +23 -116
- package/dist/esm/{src/canvas → canvas}/text.canvas.d.ts +1 -1
- package/dist/esm/canvas/text.canvas.d.ts.map +1 -0
- package/dist/esm/canvas/text.canvas.js +2 -2
- package/dist/esm/constant/common.const.d.ts.map +1 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/util/disk.cache.d.ts.map +1 -0
- package/dist/esm/worker/comlink.pool.d.ts +30 -0
- package/dist/esm/worker/comlink.pool.d.ts.map +1 -0
- package/dist/esm/worker/comlink.pool.js +139 -0
- package/dist/esm/worker/comlink.setup.d.ts +4 -0
- package/dist/esm/worker/comlink.setup.d.ts.map +1 -0
- package/dist/esm/worker/comlink.setup.js +30 -0
- package/dist/esm/worker/render.worker.d.ts.map +1 -0
- package/dist/esm/worker/render.worker.js +38 -60
- package/dist/esm/worker/worker.types.d.ts +13 -0
- package/dist/esm/worker/worker.types.d.ts.map +1 -0
- package/package.json +2 -1
- package/dist/cjs/src/canvas/canvas.helper.d.ts.map +0 -1
- package/dist/cjs/src/canvas/canvas.type.d.ts.map +0 -1
- package/dist/cjs/src/canvas/chart.canvas.d.ts.map +0 -1
- package/dist/cjs/src/canvas/grid.canvas.d.ts.map +0 -1
- package/dist/cjs/src/canvas/image.canvas.d.ts.map +0 -1
- package/dist/cjs/src/canvas/layout.canvas.d.ts.map +0 -1
- package/dist/cjs/src/canvas/root.canvas.d.ts.map +0 -1
- package/dist/cjs/src/canvas/text.canvas.d.ts.map +0 -1
- package/dist/cjs/src/constant/common.const.d.ts.map +0 -1
- package/dist/cjs/src/index.d.ts.map +0 -1
- package/dist/cjs/src/util/disk.cache.d.ts.map +0 -1
- package/dist/cjs/src/worker/render.worker.d.ts.map +0 -1
- package/dist/cjs/src/worker/worker.types.d.ts +0 -76
- package/dist/cjs/src/worker/worker.types.d.ts.map +0 -1
- package/dist/esm/src/canvas/canvas.helper.d.ts.map +0 -1
- package/dist/esm/src/canvas/canvas.type.d.ts.map +0 -1
- package/dist/esm/src/canvas/chart.canvas.d.ts.map +0 -1
- package/dist/esm/src/canvas/grid.canvas.d.ts.map +0 -1
- package/dist/esm/src/canvas/image.canvas.d.ts.map +0 -1
- package/dist/esm/src/canvas/layout.canvas.d.ts.map +0 -1
- package/dist/esm/src/canvas/root.canvas.d.ts.map +0 -1
- package/dist/esm/src/canvas/text.canvas.d.ts.map +0 -1
- package/dist/esm/src/constant/common.const.d.ts.map +0 -1
- package/dist/esm/src/index.d.ts.map +0 -1
- package/dist/esm/src/util/disk.cache.d.ts.map +0 -1
- package/dist/esm/src/worker/render.worker.d.ts.map +0 -1
- package/dist/esm/src/worker/worker.types.d.ts +0 -76
- package/dist/esm/src/worker/worker.types.d.ts.map +0 -1
- /package/dist/cjs/{src/canvas → canvas}/grid.canvas.d.ts +0 -0
- /package/dist/cjs/{src/constant → constant}/common.const.d.ts +0 -0
- /package/dist/cjs/{src/index.d.ts → index.d.ts} +0 -0
- /package/dist/cjs/{src/util → util}/disk.cache.d.ts +0 -0
- /package/dist/cjs/{src/worker → worker}/render.worker.d.ts +0 -0
- /package/dist/esm/{src/canvas → canvas}/grid.canvas.d.ts +0 -0
- /package/dist/esm/{src/constant → constant}/common.const.d.ts +0 -0
- /package/dist/esm/{src/index.d.ts → index.d.ts} +0 -0
- /package/dist/esm/{src/util → util}/disk.cache.d.ts +0 -0
- /package/dist/esm/{src/worker → worker}/render.worker.d.ts +0 -0
|
@@ -3,29 +3,7 @@
|
|
|
3
3
|
var layout_canvas = require('./layout.canvas.js');
|
|
4
4
|
var common_const = require('../constant/common.const.js');
|
|
5
5
|
var text_canvas = require('./text.canvas.js');
|
|
6
|
-
var image_canvas = require('./image.canvas.js');
|
|
7
6
|
|
|
8
|
-
/**
|
|
9
|
-
* Local buildTree for pre-computed render function results.
|
|
10
|
-
* Handles only node types that render functions would return (Box, Column, Row, Text, Image).
|
|
11
|
-
* Avoids circular dependency with root.canvas.ts.
|
|
12
|
-
*/
|
|
13
|
-
function buildDescriptorTree(descriptor) {
|
|
14
|
-
switch (descriptor.__type) {
|
|
15
|
-
case 'Box':
|
|
16
|
-
return new layout_canvas.BoxNode({ ...descriptor.props, children: descriptor.children?.map(buildDescriptorTree) });
|
|
17
|
-
case 'Column':
|
|
18
|
-
return new layout_canvas.ColumnNode({ ...descriptor.props, children: descriptor.children?.map(buildDescriptorTree) });
|
|
19
|
-
case 'Row':
|
|
20
|
-
return new layout_canvas.RowNode({ ...descriptor.props, children: descriptor.children?.map(buildDescriptorTree) });
|
|
21
|
-
case 'Image':
|
|
22
|
-
return new image_canvas.ImageNode(descriptor.props);
|
|
23
|
-
case 'Text':
|
|
24
|
-
return new text_canvas.TextNode(descriptor.text, descriptor.props);
|
|
25
|
-
default:
|
|
26
|
-
return new layout_canvas.BoxNode({});
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
7
|
class ChartNode extends layout_canvas.BoxNode {
|
|
30
8
|
chartData;
|
|
31
9
|
chartType;
|
|
@@ -70,9 +48,9 @@ class ChartNode extends layout_canvas.BoxNode {
|
|
|
70
48
|
}
|
|
71
49
|
}
|
|
72
50
|
}
|
|
73
|
-
_renderContent(ctx, x, y, width, height) {
|
|
51
|
+
async _renderContent(ctx, x, y, width, height) {
|
|
74
52
|
// First render background/borders from parent
|
|
75
|
-
super._renderContent(ctx, x, y, width, height);
|
|
53
|
+
await super._renderContent(ctx, x, y, width, height);
|
|
76
54
|
// Then render chart-specific content
|
|
77
55
|
const paddingLeft = this.node.getComputedPadding(common_const.Style.Edge.Left);
|
|
78
56
|
const paddingRight = this.node.getComputedPadding(common_const.Style.Edge.Right);
|
|
@@ -84,16 +62,16 @@ class ChartNode extends layout_canvas.BoxNode {
|
|
|
84
62
|
const contentHeight = height - paddingTop - paddingBottom;
|
|
85
63
|
switch (this.chartType) {
|
|
86
64
|
case 'bar':
|
|
87
|
-
this.renderBarChart(ctx, contentX, contentY, contentWidth, contentHeight);
|
|
65
|
+
await this.renderBarChart(ctx, contentX, contentY, contentWidth, contentHeight);
|
|
88
66
|
break;
|
|
89
67
|
case 'line':
|
|
90
|
-
this.renderLineChart(ctx, contentX, contentY, contentWidth, contentHeight);
|
|
68
|
+
await this.renderLineChart(ctx, contentX, contentY, contentWidth, contentHeight);
|
|
91
69
|
break;
|
|
92
70
|
case 'pie':
|
|
93
|
-
this.renderPieChart(ctx, contentX, contentY, contentWidth, contentHeight);
|
|
71
|
+
await this.renderPieChart(ctx, contentX, contentY, contentWidth, contentHeight);
|
|
94
72
|
break;
|
|
95
73
|
case 'doughnut':
|
|
96
|
-
this.renderDoughnutChart(ctx, contentX, contentY, contentWidth, contentHeight);
|
|
74
|
+
await this.renderDoughnutChart(ctx, contentX, contentY, contentWidth, contentHeight);
|
|
97
75
|
break;
|
|
98
76
|
}
|
|
99
77
|
}
|
|
@@ -213,7 +191,7 @@ class ChartNode extends layout_canvas.BoxNode {
|
|
|
213
191
|
chartY: chartAreaY,
|
|
214
192
|
};
|
|
215
193
|
}
|
|
216
|
-
renderBarChart(ctx, x, y, width, height) {
|
|
194
|
+
async renderBarChart(ctx, x, y, width, height) {
|
|
217
195
|
if (this.chartType !== 'bar')
|
|
218
196
|
return;
|
|
219
197
|
const chartData = this.chartData;
|
|
@@ -228,8 +206,7 @@ class ChartNode extends layout_canvas.BoxNode {
|
|
|
228
206
|
if (chartOptions?.showYAxis) {
|
|
229
207
|
const fontSize = chartOptions.yAxisFontSize || 12;
|
|
230
208
|
ctx.font = `${fontSize}px ${this.props.fontFamily || 'sans-serif'}`;
|
|
231
|
-
const maxLabel = chartOptions.
|
|
232
|
-
(chartOptions.yAxisLabelFormatter ? chartOptions.yAxisLabelFormatter(maxValue) : this.getSmartYAxisFormatter(maxValue)(maxValue));
|
|
209
|
+
const maxLabel = chartOptions.yAxisLabelFormatter ? await chartOptions.yAxisLabelFormatter(maxValue) : this.getSmartYAxisFormatter(maxValue)(maxValue);
|
|
233
210
|
const yAxisWidth = ctx.measureText(maxLabel).width + 10;
|
|
234
211
|
chartX += yAxisWidth;
|
|
235
212
|
chartWidth -= yAxisWidth;
|
|
@@ -263,8 +240,7 @@ class ChartNode extends layout_canvas.BoxNode {
|
|
|
263
240
|
ctx.stroke();
|
|
264
241
|
if (chartOptions?.showYAxis) {
|
|
265
242
|
const value = maxValue - (maxValue / 5) * i;
|
|
266
|
-
const label = chartOptions.
|
|
267
|
-
(chartOptions.yAxisLabelFormatter ? chartOptions.yAxisLabelFormatter(value) : this.getSmartYAxisFormatter(maxValue)(value));
|
|
243
|
+
const label = chartOptions.yAxisLabelFormatter ? await chartOptions.yAxisLabelFormatter(value) : this.getSmartYAxisFormatter(maxValue)(value);
|
|
268
244
|
text_canvas.TextNode.renderSimpleText(ctx, label, chartX - 5, gridY, {
|
|
269
245
|
color: chartOptions.yAxisColor || chartOptions.axisColor || '#000',
|
|
270
246
|
fontSize: chartOptions.yAxisFontSize || 12,
|
|
@@ -277,9 +253,11 @@ class ChartNode extends layout_canvas.BoxNode {
|
|
|
277
253
|
ctx.setLineDash([]);
|
|
278
254
|
}
|
|
279
255
|
// Render bars
|
|
280
|
-
labels.
|
|
256
|
+
for (let index = 0; index < labels.length; index++) {
|
|
257
|
+
const label = labels[index];
|
|
281
258
|
const groupX = chartX + index * groupWidth + barSpacing / 2;
|
|
282
|
-
datasets.
|
|
259
|
+
for (let datasetIndex = 0; datasetIndex < datasets.length; datasetIndex++) {
|
|
260
|
+
const dataset = datasets[datasetIndex];
|
|
283
261
|
const barHeight = (dataset.data[index] / maxValue) * finalChartHeight;
|
|
284
262
|
const barX = groupX + datasetIndex * barWidth;
|
|
285
263
|
const barY = chartY + finalChartHeight - barHeight;
|
|
@@ -290,21 +268,13 @@ class ChartNode extends layout_canvas.BoxNode {
|
|
|
290
268
|
const value = dataset.data[index];
|
|
291
269
|
const valueX = barX + barWidth / 2;
|
|
292
270
|
const valueY = barY - 5; // 5px padding above bar
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
const valueNode = buildDescriptorTree(preComputedValueDesc);
|
|
296
|
-
valueNode.processInitialChildren();
|
|
297
|
-
valueNode.node.calculateLayout(undefined, undefined, common_const.Style.Direction.LTR);
|
|
298
|
-
const layout = valueNode.node.getComputedLayout();
|
|
299
|
-
valueNode.render(ctx, valueX - layout.width / 2, valueY - layout.height);
|
|
300
|
-
}
|
|
301
|
-
else if (chartOptions.renderValueItem) {
|
|
302
|
-
const valueNode = chartOptions.renderValueItem({ item: value, index, datasetIndex });
|
|
271
|
+
if (chartOptions.renderValueItem) {
|
|
272
|
+
const valueNode = await chartOptions.renderValueItem({ item: value, index, datasetIndex });
|
|
303
273
|
if (valueNode) {
|
|
304
274
|
valueNode.processInitialChildren();
|
|
305
275
|
valueNode.node.calculateLayout(undefined, undefined, common_const.Style.Direction.LTR);
|
|
306
276
|
const layout = valueNode.node.getComputedLayout();
|
|
307
|
-
valueNode.render(ctx, valueX - layout.width / 2, valueY - layout.height);
|
|
277
|
+
await valueNode.render(ctx, valueX - layout.width / 2, valueY - layout.height);
|
|
308
278
|
}
|
|
309
279
|
}
|
|
310
280
|
else {
|
|
@@ -317,25 +287,17 @@ class ChartNode extends layout_canvas.BoxNode {
|
|
|
317
287
|
});
|
|
318
288
|
}
|
|
319
289
|
}
|
|
320
|
-
}
|
|
290
|
+
}
|
|
321
291
|
// Render labels
|
|
322
292
|
if (chartOptions?.showLabels) {
|
|
323
|
-
const displayLabel = chartOptions.
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
const labelNode = buildDescriptorTree(preComputedLabelDesc);
|
|
327
|
-
labelNode.processInitialChildren();
|
|
328
|
-
labelNode.node.calculateLayout(undefined, undefined, common_const.Style.Direction.LTR);
|
|
329
|
-
const layout = labelNode.node.getComputedLayout();
|
|
330
|
-
labelNode.render(ctx, groupX + (groupWidth - barSpacing) / 2 - layout.width / 2, chartY + finalChartHeight + labelHeight / 2 - layout.height / 2);
|
|
331
|
-
}
|
|
332
|
-
else if (chartOptions.renderLabelItem) {
|
|
333
|
-
const labelNode = chartOptions.renderLabelItem({ item: label, index });
|
|
293
|
+
const displayLabel = chartOptions.xAxisLabelFormatter ? await chartOptions.xAxisLabelFormatter(label, index) : label;
|
|
294
|
+
if (chartOptions.renderLabelItem) {
|
|
295
|
+
const labelNode = await chartOptions.renderLabelItem({ item: label, index });
|
|
334
296
|
if (labelNode) {
|
|
335
297
|
labelNode.processInitialChildren();
|
|
336
298
|
labelNode.node.calculateLayout(undefined, undefined, common_const.Style.Direction.LTR);
|
|
337
299
|
const layout = labelNode.node.getComputedLayout();
|
|
338
|
-
labelNode.render(ctx, groupX + (groupWidth - barSpacing) / 2 - layout.width / 2, chartY + finalChartHeight + labelHeight / 2 - layout.height / 2);
|
|
300
|
+
await labelNode.render(ctx, groupX + (groupWidth - barSpacing) / 2 - layout.width / 2, chartY + finalChartHeight + labelHeight / 2 - layout.height / 2);
|
|
339
301
|
}
|
|
340
302
|
}
|
|
341
303
|
else {
|
|
@@ -348,13 +310,13 @@ class ChartNode extends layout_canvas.BoxNode {
|
|
|
348
310
|
});
|
|
349
311
|
}
|
|
350
312
|
}
|
|
351
|
-
}
|
|
313
|
+
}
|
|
352
314
|
// Render legend
|
|
353
315
|
if (chartOptions?.showLegend) {
|
|
354
|
-
this.renderLegend(ctx, x + legendLayout.x, y + legendLayout.y, legendLayout.width, legendLayout.height);
|
|
316
|
+
await this.renderLegend(ctx, x + legendLayout.x, y + legendLayout.y, legendLayout.width, legendLayout.height);
|
|
355
317
|
}
|
|
356
318
|
}
|
|
357
|
-
renderLineChart(ctx, x, y, width, height) {
|
|
319
|
+
async renderLineChart(ctx, x, y, width, height) {
|
|
358
320
|
if (this.chartType !== 'line')
|
|
359
321
|
return;
|
|
360
322
|
const chartData = this.chartData;
|
|
@@ -369,8 +331,7 @@ class ChartNode extends layout_canvas.BoxNode {
|
|
|
369
331
|
if (chartOptions?.showYAxis) {
|
|
370
332
|
const fontSize = chartOptions.yAxisFontSize || 12;
|
|
371
333
|
ctx.font = `${fontSize}px ${this.props.fontFamily || 'sans-serif'}`;
|
|
372
|
-
const maxLabel = chartOptions.
|
|
373
|
-
(chartOptions.yAxisLabelFormatter ? chartOptions.yAxisLabelFormatter(maxValue) : this.getSmartYAxisFormatter(maxValue)(maxValue));
|
|
334
|
+
const maxLabel = chartOptions.yAxisLabelFormatter ? await chartOptions.yAxisLabelFormatter(maxValue) : this.getSmartYAxisFormatter(maxValue)(maxValue);
|
|
374
335
|
const yAxisWidth = ctx.measureText(maxLabel).width + 10;
|
|
375
336
|
chartX += yAxisWidth;
|
|
376
337
|
chartWidth -= yAxisWidth;
|
|
@@ -402,8 +363,7 @@ class ChartNode extends layout_canvas.BoxNode {
|
|
|
402
363
|
ctx.stroke();
|
|
403
364
|
if (chartOptions?.showYAxis) {
|
|
404
365
|
const value = maxValue - (maxValue / 5) * i;
|
|
405
|
-
const label = chartOptions.
|
|
406
|
-
(chartOptions.yAxisLabelFormatter ? chartOptions.yAxisLabelFormatter(value) : this.getSmartYAxisFormatter(maxValue)(value));
|
|
366
|
+
const label = chartOptions.yAxisLabelFormatter ? await chartOptions.yAxisLabelFormatter(value) : this.getSmartYAxisFormatter(maxValue)(value);
|
|
407
367
|
text_canvas.TextNode.renderSimpleText(ctx, label, chartX - 5, gridY, {
|
|
408
368
|
color: chartOptions.yAxisColor || chartOptions.axisColor || '#000',
|
|
409
369
|
fontSize: chartOptions.yAxisFontSize || 12,
|
|
@@ -416,11 +376,13 @@ class ChartNode extends layout_canvas.BoxNode {
|
|
|
416
376
|
ctx.setLineDash([]);
|
|
417
377
|
}
|
|
418
378
|
// Render lines and points
|
|
419
|
-
datasets.
|
|
379
|
+
for (let datasetIndex = 0; datasetIndex < datasets.length; datasetIndex++) {
|
|
380
|
+
const dataset = datasets[datasetIndex];
|
|
420
381
|
ctx.strokeStyle = dataset.color || this.generateColor(datasetIndex);
|
|
421
382
|
ctx.lineWidth = 2;
|
|
422
383
|
ctx.beginPath();
|
|
423
|
-
dataset.data.
|
|
384
|
+
for (let index = 0; index < dataset.data.length; index++) {
|
|
385
|
+
const value = dataset.data[index];
|
|
424
386
|
const pointX = chartX + index * pointSpacing;
|
|
425
387
|
const pointY = chartY + finalChartHeight - (value / maxValue) * finalChartHeight;
|
|
426
388
|
if (index === 0) {
|
|
@@ -429,38 +391,31 @@ class ChartNode extends layout_canvas.BoxNode {
|
|
|
429
391
|
else {
|
|
430
392
|
ctx.lineTo(pointX, pointY);
|
|
431
393
|
}
|
|
432
|
-
}
|
|
394
|
+
}
|
|
433
395
|
ctx.stroke();
|
|
434
396
|
// Render points
|
|
435
|
-
dataset.data.
|
|
397
|
+
for (let index = 0; index < dataset.data.length; index++) {
|
|
436
398
|
const pointX = chartX + index * pointSpacing;
|
|
437
|
-
const pointY = chartY + finalChartHeight - (
|
|
399
|
+
const pointY = chartY + finalChartHeight - (dataset.data[index] / maxValue) * finalChartHeight;
|
|
438
400
|
ctx.fillStyle = dataset.color || this.generateColor(datasetIndex);
|
|
439
401
|
ctx.beginPath();
|
|
440
402
|
ctx.arc(pointX, pointY, 4, 0, Math.PI * 2);
|
|
441
403
|
ctx.fill();
|
|
442
|
-
}
|
|
443
|
-
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
444
406
|
// Render labels
|
|
445
407
|
if (chartOptions?.showLabels) {
|
|
446
|
-
labels.
|
|
408
|
+
for (let index = 0; index < labels.length; index++) {
|
|
409
|
+
const label = labels[index];
|
|
447
410
|
const pointX = chartX + index * pointSpacing;
|
|
448
|
-
const displayLabel = chartOptions.
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
const labelNode = buildDescriptorTree(preComputedLabelDesc);
|
|
452
|
-
labelNode.processInitialChildren();
|
|
453
|
-
labelNode.node.calculateLayout(undefined, undefined, common_const.Style.Direction.LTR);
|
|
454
|
-
const layout = labelNode.node.getComputedLayout();
|
|
455
|
-
labelNode.render(ctx, pointX - layout.width / 2, chartY + finalChartHeight + labelHeight / 2 - layout.height / 2);
|
|
456
|
-
}
|
|
457
|
-
else if (chartOptions.renderLabelItem) {
|
|
458
|
-
const labelNode = chartOptions.renderLabelItem({ item: label, index });
|
|
411
|
+
const displayLabel = chartOptions.xAxisLabelFormatter ? await chartOptions.xAxisLabelFormatter(label, index) : label;
|
|
412
|
+
if (chartOptions.renderLabelItem) {
|
|
413
|
+
const labelNode = await chartOptions.renderLabelItem({ item: label, index });
|
|
459
414
|
if (labelNode) {
|
|
460
415
|
labelNode.processInitialChildren();
|
|
461
416
|
labelNode.node.calculateLayout(undefined, undefined, common_const.Style.Direction.LTR);
|
|
462
417
|
const layout = labelNode.node.getComputedLayout();
|
|
463
|
-
labelNode.render(ctx, pointX - layout.width / 2, chartY + finalChartHeight + labelHeight / 2 - layout.height / 2);
|
|
418
|
+
await labelNode.render(ctx, pointX - layout.width / 2, chartY + finalChartHeight + labelHeight / 2 - layout.height / 2);
|
|
464
419
|
}
|
|
465
420
|
}
|
|
466
421
|
else {
|
|
@@ -472,13 +427,13 @@ class ChartNode extends layout_canvas.BoxNode {
|
|
|
472
427
|
textBaseline: 'middle',
|
|
473
428
|
});
|
|
474
429
|
}
|
|
475
|
-
}
|
|
430
|
+
}
|
|
476
431
|
}
|
|
477
432
|
if (chartOptions?.showLegend) {
|
|
478
|
-
this.renderLegend(ctx, x + legendLayout.x, y + legendLayout.y, legendLayout.width, legendLayout.height);
|
|
433
|
+
await this.renderLegend(ctx, x + legendLayout.x, y + legendLayout.y, legendLayout.width, legendLayout.height);
|
|
479
434
|
}
|
|
480
435
|
}
|
|
481
|
-
renderPieChart(ctx, x, y, width, height) {
|
|
436
|
+
async renderPieChart(ctx, x, y, width, height) {
|
|
482
437
|
if (this.chartType !== 'pie')
|
|
483
438
|
return;
|
|
484
439
|
const data = this.chartData;
|
|
@@ -493,7 +448,8 @@ class ChartNode extends layout_canvas.BoxNode {
|
|
|
493
448
|
const radius = Math.min(chartWidth, chartHeight) / 2 - 10;
|
|
494
449
|
const total = data.reduce((sum, point) => sum + point.value, 0);
|
|
495
450
|
let currentAngle = -Math.PI / 2; // Start at top
|
|
496
|
-
data.
|
|
451
|
+
for (let index = 0; index < data.length; index++) {
|
|
452
|
+
const point = data[index];
|
|
497
453
|
const sliceAngle = (point.value / total) * Math.PI * 2;
|
|
498
454
|
const startAngle = currentAngle;
|
|
499
455
|
const endAngle = currentAngle + sliceAngle;
|
|
@@ -513,21 +469,13 @@ class ChartNode extends layout_canvas.BoxNode {
|
|
|
513
469
|
const labelRadius = radius * 0.7;
|
|
514
470
|
const labelX = centerX + Math.cos(labelAngle) * labelRadius;
|
|
515
471
|
const labelY = centerY + Math.sin(labelAngle) * labelRadius;
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
const labelNode = buildDescriptorTree(preComputedLabelDesc);
|
|
519
|
-
labelNode.processInitialChildren();
|
|
520
|
-
labelNode.node.calculateLayout(undefined, undefined, common_const.Style.Direction.LTR);
|
|
521
|
-
const layout = labelNode.node.getComputedLayout();
|
|
522
|
-
labelNode.render(ctx, labelX - layout.width / 2, labelY - layout.height / 2);
|
|
523
|
-
}
|
|
524
|
-
else if (chartOptions.renderLabelItem) {
|
|
525
|
-
const labelNode = chartOptions.renderLabelItem({ item: point, index });
|
|
472
|
+
if (chartOptions.renderLabelItem) {
|
|
473
|
+
const labelNode = await chartOptions.renderLabelItem({ item: point, index });
|
|
526
474
|
if (labelNode) {
|
|
527
475
|
labelNode.processInitialChildren();
|
|
528
476
|
labelNode.node.calculateLayout(undefined, undefined, common_const.Style.Direction.LTR);
|
|
529
477
|
const layout = labelNode.node.getComputedLayout();
|
|
530
|
-
labelNode.render(ctx, labelX - layout.width / 2, labelY - layout.height / 2);
|
|
478
|
+
await labelNode.render(ctx, labelX - layout.width / 2, labelY - layout.height / 2);
|
|
531
479
|
}
|
|
532
480
|
}
|
|
533
481
|
else {
|
|
@@ -541,12 +489,12 @@ class ChartNode extends layout_canvas.BoxNode {
|
|
|
541
489
|
}
|
|
542
490
|
}
|
|
543
491
|
currentAngle = endAngle;
|
|
544
|
-
}
|
|
492
|
+
}
|
|
545
493
|
if (chartOptions?.showLegend) {
|
|
546
|
-
this.renderLegend(ctx, x + legendLayout.x, y + legendLayout.y, legendLayout.width, legendLayout.height);
|
|
494
|
+
await this.renderLegend(ctx, x + legendLayout.x, y + legendLayout.y, legendLayout.width, legendLayout.height);
|
|
547
495
|
}
|
|
548
496
|
}
|
|
549
|
-
renderDoughnutChart(ctx, x, y, width, height) {
|
|
497
|
+
async renderDoughnutChart(ctx, x, y, width, height) {
|
|
550
498
|
if (this.chartType !== 'doughnut')
|
|
551
499
|
return;
|
|
552
500
|
const data = this.chartData;
|
|
@@ -562,7 +510,8 @@ class ChartNode extends layout_canvas.BoxNode {
|
|
|
562
510
|
const innerRadius = outerRadius * (chartOptions?.innerRadius ?? 0.6);
|
|
563
511
|
const total = data.reduce((sum, point) => sum + point.value, 0);
|
|
564
512
|
let currentAngle = -Math.PI / 2;
|
|
565
|
-
data.
|
|
513
|
+
for (let index = 0; index < data.length; index++) {
|
|
514
|
+
const point = data[index];
|
|
566
515
|
const sliceAngle = (point.value / total) * Math.PI * 2;
|
|
567
516
|
const startAngle = currentAngle;
|
|
568
517
|
const endAngle = currentAngle + sliceAngle;
|
|
@@ -581,21 +530,13 @@ class ChartNode extends layout_canvas.BoxNode {
|
|
|
581
530
|
const labelRadius = innerRadius + (outerRadius - innerRadius) / 2;
|
|
582
531
|
const labelX = centerX + Math.cos(labelAngle) * labelRadius;
|
|
583
532
|
const labelY = centerY + Math.sin(labelAngle) * labelRadius;
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
const labelNode = buildDescriptorTree(preComputedLabelDesc);
|
|
587
|
-
labelNode.processInitialChildren();
|
|
588
|
-
labelNode.node.calculateLayout(undefined, undefined, common_const.Style.Direction.LTR);
|
|
589
|
-
const layout = labelNode.node.getComputedLayout();
|
|
590
|
-
labelNode.render(ctx, labelX - layout.width / 2, labelY - layout.height / 2);
|
|
591
|
-
}
|
|
592
|
-
else if (chartOptions.renderLabelItem) {
|
|
593
|
-
const labelNode = chartOptions.renderLabelItem({ item: point, index });
|
|
533
|
+
if (chartOptions.renderLabelItem) {
|
|
534
|
+
const labelNode = await chartOptions.renderLabelItem({ item: point, index });
|
|
594
535
|
if (labelNode) {
|
|
595
536
|
labelNode.processInitialChildren();
|
|
596
537
|
labelNode.node.calculateLayout(undefined, undefined, common_const.Style.Direction.LTR);
|
|
597
538
|
const layout = labelNode.node.getComputedLayout();
|
|
598
|
-
labelNode.render(ctx, labelX - layout.width / 2, labelY - layout.height / 2);
|
|
539
|
+
await labelNode.render(ctx, labelX - layout.width / 2, labelY - layout.height / 2);
|
|
599
540
|
}
|
|
600
541
|
}
|
|
601
542
|
else {
|
|
@@ -609,48 +550,31 @@ class ChartNode extends layout_canvas.BoxNode {
|
|
|
609
550
|
}
|
|
610
551
|
}
|
|
611
552
|
currentAngle = endAngle;
|
|
612
|
-
}
|
|
553
|
+
}
|
|
613
554
|
if (chartOptions?.showLegend) {
|
|
614
|
-
this.renderLegend(ctx, x + legendLayout.x, y + legendLayout.y, legendLayout.width, legendLayout.height);
|
|
555
|
+
await this.renderLegend(ctx, x + legendLayout.x, y + legendLayout.y, legendLayout.width, legendLayout.height);
|
|
615
556
|
}
|
|
616
557
|
}
|
|
617
|
-
renderLegend(ctx, x, y, width, height) {
|
|
618
|
-
const
|
|
619
|
-
|
|
620
|
-
const finalNodes = _preComputedLegendItems.filter((desc) => !!desc).map(desc => buildDescriptorTree(desc));
|
|
621
|
-
if (finalNodes.length > 0) {
|
|
622
|
-
const legendContainer = new layout_canvas.RowNode({
|
|
623
|
-
children: finalNodes,
|
|
624
|
-
width,
|
|
625
|
-
height,
|
|
626
|
-
justifyContent: common_const.Style.Justify.Center,
|
|
627
|
-
alignItems: common_const.Style.Align.Center,
|
|
628
|
-
flexWrap: common_const.Style.Wrap.Wrap,
|
|
629
|
-
gap: 10,
|
|
630
|
-
});
|
|
631
|
-
legendContainer.processInitialChildren();
|
|
632
|
-
legendContainer.node.calculateLayout(width, height, common_const.Style.Direction.LTR);
|
|
633
|
-
legendContainer.render(ctx, x, y);
|
|
634
|
-
}
|
|
635
|
-
return;
|
|
636
|
-
}
|
|
558
|
+
async renderLegend(ctx, x, y, width, height) {
|
|
559
|
+
const chartOptions = this.chartOptions;
|
|
560
|
+
const renderLegendItem = chartOptions?.renderLegendItem;
|
|
637
561
|
if (renderLegendItem) {
|
|
638
562
|
let legendNodes;
|
|
639
563
|
if (this.chartType === 'bar' || this.chartType === 'line') {
|
|
640
564
|
const items = this.chartData.datasets;
|
|
641
565
|
const render = renderLegendItem;
|
|
642
|
-
legendNodes = items.map((item, index) => {
|
|
566
|
+
legendNodes = await Promise.all(items.map(async (item, index) => {
|
|
643
567
|
const color = item.color || this.generateColor(index);
|
|
644
568
|
return render({ item, index, color });
|
|
645
|
-
});
|
|
569
|
+
}));
|
|
646
570
|
}
|
|
647
571
|
else {
|
|
648
572
|
const items = this.chartData;
|
|
649
573
|
const render = renderLegendItem;
|
|
650
|
-
legendNodes = items.map((item, index) => {
|
|
574
|
+
legendNodes = await Promise.all(items.map(async (item, index) => {
|
|
651
575
|
const color = item.color || this.generateColor(index);
|
|
652
576
|
return render({ item, index, color });
|
|
653
|
-
});
|
|
577
|
+
}));
|
|
654
578
|
}
|
|
655
579
|
const finalNodes = legendNodes.filter((node) => !!node);
|
|
656
580
|
if (finalNodes.length > 0) {
|
|
@@ -665,11 +589,13 @@ class ChartNode extends layout_canvas.BoxNode {
|
|
|
665
589
|
});
|
|
666
590
|
legendContainer.processInitialChildren();
|
|
667
591
|
legendContainer.node.calculateLayout(width, height, common_const.Style.Direction.LTR);
|
|
668
|
-
legendContainer.render(ctx, x, y);
|
|
592
|
+
await legendContainer.render(ctx, x, y);
|
|
669
593
|
}
|
|
670
594
|
return;
|
|
671
595
|
}
|
|
672
596
|
// Fallback to default rendering if renderLegendItem is not provided
|
|
597
|
+
if (!this.chartData)
|
|
598
|
+
return;
|
|
673
599
|
const legendItems = 'datasets' in this.chartData
|
|
674
600
|
? this.chartData.datasets.map(d => ({ label: d.label, value: d.data.reduce((a, b) => a + b, 0) }))
|
|
675
601
|
: this.chartData;
|
|
@@ -679,7 +605,7 @@ class ChartNode extends layout_canvas.BoxNode {
|
|
|
679
605
|
const textHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
|
|
680
606
|
const itemHeight = Math.ceil(textHeight + 8);
|
|
681
607
|
const boxSize = Math.min(15, itemHeight - 2);
|
|
682
|
-
const position = this.chartOptions
|
|
608
|
+
const position = this.chartOptions?.legendPosition;
|
|
683
609
|
if (position === 'top' || position === 'bottom') {
|
|
684
610
|
const itemPadding = 20; // horizontal padding between items
|
|
685
611
|
const rows = [];
|