abstract-chart 10.0.11 → 10.0.12
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/README.md +1 -1
- package/lib/axis.js +22 -72
- package/lib/axis.js.map +1 -1
- package/lib/chart.d.ts +14 -14
- package/lib/chart.d.ts.map +1 -1
- package/lib/chart.js +51 -109
- package/lib/chart.js.map +1 -1
- package/lib/index.js +2 -18
- package/lib/index.js.map +1 -1
- package/package.json +3 -3
- package/src/chart.ts +49 -45
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "abstract-chart",
|
|
3
|
-
"version": "10.0.
|
|
3
|
+
"version": "10.0.12",
|
|
4
4
|
"description": "Drawing charts using multiple unit of measure axes as coordinate system",
|
|
5
5
|
"repository": "https://github.com/dividab/abstract-visuals/tree/master/packages/abstract-chart",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
"README.md"
|
|
19
19
|
],
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"abstract-image": "^11.0.
|
|
21
|
+
"abstract-image": "^11.0.4",
|
|
22
22
|
"ts-exhaustive-check": "^1.0.0"
|
|
23
23
|
},
|
|
24
|
-
"gitHead": "
|
|
24
|
+
"gitHead": "2b28beae0303be1d261b3b91a7bd946986ba334a"
|
|
25
25
|
}
|
package/src/chart.ts
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
/* eslint-disable max-lines */
|
|
2
|
-
import * as AI from "abstract-image";
|
|
3
|
-
import * as Axis from "./axis.js";
|
|
4
2
|
import { exhaustiveCheck } from "ts-exhaustive-check";
|
|
3
|
+
import * as AI from "abstract-image";
|
|
4
|
+
import {
|
|
5
|
+
Axis,
|
|
6
|
+
AxisBase,
|
|
7
|
+
inverseTransformValue,
|
|
8
|
+
getTicks,
|
|
9
|
+
createLinearAxis,
|
|
10
|
+
transformValue,
|
|
11
|
+
transformPoint,
|
|
12
|
+
DiscreteAxisPoint,
|
|
13
|
+
} from "./axis.js";
|
|
5
14
|
|
|
6
15
|
// tslint:disable:max-file-line-count
|
|
7
16
|
|
|
@@ -22,10 +31,10 @@ export interface Chart {
|
|
|
22
31
|
readonly chartDataAxisesTop: Array<ChartDataAxis>;
|
|
23
32
|
readonly chartDataAxisesLeft: Array<ChartDataAxis>;
|
|
24
33
|
readonly chartDataAxisesRight: Array<ChartDataAxis>;
|
|
25
|
-
readonly xAxisesBottom: ReadonlyArray<Axis
|
|
26
|
-
readonly xAxisesTop: ReadonlyArray<Axis
|
|
27
|
-
readonly yAxisesLeft: ReadonlyArray<Axis
|
|
28
|
-
readonly yAxisesRight: ReadonlyArray<Axis
|
|
34
|
+
readonly xAxisesBottom: ReadonlyArray<Axis>;
|
|
35
|
+
readonly xAxisesTop: ReadonlyArray<Axis>;
|
|
36
|
+
readonly yAxisesLeft: ReadonlyArray<Axis>;
|
|
37
|
+
readonly yAxisesRight: ReadonlyArray<Axis>;
|
|
29
38
|
readonly backgroundColor: AI.Color;
|
|
30
39
|
readonly xGrid: ChartGrid;
|
|
31
40
|
readonly yGrid: ChartGrid;
|
|
@@ -230,7 +239,7 @@ export function createChartStack(props: ChartStackProps): ChartStack {
|
|
|
230
239
|
return { points, xAxis, yAxis, config };
|
|
231
240
|
}
|
|
232
241
|
|
|
233
|
-
export type ChartDataAxis =
|
|
242
|
+
export type ChartDataAxis = AxisBase & {
|
|
234
243
|
readonly points: Array<AI.Point>;
|
|
235
244
|
};
|
|
236
245
|
|
|
@@ -268,13 +277,8 @@ export function inverseTransformPoint(point: AI.Point, chart: Chart, xAxis: XAxi
|
|
|
268
277
|
const xMax = chart.width - padding.right;
|
|
269
278
|
const yMin = chart.height - padding.bottom;
|
|
270
279
|
const yMax = padding.top;
|
|
271
|
-
const x =
|
|
272
|
-
|
|
273
|
-
xMin,
|
|
274
|
-
xMax,
|
|
275
|
-
xAxis === "top" ? chart.xAxisesTop[0] : chart.xAxisesBottom[0]
|
|
276
|
-
);
|
|
277
|
-
const y = Axis.inverseTransformValue(
|
|
280
|
+
const x = inverseTransformValue(point.x, xMin, xMax, xAxis === "top" ? chart.xAxisesTop[0] : chart.xAxisesBottom[0]);
|
|
281
|
+
const y = inverseTransformValue(
|
|
278
282
|
point.y,
|
|
279
283
|
yMin,
|
|
280
284
|
yMax,
|
|
@@ -461,7 +465,7 @@ export function generateBackground(xMin: number, xMax: number, yMin: number, yMa
|
|
|
461
465
|
export function xAxises(
|
|
462
466
|
xAxis: XAxis,
|
|
463
467
|
xNumTicks: number,
|
|
464
|
-
axises: ReadonlyArray<Axis
|
|
468
|
+
axises: ReadonlyArray<Axis>,
|
|
465
469
|
xMin: number,
|
|
466
470
|
xMax: number,
|
|
467
471
|
yMin: number,
|
|
@@ -476,7 +480,7 @@ export function xAxises(
|
|
|
476
480
|
const [dirFactor, axisWidth] = xAxis === "bottom" ? [1, chart.axisWidth.bottom] : [-1, chart.axisWidth.top];
|
|
477
481
|
for (const [ix, axis] of axises.entries()) {
|
|
478
482
|
const fullGrid = ix === 0 && xAxis === "bottom";
|
|
479
|
-
const xTicks =
|
|
483
|
+
const xTicks = getTicks(xNumTicks, axis);
|
|
480
484
|
if (chart.xGrid && !axis.noTicks) {
|
|
481
485
|
gridLineComponents.push(
|
|
482
486
|
generateXAxisGridLines(xMin, xMax, lineY + dirFactor * 10, fullGrid ? yMax : lineY, xTicks, axis, chart.xGrid)
|
|
@@ -533,7 +537,7 @@ export function xAxises(
|
|
|
533
537
|
export function yAxises(
|
|
534
538
|
yAxis: YAxis,
|
|
535
539
|
yNumTicks: number,
|
|
536
|
-
axises: ReadonlyArray<Axis
|
|
540
|
+
axises: ReadonlyArray<Axis>,
|
|
537
541
|
xMin: number,
|
|
538
542
|
xMax: number,
|
|
539
543
|
yMin: number,
|
|
@@ -549,7 +553,7 @@ export function yAxises(
|
|
|
549
553
|
|
|
550
554
|
for (const [ix, axis] of axises.entries()) {
|
|
551
555
|
const fullGrid = ix === 0 && yAxis === "left";
|
|
552
|
-
const yTicks =
|
|
556
|
+
const yTicks = getTicks(yNumTicks, axis);
|
|
553
557
|
if (chart.yGrid && !axis.noTicks) {
|
|
554
558
|
gridLineComponents.push(
|
|
555
559
|
generateYAxisLines(
|
|
@@ -624,7 +628,7 @@ export function generateDataAxisesX(
|
|
|
624
628
|
for (const axis of axises) {
|
|
625
629
|
const min = Math.min(...axis.points.map((p) => p.y));
|
|
626
630
|
const max = Math.max(...axis.points.map((p) => p.y));
|
|
627
|
-
const linear =
|
|
631
|
+
const linear = createLinearAxis(
|
|
628
632
|
min,
|
|
629
633
|
max,
|
|
630
634
|
axis.label,
|
|
@@ -653,12 +657,12 @@ export function generateDataAxisesX(
|
|
|
653
657
|
}
|
|
654
658
|
return axis.points[axis.points.length - 1]?.x ?? 0;
|
|
655
659
|
};
|
|
656
|
-
const yValues =
|
|
660
|
+
const yValues = getTicks(numTicks, linear).map((t) => t.value);
|
|
657
661
|
const lineY2 = lineY;
|
|
658
662
|
components.push(
|
|
659
663
|
...yValues.flatMap((y) => {
|
|
660
664
|
const tickX = findX(y);
|
|
661
|
-
const x =
|
|
665
|
+
const x = transformValue(tickX, xMin, xMax, chart.xAxisesBottom[0]);
|
|
662
666
|
const start = AI.createPoint(x, lineY2);
|
|
663
667
|
const end = AI.createPoint(x, lineY2 + dirFactor * 10);
|
|
664
668
|
const textPos = AI.createPoint(x, lineY2 + dirFactor * 12);
|
|
@@ -734,7 +738,7 @@ export function generateDataAxisesY(
|
|
|
734
738
|
for (const axis of axises) {
|
|
735
739
|
const min = Math.min(...axis.points.map((p) => p.y));
|
|
736
740
|
const max = Math.max(...axis.points.map((p) => p.y));
|
|
737
|
-
const linear =
|
|
741
|
+
const linear = createLinearAxis(
|
|
738
742
|
min,
|
|
739
743
|
max,
|
|
740
744
|
axis.label,
|
|
@@ -763,12 +767,12 @@ export function generateDataAxisesY(
|
|
|
763
767
|
}
|
|
764
768
|
return axis.points[axis.points.length - 1]?.x ?? 0;
|
|
765
769
|
};
|
|
766
|
-
const yValues =
|
|
770
|
+
const yValues = getTicks(numTicks, linear).map((t) => t.value);
|
|
767
771
|
const lineX2 = lineX;
|
|
768
772
|
components.push(
|
|
769
773
|
...yValues.flatMap((y) => {
|
|
770
774
|
const tickY = findX(y);
|
|
771
|
-
const yPx =
|
|
775
|
+
const yPx = transformValue(tickY, yMin, yMax, chart.yAxisesLeft[0]);
|
|
772
776
|
const start = AI.createPoint(lineX2, yPx);
|
|
773
777
|
const end = AI.createPoint(lineX2 + dirFactor * 10, yPx);
|
|
774
778
|
const textPos = AI.createPoint(lineX2 + dirFactor * 12, yPx);
|
|
@@ -864,7 +868,7 @@ function generateUnsignedStack(xMin: number, xMax: number, yMin: number, yMax: n
|
|
|
864
868
|
let sumY = 0;
|
|
865
869
|
const points = stackPoints.ys.map((y) => {
|
|
866
870
|
sumY += y;
|
|
867
|
-
return
|
|
871
|
+
return transformPoint(AI.createPoint(stackPoints.x, sumY), xMin, xMax, yMin, yMax, xAxis, yAxis);
|
|
868
872
|
});
|
|
869
873
|
return points;
|
|
870
874
|
});
|
|
@@ -880,7 +884,7 @@ function generateUnsignedStack(xMin: number, xMax: number, yMin: number, yMax: n
|
|
|
880
884
|
|
|
881
885
|
const polygons: Array<AI.Polygon> = [];
|
|
882
886
|
let lastLine = chart.chartStack.points.map((stackPoint) =>
|
|
883
|
-
|
|
887
|
+
transformPoint(AI.createPoint(stackPoint.x, 0), xMin, xMax, yMin, yMax, xAxis, yAxis)
|
|
884
888
|
);
|
|
885
889
|
lines.forEach((line, index) => {
|
|
886
890
|
const config = chart.chartStack.config[index];
|
|
@@ -903,7 +907,7 @@ export function generateLines(xMin: number, xMax: number, yMin: number, yMax: nu
|
|
|
903
907
|
}
|
|
904
908
|
const xAxis = l.xAxis === "top" ? chart.xAxisesTop[0] : chart.xAxisesBottom[0];
|
|
905
909
|
const yAxis = l.yAxis === "right" ? chart.yAxisesRight[0] : chart.yAxisesLeft[0];
|
|
906
|
-
const points = l.points.map((p) =>
|
|
910
|
+
const points = l.points.map((p) => transformPoint(p, xMin, xMax, yMin, yMax, xAxis, yAxis));
|
|
907
911
|
const segments = getLineSegmentsInsideChart(xMin, xMax, yMin, yMax, points);
|
|
908
912
|
const components = [];
|
|
909
913
|
const outlineColor = l.textOutlineColor ?? chart.textOutlineColor;
|
|
@@ -1020,7 +1024,7 @@ export function generatePoints(xMin: number, xMax: number, yMin: number, yMax: n
|
|
|
1020
1024
|
const points = chart.chartPoints.map((p) => {
|
|
1021
1025
|
const xAxis = p.xAxis === "top" ? chart.xAxisesTop[0] : chart.xAxisesBottom[0];
|
|
1022
1026
|
const yAxis = p.yAxis === "right" ? chart.yAxisesRight[0] : chart.yAxisesLeft[0];
|
|
1023
|
-
const position =
|
|
1027
|
+
const position = transformPoint(p.position, xMin, xMax, yMin, yMax, xAxis, yAxis);
|
|
1024
1028
|
const outlineColor = p.textOutlineColor ?? chart.textOutlineColor;
|
|
1025
1029
|
const components = [
|
|
1026
1030
|
generatePointShape(p, position, undefined),
|
|
@@ -1090,9 +1094,9 @@ export function generateBars(xMin: number, xMax: number, yMin: number, yMax: num
|
|
|
1090
1094
|
AI.createPoint(barPos, (b.max + (b.min ?? yMinValue)) / 2),
|
|
1091
1095
|
AI.createPoint(barPos + bars.width / 2, b.min ?? yMinValue),
|
|
1092
1096
|
];
|
|
1093
|
-
const pos =
|
|
1094
|
-
const topLeft =
|
|
1095
|
-
const bottomRight =
|
|
1097
|
+
const pos = transformPoint(middle, xMin, xMax, yMin, yMax, xAxis, yAxis);
|
|
1098
|
+
const topLeft = transformPoint(tl, xMin, xMax, yMin, yMax, xAxis, yAxis);
|
|
1099
|
+
const bottomRight = transformPoint(br, xMin, xMax, yMin, yMax, xAxis, yAxis);
|
|
1096
1100
|
components.push(
|
|
1097
1101
|
AI.createRectangle(
|
|
1098
1102
|
topLeft,
|
|
@@ -1164,12 +1168,12 @@ export function generateXAxisGridLines(
|
|
|
1164
1168
|
xMax: number,
|
|
1165
1169
|
yMin: number,
|
|
1166
1170
|
yMax: number,
|
|
1167
|
-
xTicks: ReadonlyArray<
|
|
1168
|
-
xAxis: Axis
|
|
1171
|
+
xTicks: ReadonlyArray<DiscreteAxisPoint>,
|
|
1172
|
+
xAxis: Axis,
|
|
1169
1173
|
xGrid: { readonly color: AI.Color; readonly thickness: number }
|
|
1170
1174
|
): AI.Component {
|
|
1171
1175
|
const xLines = xTicks.map((l) => {
|
|
1172
|
-
const x =
|
|
1176
|
+
const x = transformValue(l.value, xMin, xMax, xAxis);
|
|
1173
1177
|
const start = AI.createPoint(x, yMin);
|
|
1174
1178
|
const end = AI.createPoint(x, yMax);
|
|
1175
1179
|
return AI.createLine(start, end, xGrid.color, xGrid.thickness);
|
|
@@ -1183,8 +1187,8 @@ export function generateXAxisLabels(
|
|
|
1183
1187
|
xMax: number,
|
|
1184
1188
|
y: number,
|
|
1185
1189
|
growVertical: AI.GrowthDirection,
|
|
1186
|
-
ticks: ReadonlyArray<
|
|
1187
|
-
axis: Axis
|
|
1190
|
+
ticks: ReadonlyArray<DiscreteAxisPoint>,
|
|
1191
|
+
axis: Axis,
|
|
1188
1192
|
chart: Chart
|
|
1189
1193
|
): AI.Component {
|
|
1190
1194
|
const rotation = axis.labelRotation ?? 0;
|
|
@@ -1200,7 +1204,7 @@ export function generateXAxisLabels(
|
|
|
1200
1204
|
}
|
|
1201
1205
|
})();
|
|
1202
1206
|
const xLabels = ticks.map((l) => {
|
|
1203
|
-
const position = AI.createPoint(
|
|
1207
|
+
const position = AI.createPoint(transformValue(l.value, xMin, xMax, axis), y);
|
|
1204
1208
|
return AI.createText(
|
|
1205
1209
|
position,
|
|
1206
1210
|
l.label ?? formatNumber(l.value),
|
|
@@ -1225,7 +1229,7 @@ export function generateXAxisLabel(
|
|
|
1225
1229
|
y: number,
|
|
1226
1230
|
horizontalGrowthDirection: AI.GrowthDirection,
|
|
1227
1231
|
verticalGrowthDirection: AI.GrowthDirection,
|
|
1228
|
-
axis: Axis
|
|
1232
|
+
axis: Axis,
|
|
1229
1233
|
chart: Chart
|
|
1230
1234
|
): AI.Component {
|
|
1231
1235
|
const position = AI.createPoint(x, y);
|
|
@@ -1252,13 +1256,13 @@ export function generateYAxisLines(
|
|
|
1252
1256
|
xMax: number,
|
|
1253
1257
|
yMin: number,
|
|
1254
1258
|
yMax: number,
|
|
1255
|
-
yTicks: ReadonlyArray<
|
|
1256
|
-
yAxis: Axis
|
|
1259
|
+
yTicks: ReadonlyArray<DiscreteAxisPoint>,
|
|
1260
|
+
yAxis: Axis,
|
|
1257
1261
|
yGrid: { readonly color: AI.Color; readonly thickness: number },
|
|
1258
1262
|
xGrid: { readonly color: AI.Color; readonly thickness: number }
|
|
1259
1263
|
): AI.Component {
|
|
1260
1264
|
const yLines = yTicks.map((l) => {
|
|
1261
|
-
const y =
|
|
1265
|
+
const y = transformValue(l.value, yMin, yMax, yAxis);
|
|
1262
1266
|
const start = AI.createPoint(xMin - xGrid.thickness / 2, y);
|
|
1263
1267
|
const end = AI.createPoint(xMax + xGrid.thickness / 2, y);
|
|
1264
1268
|
return AI.createLine(start, end, yGrid.color, yGrid.thickness);
|
|
@@ -1271,8 +1275,8 @@ export function generateYAxisLabels(
|
|
|
1271
1275
|
yMin: number,
|
|
1272
1276
|
yMax: number,
|
|
1273
1277
|
growHorizontal: AI.GrowthDirection,
|
|
1274
|
-
yTicks: ReadonlyArray<
|
|
1275
|
-
yAxis: Axis
|
|
1278
|
+
yTicks: ReadonlyArray<DiscreteAxisPoint>,
|
|
1279
|
+
yAxis: Axis,
|
|
1276
1280
|
chart: Chart
|
|
1277
1281
|
): AI.Component {
|
|
1278
1282
|
const rotation = yAxis.labelRotation ?? 0;
|
|
@@ -1288,7 +1292,7 @@ export function generateYAxisLabels(
|
|
|
1288
1292
|
})();
|
|
1289
1293
|
|
|
1290
1294
|
const yLabels = yTicks.map((l) => {
|
|
1291
|
-
const position = AI.createPoint(x,
|
|
1295
|
+
const position = AI.createPoint(x, transformValue(l.value, yMin, yMax, yAxis));
|
|
1292
1296
|
return AI.createText(
|
|
1293
1297
|
position,
|
|
1294
1298
|
l.label ?? formatNumber(l.value),
|
|
@@ -1314,7 +1318,7 @@ export function generateYAxisLabel(
|
|
|
1314
1318
|
rotation: number,
|
|
1315
1319
|
horizontalGrowthDirection: AI.GrowthDirection,
|
|
1316
1320
|
verticalGrowthDirection: AI.GrowthDirection,
|
|
1317
|
-
axis: Axis
|
|
1321
|
+
axis: Axis,
|
|
1318
1322
|
chart: Chart
|
|
1319
1323
|
): AI.Component {
|
|
1320
1324
|
const position = AI.createPoint(x, y);
|