@cehlers88/chart 1.1.1 → 1.2.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/README.md +145 -3
- package/dist/ChartEngine.d.ts +54 -0
- package/dist/Factory/DataGroupFactory.d.ts +14 -1
- package/dist/Registry/DiagramRegistry.d.ts +8 -0
- package/dist/customElement/CanvasDiagram.d.ts +30 -0
- package/dist/index.d.ts +2 -3
- package/dist/index.js +11 -11
- package/dist/interface/ICanvasDiagram.d.ts +14 -0
- package/dist/interface/IChartEngine.d.ts +8 -0
- package/dist/plugin/AbstractDiagramPlugin.d.ts +2 -4
- package/dist/plugin/AbstractPlugin.d.ts +14 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -60,13 +60,104 @@ Attributes:
|
|
|
60
60
|
|
|
61
61
|
| Attribute | Description | Default |
|
|
62
62
|
|-------------|----------------------------------------------------------------------|---------|
|
|
63
|
-
| `width` | Canvas width in pixels
|
|
63
|
+
| `width` | Canvas width in pixels; `100%`/`auto` makes the diagram responsive (it takes the width of its container and is redrawn sharply whenever that changes) | `300` |
|
|
64
64
|
| `height` | Canvas height in pixels | `150` |
|
|
65
65
|
| `value` | JSON string with the data groups (see data format below) | `[]` |
|
|
66
66
|
| `autostart` | Starts the chart automatically once mounted (`"true"`/`"false"`) | `true` |
|
|
67
67
|
|
|
68
68
|
Additional plugins can be registered on the element before it starts via `getPlugin()`/`addPlugin()`.
|
|
69
69
|
|
|
70
|
+
## Changing data at runtime
|
|
71
|
+
|
|
72
|
+
The data of a chart is not frozen after the page was loaded – it can be read,
|
|
73
|
+
replaced and manipulated at any time, either through the `<canvas-diagram>`
|
|
74
|
+
element or through the `ChartEngine`. A running chart picks the changes up with
|
|
75
|
+
the next frame, no restart needed.
|
|
76
|
+
|
|
77
|
+
```html
|
|
78
|
+
<canvas-diagram id="sales" width="600" height="300"
|
|
79
|
+
value='{"Revenue":[1,5,3,8,2]}'></canvas-diagram>
|
|
80
|
+
|
|
81
|
+
<script type="module">
|
|
82
|
+
import { DataGroupFactory, diagramRegistry } from "@cehlers88/chart";
|
|
83
|
+
|
|
84
|
+
const diagram = document.getElementById("sales");
|
|
85
|
+
// ... or, without a dom reference:
|
|
86
|
+
// const diagram = diagramRegistry.getDiagram("sales");
|
|
87
|
+
|
|
88
|
+
diagram.addValue(6, "Revenue"); // append a value
|
|
89
|
+
diagram.setValue("Revenue", 0, 4); // replace a single value
|
|
90
|
+
diagram.removeValue("Revenue", 1); // remove a single value
|
|
91
|
+
diagram.addDataGroup( // add a whole group
|
|
92
|
+
DataGroupFactory.createDataGroup([2, 3, 1], "Costs", "#e84949")
|
|
93
|
+
);
|
|
94
|
+
diagram.removeDataGroup("Costs"); // remove a whole group
|
|
95
|
+
diagram.setData({ Revenue: [1, 2, 3] }); // replace everything
|
|
96
|
+
diagram.clearData(); // remove everything
|
|
97
|
+
|
|
98
|
+
console.log(diagram.getDataGroups()); // read the current data
|
|
99
|
+
</script>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Setting the `value` attribute again works as well and replaces the complete data:
|
|
103
|
+
|
|
104
|
+
```javascript
|
|
105
|
+
document.getElementById("sales").setAttribute("value", '{"Revenue":[3,4,5]}');
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Methods of `<canvas-diagram>`:
|
|
109
|
+
|
|
110
|
+
| Method | Description |
|
|
111
|
+
|-----------------------------------------|--------------------------------------------------------------------------|
|
|
112
|
+
| `setData(definition)` | Replaces all data. Accepts a JSON string, an array or an object |
|
|
113
|
+
| `setDataGroups(dataGroups)` | Replaces all data with ready-made `TDataGroup`s |
|
|
114
|
+
| `getDataGroups()` | Returns the current data groups |
|
|
115
|
+
| `getDataGroup(labelOrIndex)` | Returns a single data group |
|
|
116
|
+
| `addDataGroup(dataGroup)` | Adds a data group |
|
|
117
|
+
| `removeDataGroup(labelOrIndex)` | Removes a data group |
|
|
118
|
+
| `addValue(value, groupName?)` | Appends a value; creates the group if it does not exist yet |
|
|
119
|
+
| `setValue(labelOrIndex, index, value)` | Replaces a single value; missing values in between are filled up empty |
|
|
120
|
+
| `removeValue(labelOrIndex, index)` | Removes a single value |
|
|
121
|
+
| `clearData()` | Removes all data groups |
|
|
122
|
+
| `addPlugin(plugin)` / `getPlugin(name)` | Registers / returns a plugin – also while the chart is already running |
|
|
123
|
+
| `start()` / `stop()` | Starts / stops the render loop |
|
|
124
|
+
| `getEngine()` | Returns the underlying `ChartEngine` |
|
|
125
|
+
|
|
126
|
+
The same data methods exist on `ChartEngine`, so the programmatic usage works
|
|
127
|
+
identically:
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
const engine = new ChartEngine(canvas, { plugins: [new plugins.BarsPlugin()] });
|
|
131
|
+
|
|
132
|
+
engine.setData({ Revenue: [1, 5, 3] });
|
|
133
|
+
engine.start();
|
|
134
|
+
|
|
135
|
+
setInterval(() => engine.addValue(Math.random() * 10, "Revenue"), 1000);
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Data methods may be called before the element is mounted as well; those calls
|
|
139
|
+
are applied as soon as the element is connected (and take precedence over the
|
|
140
|
+
`value` attribute).
|
|
141
|
+
|
|
142
|
+
### Live data
|
|
143
|
+
|
|
144
|
+
For values that arrive after the page was loaded (ajax, Mercure, websockets, …) give the
|
|
145
|
+
group a `maxLength` and append the new values with their timestamp. The oldest values are
|
|
146
|
+
pushed out, so the chart keeps its time window, and the new value is labelled like the
|
|
147
|
+
initial ones:
|
|
148
|
+
|
|
149
|
+
```html
|
|
150
|
+
<canvas-diagram id="co2" width="100%" height="110"
|
|
151
|
+
value='{"CO2":{"data":[450,470],"timestamps":[1790000000,1790000600],"unit":"ppm","maxLength":2}}'></canvas-diagram>
|
|
152
|
+
|
|
153
|
+
<script type="module">
|
|
154
|
+
import { diagramRegistry } from "@cehlers88/chart";
|
|
155
|
+
|
|
156
|
+
// without a group name the value goes to the only group of the chart
|
|
157
|
+
diagramRegistry.getDiagram("co2").addValue({ value: 480, timestamp: 1790001200 });
|
|
158
|
+
</script>
|
|
159
|
+
```
|
|
160
|
+
|
|
70
161
|
## Data format
|
|
71
162
|
|
|
72
163
|
`DataGroupFactory` accepts several notations for the values within a group:
|
|
@@ -91,13 +182,58 @@ As a JSON string (e.g. for the custom element's `value` attribute), groups are g
|
|
|
91
182
|
}
|
|
92
183
|
```
|
|
93
184
|
|
|
185
|
+
The object notation takes a few optional keys more:
|
|
186
|
+
|
|
187
|
+
| Key | Description |
|
|
188
|
+
|--------------|-----------------------------------------------------------------------------------------------|
|
|
189
|
+
| `unit` | Unit of the values, shown in the tooltip and on the value axis (`"°C"`, `"ppm"`) |
|
|
190
|
+
| `labels` | One label per value (e.g. the time of a measurement), shown in the tooltip and on the x axis |
|
|
191
|
+
| `timestamps` | One unix timestamp per value (seconds or milliseconds), turned into time labels; `0`/`null` means "no label". Values below 1e11 are read as seconds (up to the year 5138), larger ones as milliseconds (from 1973 on). Single values take theirs as `{ "value": 1, "timestamp": 1790000000 }` |
|
|
192
|
+
| `maxLength` | Maximum number of values; values appended later push the oldest ones out |
|
|
193
|
+
|
|
194
|
+
`null` values are gaps: the line is interrupted there instead of dropping to 0, and they
|
|
195
|
+
do not count for the value range.
|
|
196
|
+
|
|
197
|
+
```json
|
|
198
|
+
{ "CO2": { "data": [null, 450, 470], "timestamps": [0, 1790000000, 1790000600], "unit": "ppm" } }
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Look & theming
|
|
202
|
+
|
|
203
|
+
`DiagramLinePlugin` draws a smooth (monotone, never overshooting) line with a gradient
|
|
204
|
+
fill, a value axis with "nice" steps on the right and - if the values carry labels - a
|
|
205
|
+
label axis at the bottom. Hovering (or tapping) shows a crosshair and a tooltip with the
|
|
206
|
+
values next to the pointer. Options: `smooth`, `fill`, `lineWidth`, `showGrid`,
|
|
207
|
+
`showYLabels`, `showXLabels`, `showTooltip`, `showBulletPoints`, `showZeroLine`,
|
|
208
|
+
`maxYTicks`, `decimals`.
|
|
209
|
+
|
|
210
|
+
Colours are read from CSS custom properties of the canvas, so the host page adapts the
|
|
211
|
+
charts to its theme:
|
|
212
|
+
|
|
213
|
+
```css
|
|
214
|
+
canvas-diagram {
|
|
215
|
+
--chart-text-color: #8a93a6;
|
|
216
|
+
--chart-grid-color: rgba(255, 255, 255, .07);
|
|
217
|
+
--chart-tooltip-background: rgba(12, 12, 12, .94);
|
|
218
|
+
--chart-tooltip-border: rgba(255, 255, 255, .12);
|
|
219
|
+
--chart-tooltip-text-color: #e4e4e4;
|
|
220
|
+
--chart-font: 11px system-ui, sans-serif;
|
|
221
|
+
--chart-background: transparent; /* background of the canvas */
|
|
222
|
+
--chart-border-radius: 0;
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
A plugin property of the same name (`textColor`, `gridColor`, `tooltipBackground`,
|
|
227
|
+
`tooltipBorder`, `tooltipTextColor`, `font`) wins over the CSS property. Numbers and
|
|
228
|
+
times are formatted in the language of the page (`<html lang>`).
|
|
229
|
+
|
|
94
230
|
## Available plugins
|
|
95
231
|
|
|
96
232
|
| Plugin | Purpose |
|
|
97
233
|
|--------------------------|---------------------------------------------------------------------|
|
|
98
234
|
| `BarsPlugin` | Renders data groups as bars |
|
|
99
|
-
| `DiagramLinePlugin` | Renders data groups as lines,
|
|
100
|
-
| `LegendsPlugin` | Displays a legend for the data groups
|
|
235
|
+
| `DiagramLinePlugin` | Renders data groups as lines with value axis, crosshair and tooltip |
|
|
236
|
+
| `LegendsPlugin` | Displays a legend for the data groups (only for two or more groups unless `showSingleGroup`; steps aside while a tooltip covers it) |
|
|
101
237
|
| `TooltipPlugin` | Shows tooltips on hover over data points |
|
|
102
238
|
| `CameraMovePlugin` | Enables scrolling/panning the view via mouse/wheel |
|
|
103
239
|
| `PaginationPlugin` | Splits large data sets into pages |
|
|
@@ -115,6 +251,12 @@ npm run watch # build in watch mode
|
|
|
115
251
|
npm test # run tests with Jest
|
|
116
252
|
```
|
|
117
253
|
|
|
254
|
+
## Release / Deployment
|
|
255
|
+
|
|
256
|
+
Pushes/merges to `main` trigger the `.github/workflows/publish.yml` GitHub Actions workflow, which installs dependencies, runs the tests and the build, and publishes the package to npm if `package.json`'s `version` differs from the version currently published on npm. To cut a release, bump `version` in `package.json` before merging to `main`.
|
|
257
|
+
|
|
258
|
+
This requires an `NPM_TOKEN` repository secret (an npm automation token with publish rights for `@cehlers88/chart`).
|
|
259
|
+
|
|
118
260
|
## License
|
|
119
261
|
|
|
120
262
|
ISC © Christoph Ehlers
|
package/dist/ChartEngine.d.ts
CHANGED
|
@@ -14,8 +14,12 @@ export default class ChartEngine implements IChartEngine {
|
|
|
14
14
|
private _entityRegistry;
|
|
15
15
|
private _ctx;
|
|
16
16
|
private _dataGroups;
|
|
17
|
+
private _dataGroupsSignature;
|
|
18
|
+
private _processedDataGroups;
|
|
17
19
|
private _plugins;
|
|
18
20
|
private _pluginProperties;
|
|
21
|
+
private _created;
|
|
22
|
+
private _runStackEntry;
|
|
19
23
|
constructor(canvasElement: HTMLCanvasElement, properties?: {
|
|
20
24
|
plugins?: IChartPlugin[];
|
|
21
25
|
});
|
|
@@ -26,9 +30,59 @@ export default class ChartEngine implements IChartEngine {
|
|
|
26
30
|
setPluginProperty(propertyName: string, value: any): ChartEngine;
|
|
27
31
|
create(): ChartEngine;
|
|
28
32
|
addDataGroup(dataGroup: TDataGroup): IChartEngine;
|
|
33
|
+
/**
|
|
34
|
+
* Returns the data groups currently held by the engine.
|
|
35
|
+
* The returned groups are the live objects; changes made to them are
|
|
36
|
+
* picked up with the next update cycle.
|
|
37
|
+
*/
|
|
38
|
+
getDataGroups(): TDataGroup[];
|
|
39
|
+
/**
|
|
40
|
+
* Returns a single data group, addressed either by its label or by its index.
|
|
41
|
+
*/
|
|
42
|
+
getDataGroup(group: string | number): TDataGroup | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Replaces all data groups at once.
|
|
45
|
+
*/
|
|
46
|
+
setDataGroups(dataGroups: TDataGroup[]): IChartEngine;
|
|
47
|
+
/**
|
|
48
|
+
* Replaces the complete data of the chart. Accepts everything
|
|
49
|
+
* `DataGroupFactory.parseDataGroupsDefinition` understands: a JSON string,
|
|
50
|
+
* a plain array of values or an object keyed by group name.
|
|
51
|
+
*/
|
|
52
|
+
setData(dataDefinition: string | any[] | object): IChartEngine;
|
|
53
|
+
/**
|
|
54
|
+
* Removes a data group, addressed either by its label or by its index.
|
|
55
|
+
*/
|
|
56
|
+
removeDataGroup(group: string | number): IChartEngine;
|
|
57
|
+
/**
|
|
58
|
+
* Removes all data groups.
|
|
59
|
+
*/
|
|
60
|
+
clearData(): IChartEngine;
|
|
29
61
|
addValue(value: any, groupName?: string): IChartEngine;
|
|
62
|
+
/**
|
|
63
|
+
* Replaces a single value within a data group.
|
|
64
|
+
*/
|
|
65
|
+
setValue(group: string | number, dataIndex: number, value: any): IChartEngine;
|
|
66
|
+
/**
|
|
67
|
+
* Removes a single value from a data group.
|
|
68
|
+
*/
|
|
69
|
+
removeValue(group: string | number, dataIndex: number): IChartEngine;
|
|
30
70
|
draw(): ChartEngine;
|
|
31
71
|
update(): ChartEngine;
|
|
72
|
+
/**
|
|
73
|
+
* Returns the data groups handed to the plugins. They are a detached copy
|
|
74
|
+
* of the data owned by the engine and are renewed whenever that data
|
|
75
|
+
* changed. Without that separation the plugins would hold references to
|
|
76
|
+
* the very objects manipulated from outside, so neither they nor the
|
|
77
|
+
* engine could tell a manipulation from the state of the last frame.
|
|
78
|
+
*/
|
|
79
|
+
private getPipelineDataGroups;
|
|
32
80
|
start(): void;
|
|
81
|
+
/**
|
|
82
|
+
* Stops the render loop of this engine. The data stays untouched, so the
|
|
83
|
+
* chart can be started again later on.
|
|
84
|
+
*/
|
|
85
|
+
stop(): ChartEngine;
|
|
86
|
+
isRunning(): boolean;
|
|
33
87
|
private getEngineCallbacks;
|
|
34
88
|
}
|
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
import { TDataGroup } from "../type/TDataGroup";
|
|
2
|
+
import { TData } from "../type/TData";
|
|
2
3
|
export default class DataGroupFactory {
|
|
3
4
|
static buildCounter: number;
|
|
4
5
|
private static _colors;
|
|
5
6
|
private static _lastColorIndex;
|
|
7
|
+
/**
|
|
8
|
+
* Normalizes a single value definition into a TData object.
|
|
9
|
+
* Accepts plain numbers, ranges ([start, end]), null (empty value) and
|
|
10
|
+
* objects like {value, valueStart, label}.
|
|
11
|
+
*/
|
|
12
|
+
static createDataValue(valueDef: any): TData;
|
|
6
13
|
static createDataGroup(values: any[], groupLabel?: string, color?: string): TDataGroup;
|
|
7
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Parses a data group definition. Beside the JSON notation used by the
|
|
16
|
+
* `value` attribute of `<canvas-diagram>` an already parsed object/array
|
|
17
|
+
* may be passed, so data can be handed over programmatically at runtime.
|
|
18
|
+
*/
|
|
19
|
+
static parseDataGroupsDefinition(value: string | any[] | object): TDataGroup[];
|
|
20
|
+
static getNextColor(): string;
|
|
8
21
|
static setColor(color: string, index: number): void;
|
|
9
22
|
static setColors(colors: string[]): void;
|
|
10
23
|
}
|
|
@@ -8,9 +8,17 @@ import CanvasDiagram from "../customElement/CanvasDiagram";
|
|
|
8
8
|
import { ICanvasDiagram } from "../interface/ICanvasDiagram";
|
|
9
9
|
declare class DiagramRegistry {
|
|
10
10
|
private static _identPrefix;
|
|
11
|
+
private static _identCounter;
|
|
11
12
|
private createUniqueIdentifier;
|
|
12
13
|
getDiagram(identifier: string): ICanvasDiagram;
|
|
14
|
+
hasDiagram(identifier: string): boolean;
|
|
15
|
+
getDiagrams(): ICanvasDiagram[];
|
|
13
16
|
register(diagram: CanvasDiagram, identifier?: string): DiagramRegistry;
|
|
17
|
+
/**
|
|
18
|
+
* Removes a diagram from the registry, either by its identifier or by the
|
|
19
|
+
* element itself, so removed diagrams are not kept alive by the registry.
|
|
20
|
+
*/
|
|
21
|
+
unregister(diagram: CanvasDiagram | string): DiagramRegistry;
|
|
14
22
|
}
|
|
15
23
|
export default DiagramRegistry;
|
|
16
24
|
export declare const diagramRegistry: DiagramRegistry;
|
|
@@ -7,13 +7,43 @@
|
|
|
7
7
|
import '../style/CanvasDiagram.css';
|
|
8
8
|
import { IChartPlugin } from "../interface/IChartPlugin";
|
|
9
9
|
import { ICanvasDiagram } from "../interface/ICanvasDiagram";
|
|
10
|
+
import { TDataGroup } from "../type/TDataGroup";
|
|
11
|
+
import { IChartEngine } from "../interface/IChartEngine";
|
|
10
12
|
declare class CanvasDiagram extends HTMLElement implements ICanvasDiagram {
|
|
11
13
|
private _cleanDom;
|
|
12
14
|
private _engine;
|
|
15
|
+
private _ignoreValueAttribute;
|
|
16
|
+
private _pendingActions;
|
|
17
|
+
static get observedAttributes(): string[];
|
|
13
18
|
connectedCallback(): void;
|
|
19
|
+
disconnectedCallback(): void;
|
|
20
|
+
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
14
21
|
addPlugin(plugin: IChartPlugin): ICanvasDiagram;
|
|
15
22
|
getPlugin(pluginName: string): IChartPlugin | undefined;
|
|
23
|
+
getEngine(): IChartEngine | undefined;
|
|
24
|
+
addDataGroup(dataGroup: TDataGroup): ICanvasDiagram;
|
|
25
|
+
addValue(value: any, groupName?: string): ICanvasDiagram;
|
|
26
|
+
clearData(): ICanvasDiagram;
|
|
27
|
+
getDataGroup(group: string | number): TDataGroup | undefined;
|
|
28
|
+
getDataGroups(): TDataGroup[];
|
|
29
|
+
removeDataGroup(group: string | number): ICanvasDiagram;
|
|
30
|
+
removeValue(group: string | number, dataIndex: number): ICanvasDiagram;
|
|
31
|
+
/**
|
|
32
|
+
* Replaces the complete data of the diagram, at any time - also long after
|
|
33
|
+
* the page was loaded.
|
|
34
|
+
*/
|
|
35
|
+
setData(dataDefinition: string | any[] | object): ICanvasDiagram;
|
|
36
|
+
setDataGroups(dataGroups: TDataGroup[]): ICanvasDiagram;
|
|
37
|
+
setValue(group: string | number, dataIndex: number, value: any): ICanvasDiagram;
|
|
16
38
|
start(): ICanvasDiagram;
|
|
39
|
+
stop(): ICanvasDiagram;
|
|
40
|
+
/**
|
|
41
|
+
* Runs the given action against the engine. If the element is not mounted
|
|
42
|
+
* yet, the action is queued and executed as soon as the engine exists,
|
|
43
|
+
* so data can be set before as well as after the element was connected.
|
|
44
|
+
*/
|
|
45
|
+
private withEngine;
|
|
46
|
+
private flushPendingActions;
|
|
17
47
|
private createCanvas;
|
|
18
48
|
private evalArguments;
|
|
19
49
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -9,7 +9,6 @@ import BarsPluginClass from "./plugin/BarsPlugin";
|
|
|
9
9
|
import ChartEngineClass from './ChartEngine';
|
|
10
10
|
import DataGroupFactoryClass from "./Factory/DataGroupFactory";
|
|
11
11
|
import DiagramLine from "./plugin/DiagramLine";
|
|
12
|
-
import DiagramRegistry from "./Registry/DiagramRegistry";
|
|
13
12
|
import CameraMove from "./plugin/CameraMove";
|
|
14
13
|
import EnrichGroupInfosPlugin from "./plugin/EnrichGroupInfosPlugin";
|
|
15
14
|
import TimelinePlugin from "./plugin/TimelinePlugin";
|
|
@@ -18,7 +17,7 @@ import PaginationPlugin from "./plugin/PaginationPlugin";
|
|
|
18
17
|
export declare const CanvasDiagram: typeof CanvasDiagramClass;
|
|
19
18
|
export declare const ChartEngine: typeof ChartEngineClass;
|
|
20
19
|
export declare const DataGroupFactory: typeof DataGroupFactoryClass;
|
|
21
|
-
export declare const diagramRegistry: DiagramRegistry;
|
|
20
|
+
export declare const diagramRegistry: import("./Registry/DiagramRegistry").default;
|
|
22
21
|
export declare const plugins: {
|
|
23
22
|
BarsPlugin: typeof BarsPluginClass;
|
|
24
23
|
CameraMovePlugin: typeof CameraMove;
|
|
@@ -32,7 +31,7 @@ declare const _default: {
|
|
|
32
31
|
CanvasDiagram: typeof CanvasDiagramClass;
|
|
33
32
|
ChartEngine: typeof ChartEngineClass;
|
|
34
33
|
DataGroupFactory: typeof DataGroupFactoryClass;
|
|
35
|
-
diagramRegistry: DiagramRegistry;
|
|
34
|
+
diagramRegistry: import("./Registry/DiagramRegistry").default;
|
|
36
35
|
plugins: {
|
|
37
36
|
BarsPlugin: typeof BarsPluginClass;
|
|
38
37
|
CameraMovePlugin: typeof CameraMove;
|
package/dist/index.js
CHANGED
|
@@ -36,7 +36,7 @@ eval("{!function(t,e){ true?module.exports=e():0}(this,()=>(()=>{\"use strict\";
|
|
|
36
36
|
(module, __webpack_exports__, __webpack_require__) {
|
|
37
37
|
|
|
38
38
|
"use strict";
|
|
39
|
-
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/noSourceMaps.js */ \"./node_modules/css-loader/dist/runtime/noSourceMaps.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);\n// Imports\n\n\nvar ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `canvas-diagram {\n
|
|
39
|
+
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/noSourceMaps.js */ \"./node_modules/css-loader/dist/runtime/noSourceMaps.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);\n// Imports\n\n\nvar ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `canvas-diagram {\n box-sizing: border-box;\n display: inline-block;\n}`, \"\"]);\n// Exports\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);\n\n\n//# sourceURL=webpack://@cehlers88/chart/./src/style/CanvasDiagram.css?./node_modules/css-loader/dist/cjs.js\n}");
|
|
40
40
|
|
|
41
41
|
/***/ },
|
|
42
42
|
|
|
@@ -146,7 +146,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
|
|
|
146
146
|
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
147
147
|
|
|
148
148
|
"use strict";
|
|
149
|
-
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ ChartEngine)\n/* harmony export */ });\n/* harmony import */ var _plugin_EnrichGroupInfosPlugin__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./plugin/EnrichGroupInfosPlugin */ \"./src/plugin/EnrichGroupInfosPlugin.ts\");\n/* harmony import */ var _Factory_DataGroupFactory__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Factory/DataGroupFactory */ \"./src/Factory/DataGroupFactory.ts\");\n/* harmony import */ var _plugin_LegendsPlugin__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./plugin/LegendsPlugin */ \"./src/plugin/LegendsPlugin.ts\");\n/* harmony import */ var _Registry_EntityRegistry__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Registry/EntityRegistry */ \"./src/Registry/EntityRegistry.ts\");\n/* harmony import */ var _plugin_PaginationPlugin__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./plugin/PaginationPlugin */ \"./src/plugin/PaginationPlugin.ts\");\n/* harmony import */ var _Camera__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./Camera */ \"./src/Camera.ts\");\n/**\n * Library ChartEngine\n * Created 26.11.22\n *\n * @author Christoph Ehlers\n */\n\n\n\n\n\n\nconst _runStack = [];\nlet _isRunning = false;\nconst _exec = () => {\n if (_isRunning)\n return;\n _isRunning = true;\n window.requestAnimationFrame(() => {\n _runStack.map(f => f());\n _isRunning = false;\n if (_runStack.length > 0)\n _exec();\n });\n};\nclass ChartEngine {\n _camera = new _Camera__WEBPACK_IMPORTED_MODULE_5__[\"default\"]();\n _canvasElement;\n _entityRegistry = new _Registry_EntityRegistry__WEBPACK_IMPORTED_MODULE_3__[\"default\"]();\n _ctx;\n _dataGroups = [];\n _plugins = [];\n _pluginProperties = {};\n constructor(canvasElement, properties = {\n plugins: []\n }) {\n this._canvasElement = canvasElement;\n this._ctx = canvasElement.getContext('2d');\n this._canvasElement.height = this._canvasElement.offsetHeight;\n this._canvasElement.width = this._canvasElement.offsetWidth;\n [\n new _plugin_EnrichGroupInfosPlugin__WEBPACK_IMPORTED_MODULE_0__[\"default\"](),\n new _plugin_PaginationPlugin__WEBPACK_IMPORTED_MODULE_4__[\"default\"](),\n new _plugin_LegendsPlugin__WEBPACK_IMPORTED_MODULE_2__[\"default\"](),\n ...properties.plugins,\n ].map(plugin => {\n this.addPlugin(plugin);\n });\n this._canvasElement.addEventListener('pointermove', (e) => {\n this._plugins.map(p => p.handleHover(e.offsetX + this._camera.getX(), e.offsetY + this._camera.getY()));\n });\n this._canvasElement.addEventListener('wheel', (e) => {\n this._plugins.map(p => p.handleScroll(e.deltaX, e.deltaY));\n });\n this._canvasElement.addEventListener('pointerout', (e) => {\n this._plugins.map(p => p.handleLeave());\n });\n }\n addPlugin(plugin) {\n for (let key in this._pluginProperties) {\n plugin.setProperty(key, this._pluginProperties[key]);\n }\n plugin\n .setCamera(this._camera)\n .setEntityRegistry(this._entityRegistry);\n this._plugins.push(plugin);\n return this;\n }\n getDrawAreaRect() {\n return {\n x: 0,\n y: 0,\n w: this._canvasElement.width,\n h: this._canvasElement.height\n };\n }\n getPlugin(pluginName) {\n return this._plugins.find((plugin) => plugin.getName() === pluginName);\n }\n getPlugins() {\n return this._plugins.sort((p1, p2) => p1.getPriority() - p2.getPriority());\n }\n setPluginProperty(propertyName, value) {\n this._pluginProperties[propertyName] = value;\n this._plugins.map(p => p.setProperty(propertyName, value));\n return this;\n }\n create() {\n this._plugins.map(p => p.create(this._canvasElement, this._dataGroups));\n return this;\n }\n addDataGroup(dataGroup) {\n this._dataGroups.push(dataGroup);\n return this;\n }\n addValue(value, groupName = '') {\n const dataGroup = this._dataGroups.find((group) => group.label === groupName);\n if (dataGroup) {\n dataGroup.data.push(value);\n }\n else {\n this._dataGroups.push(_Factory_DataGroupFactory__WEBPACK_IMPORTED_MODULE_1__[\"default\"].createDataGroup([value], groupName));\n }\n return this;\n }\n draw() {\n this._ctx.clearRect(0, 0, this._canvasElement.width, this._canvasElement.height);\n this.getPlugins().map(p => p.draw());\n return this;\n }\n update() {\n this.getPlugins().map(p => {\n this._dataGroups = p.update(this._dataGroups).dataGroups;\n });\n return this;\n }\n start() {\n this.create();\n _runStack.push(() => {\n this.update();\n this.draw();\n });\n _exec();\n }\n getEngineCallbacks() {\n return {\n updateData: (indexGroup, indexData, newData) => {\n console.log('updateData context:', this);\n this._dataGroups[indexData].data[indexData] = newData;\n return this;\n }\n };\n }\n}\n\n\n//# sourceURL=webpack://@cehlers88/chart/./src/ChartEngine.ts?\n}");
|
|
149
|
+
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ ChartEngine)\n/* harmony export */ });\n/* harmony import */ var _plugin_EnrichGroupInfosPlugin__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./plugin/EnrichGroupInfosPlugin */ \"./src/plugin/EnrichGroupInfosPlugin.ts\");\n/* harmony import */ var _Factory_DataGroupFactory__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Factory/DataGroupFactory */ \"./src/Factory/DataGroupFactory.ts\");\n/* harmony import */ var _plugin_LegendsPlugin__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./plugin/LegendsPlugin */ \"./src/plugin/LegendsPlugin.ts\");\n/* harmony import */ var _Registry_EntityRegistry__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Registry/EntityRegistry */ \"./src/Registry/EntityRegistry.ts\");\n/* harmony import */ var _plugin_PaginationPlugin__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./plugin/PaginationPlugin */ \"./src/plugin/PaginationPlugin.ts\");\n/* harmony import */ var _Camera__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./Camera */ \"./src/Camera.ts\");\n/**\n * Library ChartEngine\n * Created 26.11.22\n *\n * @author Christoph Ehlers\n */\n\n\n\n\n\n\nconst _runStack = [];\nlet _isRunning = false;\nconst _exec = () => {\n if (_isRunning)\n return;\n _isRunning = true;\n window.requestAnimationFrame(() => {\n _runStack.map(f => f());\n _isRunning = false;\n if (_runStack.length > 0)\n _exec();\n });\n};\nclass ChartEngine {\n _camera = new _Camera__WEBPACK_IMPORTED_MODULE_5__[\"default\"]();\n _canvasElement;\n _entityRegistry = new _Registry_EntityRegistry__WEBPACK_IMPORTED_MODULE_3__[\"default\"]();\n _ctx;\n _dataGroups = [];\n _dataGroupsSignature = '';\n _processedDataGroups = [];\n _plugins = [];\n _pluginProperties = {};\n _created = false;\n _runStackEntry;\n constructor(canvasElement, properties = {\n plugins: []\n }) {\n this._canvasElement = canvasElement;\n this._ctx = canvasElement.getContext('2d');\n this._canvasElement.height = this._canvasElement.offsetHeight;\n this._canvasElement.width = this._canvasElement.offsetWidth;\n [\n new _plugin_EnrichGroupInfosPlugin__WEBPACK_IMPORTED_MODULE_0__[\"default\"](),\n new _plugin_PaginationPlugin__WEBPACK_IMPORTED_MODULE_4__[\"default\"](),\n new _plugin_LegendsPlugin__WEBPACK_IMPORTED_MODULE_2__[\"default\"](),\n ...(properties.plugins || []),\n ].map(plugin => {\n this.addPlugin(plugin);\n });\n this._canvasElement.addEventListener('pointermove', (e) => {\n this._plugins.map(p => p.handleHover(e.offsetX + this._camera.getX(), e.offsetY + this._camera.getY()));\n });\n this._canvasElement.addEventListener('wheel', (e) => {\n this._plugins.map(p => p.handleScroll(e.deltaX, e.deltaY));\n });\n this._canvasElement.addEventListener('pointerout', (e) => {\n this._plugins.map(p => p.handleLeave());\n });\n }\n addPlugin(plugin) {\n for (let key in this._pluginProperties) {\n plugin.setProperty(key, this._pluginProperties[key]);\n }\n plugin\n .setCamera(this._camera)\n .setEntityRegistry(this._entityRegistry);\n this._plugins.push(plugin);\n if (this._created) {\n // The chart is already running, so the plugin has to catch up.\n plugin.create(this._canvasElement, this.getPipelineDataGroups());\n }\n return this;\n }\n getDrawAreaRect() {\n return {\n x: 0,\n y: 0,\n w: this._canvasElement.width,\n h: this._canvasElement.height\n };\n }\n getPlugin(pluginName) {\n return this._plugins.find((plugin) => plugin.getName() === pluginName);\n }\n getPlugins() {\n return this._plugins.sort((p1, p2) => p1.getPriority() - p2.getPriority());\n }\n setPluginProperty(propertyName, value) {\n this._pluginProperties[propertyName] = value;\n this._plugins.map(p => p.setProperty(propertyName, value));\n return this;\n }\n create() {\n this._plugins.map(p => p.create(this._canvasElement, this.getPipelineDataGroups()));\n this._created = true;\n return this;\n }\n addDataGroup(dataGroup) {\n this._dataGroups.push(dataGroup);\n return this;\n }\n /**\n * Returns the data groups currently held by the engine.\n * The returned groups are the live objects; changes made to them are\n * picked up with the next update cycle.\n */\n getDataGroups() {\n return this._dataGroups;\n }\n /**\n * Returns a single data group, addressed either by its label or by its index.\n */\n getDataGroup(group) {\n if (typeof group === 'number') {\n return this._dataGroups[group];\n }\n return this._dataGroups.find((dataGroup) => dataGroup.label === group);\n }\n /**\n * Replaces all data groups at once.\n */\n setDataGroups(dataGroups) {\n this._dataGroups = dataGroups || [];\n return this;\n }\n /**\n * Replaces the complete data of the chart. Accepts everything\n * `DataGroupFactory.parseDataGroupsDefinition` understands: a JSON string,\n * a plain array of values or an object keyed by group name.\n */\n setData(dataDefinition) {\n return this.setDataGroups(_Factory_DataGroupFactory__WEBPACK_IMPORTED_MODULE_1__[\"default\"].parseDataGroupsDefinition(dataDefinition));\n }\n /**\n * Removes a data group, addressed either by its label or by its index.\n */\n removeDataGroup(group) {\n const index = typeof group === 'number' ? group : this._dataGroups.findIndex((dataGroup) => dataGroup.label === group);\n if (index > -1 && index < this._dataGroups.length) {\n this._dataGroups.splice(index, 1);\n }\n return this;\n }\n /**\n * Removes all data groups.\n */\n clearData() {\n this._dataGroups = [];\n return this;\n }\n addValue(value, groupName = '') {\n const dataGroup = this._dataGroups.find((group) => group.label === groupName);\n if (dataGroup) {\n dataGroup.data.push(_Factory_DataGroupFactory__WEBPACK_IMPORTED_MODULE_1__[\"default\"].createDataValue(value));\n }\n else {\n this._dataGroups.push(_Factory_DataGroupFactory__WEBPACK_IMPORTED_MODULE_1__[\"default\"].createDataGroup([value], groupName));\n }\n return this;\n }\n /**\n * Replaces a single value within a data group.\n */\n setValue(group, dataIndex, value) {\n const dataGroup = this.getDataGroup(group);\n if (!dataGroup) {\n throw new Error('ChartEngine.setValue: data group \"' + group + '\" not found.');\n }\n if (!Number.isSafeInteger(dataIndex) || dataIndex < 0) {\n throw new Error('ChartEngine.setValue: data index must be a non-negative integer.');\n }\n while (dataGroup.data.length <= dataIndex) {\n dataGroup.data.push(_Factory_DataGroupFactory__WEBPACK_IMPORTED_MODULE_1__[\"default\"].createDataValue(null));\n }\n dataGroup.data[dataIndex] = _Factory_DataGroupFactory__WEBPACK_IMPORTED_MODULE_1__[\"default\"].createDataValue(value);\n return this;\n }\n /**\n * Removes a single value from a data group.\n */\n removeValue(group, dataIndex) {\n const dataGroup = this.getDataGroup(group);\n if (dataGroup && dataIndex > -1 && dataIndex < dataGroup.data.length) {\n dataGroup.data.splice(dataIndex, 1);\n }\n return this;\n }\n draw() {\n this._ctx.clearRect(0, 0, this._canvasElement.width, this._canvasElement.height);\n this.getPlugins().map(p => p.draw());\n return this;\n }\n update() {\n let dataGroups = this.getPipelineDataGroups();\n this.getPlugins().map(p => {\n dataGroups = p.update(dataGroups).dataGroups;\n });\n return this;\n }\n /**\n * Returns the data groups handed to the plugins. They are a detached copy\n * of the data owned by the engine and are renewed whenever that data\n * changed. Without that separation the plugins would hold references to\n * the very objects manipulated from outside, so neither they nor the\n * engine could tell a manipulation from the state of the last frame.\n */\n getPipelineDataGroups() {\n const signature = JSON.stringify(this._dataGroups);\n if (signature !== this._dataGroupsSignature) {\n this._dataGroupsSignature = signature;\n this._processedDataGroups = JSON.parse(signature);\n }\n return this._processedDataGroups;\n }\n start() {\n if (this._runStackEntry) {\n // already running\n return;\n }\n if (!this._created) {\n this.create();\n }\n this._runStackEntry = () => {\n this.update();\n this.draw();\n };\n _runStack.push(this._runStackEntry);\n _exec();\n }\n /**\n * Stops the render loop of this engine. The data stays untouched, so the\n * chart can be started again later on.\n */\n stop() {\n if (this._runStackEntry) {\n const index = _runStack.indexOf(this._runStackEntry);\n if (index > -1) {\n _runStack.splice(index, 1);\n }\n this._runStackEntry = undefined;\n }\n return this;\n }\n isRunning() {\n return this._runStackEntry !== undefined;\n }\n getEngineCallbacks() {\n return {\n updateData: (indexGroup, indexData, newData) => {\n this._dataGroups[indexGroup].data[indexData] = newData;\n return this;\n }\n };\n }\n}\n\n\n//# sourceURL=webpack://@cehlers88/chart/./src/ChartEngine.ts?\n}");
|
|
150
150
|
|
|
151
151
|
/***/ },
|
|
152
152
|
|
|
@@ -168,7 +168,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
|
|
|
168
168
|
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
169
169
|
|
|
170
170
|
"use strict";
|
|
171
|
-
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ DataGroupFactory)\n/* harmony export */ });\nclass DataGroupFactory {\n static buildCounter = 0;\n static _colors = [\n '#e84949',\n '#30cb30',\n '#f0a30a',\n '#1d91e3',\n '#ec459e',\n '#9f4ef4',\n '#f4f44e',\n '#4ef4f4',\n '#4ef49f',\n '#f49f4e',\n '#4e9bf4',\n ];\n static _lastColorIndex = -1;\n
|
|
171
|
+
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ DataGroupFactory)\n/* harmony export */ });\nclass DataGroupFactory {\n static buildCounter = 0;\n static _colors = [\n '#e84949',\n '#30cb30',\n '#f0a30a',\n '#1d91e3',\n '#ec459e',\n '#9f4ef4',\n '#f4f44e',\n '#4ef4f4',\n '#4ef49f',\n '#f49f4e',\n '#4e9bf4',\n ];\n static _lastColorIndex = -1;\n /**\n * Normalizes a single value definition into a TData object.\n * Accepts plain numbers, ranges ([start, end]), null (empty value) and\n * objects like {value, valueStart, label}.\n */\n static createDataValue(valueDef) {\n let value = valueDef;\n let label = undefined;\n let valueStart = valueDef;\n let valueEnd = valueDef;\n if (valueDef !== null && valueDef !== undefined) {\n if (typeof valueDef === 'object' && !Array.isArray(valueDef)) {\n if (Array.isArray(valueDef.value)) {\n if (valueDef.value.length === 2) {\n valueStart = valueDef.value[0];\n value = valueDef.value[1];\n valueEnd = valueDef.value[1];\n }\n else {\n console.warn('valueDef.value must be an array with 2 elements', valueDef);\n }\n }\n else {\n value = valueDef.value;\n valueEnd = valueDef.value;\n valueStart = valueDef.valueStart === undefined ? 0 : valueDef.valueStart;\n }\n label = valueDef.label;\n }\n else {\n if (Array.isArray(valueDef) && valueDef.length === 2) {\n valueStart = valueDef[0];\n value = valueDef[1];\n valueEnd = valueDef[1];\n label = valueDef[0] + ' - ' + valueDef[1];\n }\n }\n }\n return {\n empty: (value === null || value === undefined),\n hasLabel: (valueDef !== null && valueDef !== undefined && valueDef.label !== undefined),\n label,\n value,\n valueEnd,\n valueStart\n };\n }\n static createDataGroup(values, groupLabel = '', color = '') {\n DataGroupFactory.buildCounter++;\n if (color === '') {\n color = DataGroupFactory.getNextColor();\n }\n return {\n color,\n label: groupLabel === '' ? 'Group#' + DataGroupFactory.buildCounter : groupLabel,\n description: \"\",\n data: (values || []).map((valueDef) => DataGroupFactory.createDataValue(valueDef)),\n infos: {}\n };\n }\n /**\n * Parses a data group definition. Beside the JSON notation used by the\n * `value` attribute of `<canvas-diagram>` an already parsed object/array\n * may be passed, so data can be handed over programmatically at runtime.\n */\n static parseDataGroupsDefinition(value) {\n const valueObj = typeof value === 'string' ? JSON.parse(value) : value;\n const result = [];\n if (valueObj === null || valueObj === undefined) {\n return result;\n }\n if (Array.isArray(valueObj)) {\n if (valueObj.length > 0) {\n result.push(DataGroupFactory.createDataGroup(valueObj));\n }\n }\n else {\n if (typeof valueObj === 'object') {\n Object.keys(valueObj).map((key) => {\n if (Array.isArray(valueObj[key])) {\n result.push(DataGroupFactory.createDataGroup(valueObj[key], key));\n }\n else {\n result.push(DataGroupFactory.createDataGroup(valueObj[key].data, key, valueObj[key].color));\n }\n });\n }\n }\n return result;\n }\n static getNextColor() {\n DataGroupFactory._lastColorIndex++;\n if (DataGroupFactory._lastColorIndex >= DataGroupFactory._colors.length) {\n DataGroupFactory._lastColorIndex = 0;\n }\n return DataGroupFactory._colors[DataGroupFactory._lastColorIndex];\n }\n static setColor(color, index) {\n DataGroupFactory._colors[index] = color;\n }\n static setColors(colors) {\n DataGroupFactory._colors = colors;\n }\n}\n\n\n//# sourceURL=webpack://@cehlers88/chart/./src/Factory/DataGroupFactory.ts?\n}");
|
|
172
172
|
|
|
173
173
|
/***/ },
|
|
174
174
|
|
|
@@ -179,7 +179,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
|
|
|
179
179
|
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
180
180
|
|
|
181
181
|
"use strict";
|
|
182
|
-
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__),\n/* harmony export */ diagramRegistry: () => (/* binding */ diagramRegistry)\n/* harmony export */ });\nconst _diagrams = {};\nclass DiagramRegistry {\n static _identPrefix = 'dia_';\n createUniqueIdentifier() {\n return 'unq' + Date.now().toString();\n }\n getDiagram(identifier) {\n const diagram = _diagrams[DiagramRegistry._identPrefix + identifier];\n if (diagram === undefined) {\n throw new Error('DiagramRegistry.getDiagram: diagram with identifier ' + identifier + ' not found.');\n }\n return diagram;\n }\n register(diagram, identifier = '') {\n if (identifier === '') {\n identifier = diagram.hasAttribute('id') ? diagram.getAttribute('id') : '';\n }\n if (identifier === '') {\n identifier = this.createUniqueIdentifier();\n }\n _diagrams[DiagramRegistry._identPrefix + identifier] = diagram;\n return this;\n }\n}\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (DiagramRegistry);\nconst diagramRegistry = new DiagramRegistry();\n\n\n//# sourceURL=webpack://@cehlers88/chart/./src/Registry/DiagramRegistry.ts?\n}");
|
|
182
|
+
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__),\n/* harmony export */ diagramRegistry: () => (/* binding */ diagramRegistry)\n/* harmony export */ });\nconst _diagrams = {};\nclass DiagramRegistry {\n static _identPrefix = 'dia_';\n static _identCounter = 0;\n createUniqueIdentifier() {\n DiagramRegistry._identCounter++;\n return 'unq' + Date.now().toString() + '_' + DiagramRegistry._identCounter;\n }\n getDiagram(identifier) {\n const diagram = _diagrams[DiagramRegistry._identPrefix + identifier];\n if (diagram === undefined) {\n throw new Error('DiagramRegistry.getDiagram: diagram with identifier ' + identifier + ' not found.');\n }\n return diagram;\n }\n hasDiagram(identifier) {\n return _diagrams[DiagramRegistry._identPrefix + identifier] !== undefined;\n }\n getDiagrams() {\n return Object.keys(_diagrams).map(ident => _diagrams[ident]);\n }\n register(diagram, identifier = '') {\n if (identifier === '') {\n identifier = diagram.hasAttribute('id') ? diagram.getAttribute('id') : '';\n }\n if (identifier === '') {\n identifier = this.createUniqueIdentifier();\n }\n _diagrams[DiagramRegistry._identPrefix + identifier] = diagram;\n return this;\n }\n /**\n * Removes a diagram from the registry, either by its identifier or by the\n * element itself, so removed diagrams are not kept alive by the registry.\n */\n unregister(diagram) {\n if (typeof diagram === 'string') {\n delete _diagrams[DiagramRegistry._identPrefix + diagram];\n return this;\n }\n Object.keys(_diagrams).map(ident => {\n if (_diagrams[ident] === diagram) {\n delete _diagrams[ident];\n }\n });\n return this;\n }\n}\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (DiagramRegistry);\nconst diagramRegistry = new DiagramRegistry();\n\n\n//# sourceURL=webpack://@cehlers88/chart/./src/Registry/DiagramRegistry.ts?\n}");
|
|
183
183
|
|
|
184
184
|
/***/ },
|
|
185
185
|
|
|
@@ -201,7 +201,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
|
|
|
201
201
|
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
202
202
|
|
|
203
203
|
"use strict";
|
|
204
|
-
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _style_CanvasDiagram_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../style/CanvasDiagram.css */ \"./src/style/CanvasDiagram.css\");\n/* harmony import */ var _Registry_DiagramRegistry__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Registry/DiagramRegistry */ \"./src/Registry/DiagramRegistry.ts\");\n/* harmony import */ var _cehlers88_ceutils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @cehlers88/ceutils */ \"./node_modules/@cehlers88/ceutils/dist/index.js\");\n/* harmony import */ var _cehlers88_ceutils__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_cehlers88_ceutils__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _Factory_DataGroupFactory__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../Factory/DataGroupFactory */ \"./src/Factory/DataGroupFactory.ts\");\n/* harmony import */ var _ChartEngine__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../ChartEngine */ \"./src/ChartEngine.ts\");\n/**\n * Element CanvasDiagram\n * Created 03.10.24\n *\n * @author Christoph Ehlers\n */\n\n\n\n\n\nclass CanvasDiagram extends HTMLElement {\n _cleanDom = true;\n _engine;\n connectedCallback() {\n _Registry_DiagramRegistry__WEBPACK_IMPORTED_MODULE_1__.diagramRegistry.register(this);\n const canvas = this.createCanvas();\n this.appendChild(canvas);\n this._engine = new _ChartEngine__WEBPACK_IMPORTED_MODULE_4__[\"default\"](canvas);\n this.evalArguments();\n }\n
|
|
204
|
+
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _style_CanvasDiagram_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../style/CanvasDiagram.css */ \"./src/style/CanvasDiagram.css\");\n/* harmony import */ var _Registry_DiagramRegistry__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Registry/DiagramRegistry */ \"./src/Registry/DiagramRegistry.ts\");\n/* harmony import */ var _cehlers88_ceutils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @cehlers88/ceutils */ \"./node_modules/@cehlers88/ceutils/dist/index.js\");\n/* harmony import */ var _cehlers88_ceutils__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_cehlers88_ceutils__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _Factory_DataGroupFactory__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../Factory/DataGroupFactory */ \"./src/Factory/DataGroupFactory.ts\");\n/* harmony import */ var _ChartEngine__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../ChartEngine */ \"./src/ChartEngine.ts\");\n/**\n * Element CanvasDiagram\n * Created 03.10.24\n *\n * @author Christoph Ehlers\n */\n\n\n\n\n\nclass CanvasDiagram extends HTMLElement {\n _cleanDom = true;\n _engine;\n _ignoreValueAttribute = false;\n _pendingActions = [];\n static get observedAttributes() {\n return ['value'];\n }\n connectedCallback() {\n if (this._engine) {\n // The element was moved within the dom, no need to build it again.\n return;\n }\n _Registry_DiagramRegistry__WEBPACK_IMPORTED_MODULE_1__.diagramRegistry.register(this);\n const canvas = this.createCanvas();\n this.appendChild(canvas);\n this._engine = new _ChartEngine__WEBPACK_IMPORTED_MODULE_4__[\"default\"](canvas);\n this.evalArguments();\n this.flushPendingActions();\n }\n disconnectedCallback() {\n if (this._engine) {\n this._engine.stop();\n }\n _Registry_DiagramRegistry__WEBPACK_IMPORTED_MODULE_1__.diagramRegistry.unregister(this);\n }\n attributeChangedCallback(name, oldValue, newValue) {\n if (name !== 'value' || this._ignoreValueAttribute || newValue === null) {\n return;\n }\n if (!this._engine) {\n // Attribute is evaluated within connectedCallback anyway.\n return;\n }\n this.setData(newValue);\n }\n addPlugin(plugin) {\n return this.withEngine(engine => engine.addPlugin(plugin));\n }\n getPlugin(pluginName) {\n return this._engine ? this._engine.getPlugin(pluginName) : undefined;\n }\n getEngine() {\n return this._engine;\n }\n addDataGroup(dataGroup) {\n return this.withEngine(engine => engine.addDataGroup(dataGroup));\n }\n addValue(value, groupName = '') {\n return this.withEngine(engine => engine.addValue(value, groupName));\n }\n clearData() {\n return this.withEngine(engine => engine.clearData());\n }\n getDataGroup(group) {\n return this._engine ? this._engine.getDataGroup(group) : undefined;\n }\n getDataGroups() {\n return this._engine ? this._engine.getDataGroups() : [];\n }\n removeDataGroup(group) {\n return this.withEngine(engine => engine.removeDataGroup(group));\n }\n removeValue(group, dataIndex) {\n return this.withEngine(engine => engine.removeValue(group, dataIndex));\n }\n /**\n * Replaces the complete data of the diagram, at any time - also long after\n * the page was loaded.\n */\n setData(dataDefinition) {\n return this.withEngine(engine => engine.setData(dataDefinition));\n }\n setDataGroups(dataGroups) {\n return this.withEngine(engine => engine.setDataGroups(dataGroups));\n }\n setValue(group, dataIndex, value) {\n return this.withEngine(engine => engine.setValue(group, dataIndex, value));\n }\n start() {\n return this.withEngine(engine => engine.start());\n }\n stop() {\n return this.withEngine(engine => engine.stop());\n }\n /**\n * Runs the given action against the engine. If the element is not mounted\n * yet, the action is queued and executed as soon as the engine exists,\n * so data can be set before as well as after the element was connected.\n */\n withEngine(action) {\n if (this._engine) {\n action(this._engine);\n }\n else {\n this._pendingActions.push(action);\n }\n return this;\n }\n flushPendingActions() {\n const actions = this._pendingActions;\n this._pendingActions = [];\n actions.map(action => action(this._engine));\n }\n createCanvas() {\n const canvas = _cehlers88_ceutils__WEBPACK_IMPORTED_MODULE_2__.domLib.createElement('canvas');\n this.setAttribute('style', 'width:0px; height:0px;');\n [\n { name: 'height', defaultValue: 150 },\n { name: 'width', defaultValue: 300 },\n ].map((attrDef) => {\n let value = (this.hasAttribute(attrDef.name) ? this.getAttribute(attrDef.name) : attrDef.defaultValue.toString());\n value = value.replace('px', '');\n console.log('set', attrDef, value);\n canvas.setAttribute(attrDef.name, value);\n console.log(canvas);\n this.style[attrDef.name] = value + 'px';\n });\n return canvas;\n }\n evalArguments() {\n [\n {\n name: 'value', defaultValue: '[]', callback: (value) => {\n _Factory_DataGroupFactory__WEBPACK_IMPORTED_MODULE_3__[\"default\"].parseDataGroupsDefinition(value).map(dataGroupDef => {\n this._engine.addDataGroup(dataGroupDef);\n });\n }\n },\n {\n name: 'autostart', defaultValue: 'true', callback: (value) => {\n if (value === 'true') {\n this.start();\n }\n }\n }\n ].map(attrDef => {\n const callbackArgument = this.hasAttribute(attrDef.name) ? this.getAttribute(attrDef.name) : attrDef.defaultValue;\n attrDef.callback(callbackArgument);\n if (this._cleanDom) {\n // Removing the attribute must not be mistaken for a data change.\n this._ignoreValueAttribute = true;\n this.removeAttribute(attrDef.name);\n this._ignoreValueAttribute = false;\n }\n });\n }\n}\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CanvasDiagram);\ncustomElements.define('canvas-diagram', CanvasDiagram);\n\n\n//# sourceURL=webpack://@cehlers88/chart/./src/customElement/CanvasDiagram.ts?\n}");
|
|
205
205
|
|
|
206
206
|
/***/ },
|
|
207
207
|
|
|
@@ -212,7 +212,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
|
|
|
212
212
|
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
213
213
|
|
|
214
214
|
"use strict";
|
|
215
|
-
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ CanvasDiagram: () => (/* binding */ CanvasDiagram),\n/* harmony export */ ChartEngine: () => (/* binding */ ChartEngine),\n/* harmony export */ DataGroupFactory: () => (/* binding */ DataGroupFactory),\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__),\n/* harmony export */ diagramRegistry: () => (/* binding */ diagramRegistry),\n/* harmony export */ plugins: () => (/* binding */ plugins)\n/* harmony export */ });\n/* harmony import */ var _customElement_CanvasDiagram__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./customElement/CanvasDiagram */ \"./src/customElement/CanvasDiagram.ts\");\n/* harmony import */ var _plugin_BarsPlugin__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./plugin/BarsPlugin */ \"./src/plugin/BarsPlugin.ts\");\n/* harmony import */ var _ChartEngine__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ChartEngine */ \"./src/ChartEngine.ts\");\n/* harmony import */ var _Factory_DataGroupFactory__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Factory/DataGroupFactory */ \"./src/Factory/DataGroupFactory.ts\");\n/* harmony import */ var _plugin_DiagramLine__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./plugin/DiagramLine */ \"./src/plugin/DiagramLine.ts\");\n/* harmony import */ var _Registry_DiagramRegistry__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./Registry/DiagramRegistry */ \"./src/Registry/DiagramRegistry.ts\");\n/* harmony import */ var _plugin_CameraMove__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./plugin/CameraMove */ \"./src/plugin/CameraMove.ts\");\n/* harmony import */ var _plugin_EnrichGroupInfosPlugin__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./plugin/EnrichGroupInfosPlugin */ \"./src/plugin/EnrichGroupInfosPlugin.ts\");\n/* harmony import */ var _plugin_TimelinePlugin__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./plugin/TimelinePlugin */ \"./src/plugin/TimelinePlugin.ts\");\n/* harmony import */ var _plugin_LegendsPlugin__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./plugin/LegendsPlugin */ \"./src/plugin/LegendsPlugin.ts\");\n/* harmony import */ var _plugin_PaginationPlugin__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./plugin/PaginationPlugin */ \"./src/plugin/PaginationPlugin.ts\");\n/**\n * index.ts\n * Created 05.05.24\n *\n * @author Christoph Ehlers\n */\n\n\n\n\n\n\n\n\n\n\n\nconst CanvasDiagram = _customElement_CanvasDiagram__WEBPACK_IMPORTED_MODULE_0__[\"default\"];\nconst ChartEngine = _ChartEngine__WEBPACK_IMPORTED_MODULE_2__[\"default\"];\nconst DataGroupFactory = _Factory_DataGroupFactory__WEBPACK_IMPORTED_MODULE_3__[\"default\"];\nconst diagramRegistry =
|
|
215
|
+
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ CanvasDiagram: () => (/* binding */ CanvasDiagram),\n/* harmony export */ ChartEngine: () => (/* binding */ ChartEngine),\n/* harmony export */ DataGroupFactory: () => (/* binding */ DataGroupFactory),\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__),\n/* harmony export */ diagramRegistry: () => (/* binding */ diagramRegistry),\n/* harmony export */ plugins: () => (/* binding */ plugins)\n/* harmony export */ });\n/* harmony import */ var _customElement_CanvasDiagram__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./customElement/CanvasDiagram */ \"./src/customElement/CanvasDiagram.ts\");\n/* harmony import */ var _plugin_BarsPlugin__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./plugin/BarsPlugin */ \"./src/plugin/BarsPlugin.ts\");\n/* harmony import */ var _ChartEngine__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ChartEngine */ \"./src/ChartEngine.ts\");\n/* harmony import */ var _Factory_DataGroupFactory__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Factory/DataGroupFactory */ \"./src/Factory/DataGroupFactory.ts\");\n/* harmony import */ var _plugin_DiagramLine__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./plugin/DiagramLine */ \"./src/plugin/DiagramLine.ts\");\n/* harmony import */ var _Registry_DiagramRegistry__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./Registry/DiagramRegistry */ \"./src/Registry/DiagramRegistry.ts\");\n/* harmony import */ var _plugin_CameraMove__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./plugin/CameraMove */ \"./src/plugin/CameraMove.ts\");\n/* harmony import */ var _plugin_EnrichGroupInfosPlugin__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./plugin/EnrichGroupInfosPlugin */ \"./src/plugin/EnrichGroupInfosPlugin.ts\");\n/* harmony import */ var _plugin_TimelinePlugin__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./plugin/TimelinePlugin */ \"./src/plugin/TimelinePlugin.ts\");\n/* harmony import */ var _plugin_LegendsPlugin__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./plugin/LegendsPlugin */ \"./src/plugin/LegendsPlugin.ts\");\n/* harmony import */ var _plugin_PaginationPlugin__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./plugin/PaginationPlugin */ \"./src/plugin/PaginationPlugin.ts\");\n/**\n * index.ts\n * Created 05.05.24\n *\n * @author Christoph Ehlers\n */\n\n\n\n\n\n\n\n\n\n\n\nconst CanvasDiagram = _customElement_CanvasDiagram__WEBPACK_IMPORTED_MODULE_0__[\"default\"];\nconst ChartEngine = _ChartEngine__WEBPACK_IMPORTED_MODULE_2__[\"default\"];\nconst DataGroupFactory = _Factory_DataGroupFactory__WEBPACK_IMPORTED_MODULE_3__[\"default\"];\nconst diagramRegistry = _Registry_DiagramRegistry__WEBPACK_IMPORTED_MODULE_5__.diagramRegistry;\nconst plugins = {\n BarsPlugin: _plugin_BarsPlugin__WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n CameraMovePlugin: _plugin_CameraMove__WEBPACK_IMPORTED_MODULE_6__[\"default\"],\n EnrichGroupInfosPlugin: _plugin_EnrichGroupInfosPlugin__WEBPACK_IMPORTED_MODULE_7__[\"default\"],\n DiagramLinePlugin: _plugin_DiagramLine__WEBPACK_IMPORTED_MODULE_4__[\"default\"],\n LegendsPlugin: _plugin_LegendsPlugin__WEBPACK_IMPORTED_MODULE_9__[\"default\"],\n PaginationPlugin: _plugin_PaginationPlugin__WEBPACK_IMPORTED_MODULE_10__[\"default\"],\n TimelinePlugin: _plugin_TimelinePlugin__WEBPACK_IMPORTED_MODULE_8__[\"default\"]\n};\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n CanvasDiagram: _customElement_CanvasDiagram__WEBPACK_IMPORTED_MODULE_0__[\"default\"],\n ChartEngine: _ChartEngine__WEBPACK_IMPORTED_MODULE_2__[\"default\"],\n DataGroupFactory: _Factory_DataGroupFactory__WEBPACK_IMPORTED_MODULE_3__[\"default\"],\n diagramRegistry,\n plugins\n});\n\n\n//# sourceURL=webpack://@cehlers88/chart/./src/index.ts?\n}");
|
|
216
216
|
|
|
217
217
|
/***/ },
|
|
218
218
|
|
|
@@ -223,7 +223,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
|
|
|
223
223
|
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
224
224
|
|
|
225
225
|
"use strict";
|
|
226
|
-
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ AbstractDiagramPlugin)\n/* harmony export */ });\n/* harmony import */ var _AbstractPlugin__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AbstractPlugin */ \"./src/plugin/AbstractPlugin.ts\");\n/* harmony import */ var _cehlers88_ceutils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @cehlers88/ceutils */ \"./node_modules/@cehlers88/ceutils/dist/index.js\");\n/* harmony import */ var _cehlers88_ceutils__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_cehlers88_ceutils__WEBPACK_IMPORTED_MODULE_1__);\n\n\nclass AbstractDiagramPlugin extends _AbstractPlugin__WEBPACK_IMPORTED_MODULE_0__[\"default\"] {\n constructor(props = {}) {\n super({\n viewSize: -1,\n ...props\n });\n this._priority = 50;\n }\n
|
|
226
|
+
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ AbstractDiagramPlugin)\n/* harmony export */ });\n/* harmony import */ var _AbstractPlugin__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AbstractPlugin */ \"./src/plugin/AbstractPlugin.ts\");\n/* harmony import */ var _cehlers88_ceutils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @cehlers88/ceutils */ \"./node_modules/@cehlers88/ceutils/dist/index.js\");\n/* harmony import */ var _cehlers88_ceutils__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_cehlers88_ceutils__WEBPACK_IMPORTED_MODULE_1__);\n\n\nclass AbstractDiagramPlugin extends _AbstractPlugin__WEBPACK_IMPORTED_MODULE_0__[\"default\"] {\n constructor(props = {}) {\n super({\n viewSize: -1,\n ...props\n });\n this._priority = 50;\n }\n onDataGroupsChanged(dataGroups) {\n this.updateBufferSize(dataGroups);\n }\n updateBufferSize(dataGroups) {\n const viewSize = this.getProperty('viewSize', -1);\n const maxDataLength = dataGroups.length === 0 ? 0 : Math.max(...dataGroups.map((dataGroup) => dataGroup.data.length));\n const dataPerView = viewSize === -1 ? maxDataLength : viewSize;\n if (maxDataLength < 1 || dataPerView < 1) {\n // Without data there is nothing to scale the buffer by.\n this.setBuffer(_cehlers88_ceutils__WEBPACK_IMPORTED_MODULE_1__.domLib.createElement('canvas', {\n height: this.getDrawAreaRect().h.toString(),\n width: this.getDrawAreaRect().w.toString()\n }));\n this._camera.setMaxX(0);\n return this.getDrawAreaRect().w;\n }\n const singleGroupWidth = this.getDrawAreaRect().w / dataPerView;\n const bufferWidth = maxDataLength * singleGroupWidth;\n this.setBuffer(_cehlers88_ceutils__WEBPACK_IMPORTED_MODULE_1__.domLib.createElement('canvas', {\n height: this.getDrawAreaRect().h.toString(),\n width: bufferWidth.toString()\n }));\n this._camera.setMaxX(bufferWidth - this.getDrawAreaRect().w);\n return singleGroupWidth;\n }\n}\n\n\n//# sourceURL=webpack://@cehlers88/chart/./src/plugin/AbstractDiagramPlugin.ts?\n}");
|
|
227
227
|
|
|
228
228
|
/***/ },
|
|
229
229
|
|
|
@@ -234,7 +234,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
|
|
|
234
234
|
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
235
235
|
|
|
236
236
|
"use strict";
|
|
237
|
-
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ AbstractPlugin)\n/* harmony export */ });\nclass AbstractPlugin {\n _camera;\n _dataGroups = [];\n _entityRegistry;\n _fixed = false;\n _priority = 50;\n bufferCtx;\n ctx;\n redrawBuffer = true;\n _buffer;\n _stateChangedListener;\n _drawAreaRect;\n _properties = {};\n constructor(props = {}) {\n if (props.enabled === undefined) {\n props.enabled = true;\n }\n Object.keys(props).map(key => {\n this.setProperty(key, props[key]);\n });\n }\n get needsRedraw() {\n return this.redrawBuffer;\n }\n setStateChangedListener(listener) {\n this._stateChangedListener = listener;\n return this;\n }\n setState(newState) {\n return this;\n }\n update(dataGroups) {\n if (this.getProperty('enabled', true) === false)\n return { dataGroups };\n this._dataGroups = this.updateDataGroups(dataGroups).dataGroups;\n return { dataGroups: this._dataGroups };\n }\n updateDataGroups(dataGroups) {\n return { dataGroups };\n }\n addEntity(entity) {\n this._entityRegistry.addEntity(this.getName(), entity);\n return this;\n }\n create(canvasElement, dataGroups) {\n this.createBuffer(canvasElement);\n this.setDrawAreaRect({\n x: this.getProperty('x', 0),\n y: this.getProperty('y', 0),\n w: canvasElement.width,\n h: canvasElement.height\n });\n this.ctx = canvasElement.getContext('2d');\n
|
|
237
|
+
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ AbstractPlugin)\n/* harmony export */ });\nclass AbstractPlugin {\n _camera;\n _dataGroups = [];\n _entityRegistry;\n _fixed = false;\n _priority = 50;\n bufferCtx;\n ctx;\n redrawBuffer = true;\n _dataGroupsChanged = true;\n _buffer;\n _dataGroupsSignature = '';\n _stateChangedListener;\n _drawAreaRect;\n _properties = {};\n constructor(props = {}) {\n if (props.enabled === undefined) {\n props.enabled = true;\n }\n Object.keys(props).map(key => {\n this.setProperty(key, props[key]);\n });\n }\n get needsRedraw() {\n return this.redrawBuffer;\n }\n setStateChangedListener(listener) {\n this._stateChangedListener = listener;\n return this;\n }\n setState(newState) {\n return this;\n }\n update(dataGroups) {\n if (this.getProperty('enabled', true) === false)\n return { dataGroups };\n this.detectDataGroupsChange(dataGroups);\n if (this._dataGroupsChanged) {\n // Data was manipulated in the meantime, so the buffer is outdated.\n this.redrawBuffer = true;\n this.onDataGroupsChanged(dataGroups);\n }\n this._dataGroups = this.updateDataGroups(dataGroups).dataGroups;\n return { dataGroups: this._dataGroups };\n }\n updateDataGroups(dataGroups) {\n return { dataGroups };\n }\n addEntity(entity) {\n this._entityRegistry.addEntity(this.getName(), entity);\n return this;\n }\n create(canvasElement, dataGroups) {\n this.createBuffer(canvasElement);\n this.setDrawAreaRect({\n x: this.getProperty('x', 0),\n y: this.getProperty('y', 0),\n w: canvasElement.width,\n h: canvasElement.height\n });\n this.ctx = canvasElement.getContext('2d');\n return {\n dataGroups,\n plugin: this\n };\n }\n drawBuffer() {\n this.redrawBuffer = false;\n }\n draw(forceRedraw = false) {\n const padding = this.getProperty('padding', 0);\n if (this.needsRedraw || forceRedraw) {\n this.bufferCtx.clearRect(0, 0, this._buffer.width, this._buffer.height);\n this.drawBuffer();\n //console.log('redraw buffer', this.bufferCtx.canvas.width, this.bufferCtx.canvas.height);\n }\n try {\n this.ctx.drawImage(this._buffer, this._fixed ? 0 : this._camera.x, this._fixed ? 0 : this._camera.y, this._drawAreaRect.w, this._drawAreaRect.h, this._drawAreaRect.x + padding, this._drawAreaRect.y + padding, this._drawAreaRect.w - (2 * padding), this._drawAreaRect.h - (2 * padding));\n }\n catch (e) {\n console.warn(e);\n }\n return this;\n }\n getDrawAreaRect() {\n return this._drawAreaRect;\n }\n getPriority() {\n return this._priority;\n }\n getProperty(propertyName, defaultResult) {\n return this._properties[propertyName] ?? defaultResult;\n }\n handleClick(x, y) {\n return this;\n }\n handleHover(x, y) {\n return this;\n }\n handleLeave() {\n this.handleHover(-1, -1);\n return this;\n }\n handleScroll(x, y) {\n return this;\n }\n setBuffer(buffer) {\n this._buffer = buffer;\n this.bufferCtx = buffer.getContext('2d');\n return this;\n }\n setCamera(camera) {\n this._camera = camera;\n return this;\n }\n setDrawAreaRect(rect) {\n this._drawAreaRect = rect;\n return this;\n }\n setEntityRegistry(entityRegistry) {\n this._entityRegistry = entityRegistry;\n return this;\n }\n setProperty(propertyName, value) {\n this._properties[propertyName] = value;\n return this;\n }\n init() {\n return this;\n }\n /**\n * Hook for plugins that have to prepare themselves (e.g. resize their\n * buffer) before the changed data is processed.\n */\n onDataGroupsChanged(dataGroups) {\n }\n createBuffer(canvasElement, width = null, height = null) {\n this._buffer = document.createElement('canvas');\n this._buffer.width = width ?? canvasElement.width;\n this._buffer.height = height ?? canvasElement.height;\n this.bufferCtx = this._buffer.getContext('2d');\n }\n /**\n * Compares the given data groups by content against the ones seen by the\n * last update and remembers the result in `_dataGroupsChanged`. Comparing\n * by content (instead of holding on to the data groups themselves) is what\n * makes manipulations of already known data groups visible.\n */\n detectDataGroupsChange(dataGroups) {\n const signature = JSON.stringify(dataGroups);\n this._dataGroupsChanged = signature !== this._dataGroupsSignature;\n this._dataGroupsSignature = signature;\n }\n}\n\n\n//# sourceURL=webpack://@cehlers88/chart/./src/plugin/AbstractPlugin.ts?\n}");
|
|
238
238
|
|
|
239
239
|
/***/ },
|
|
240
240
|
|
|
@@ -245,7 +245,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
|
|
|
245
245
|
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
246
246
|
|
|
247
247
|
"use strict";
|
|
248
|
-
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ ERangeType: () => (/* binding */ ERangeType),\n/* harmony export */ \"default\": () => (/* binding */ BarsPlugin)\n/* harmony export */ });\n/* harmony import */ var _AbstractDiagramPlugin__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AbstractDiagramPlugin */ \"./src/plugin/AbstractDiagramPlugin.ts\");\n/**\n * Library BarsPlugin\n * Created 05.05.24\n *\n * @author Christoph Ehlers\n */\n\nvar ERangeType;\n(function (ERangeType) {\n ERangeType[\"ZERO_BASED\"] = \"zero_based\";\n ERangeType[\"MIN_MAX\"] = \"min_max\";\n})(ERangeType || (ERangeType = {}));\nclass BarsPlugin extends _AbstractDiagramPlugin__WEBPACK_IMPORTED_MODULE_0__[\"default\"] {\n barGroups = [];\n hoverPosition = { x: 0, y: 0 };\n rangeType = ERangeType.MIN_MAX;\n constructor(props = {}) {\n super({\n animationSpeed: 1,\n enableAnimation: true,\n padding: 0,\n ...props,\n });\n }\n drawBuffer() {\n this.barGroups.map((group) => {\n group.map((bar) => {\n this.bufferCtx.fillStyle = bar.color;\n const hover = this.hoverPosition.x >= bar.x && this.hoverPosition.x <= bar.x + bar.width;\n this.bufferCtx.fillRect(bar.x - (hover ? 1 : 0), bar.y, bar.width + (hover ? 2 : 0), bar.height);\n });\n });\n super.drawBuffer();\n }\n handleHover(x, y) {\n this.hoverPosition = { x, y };\n this.barGroups.map((group) => {\n group.map((bar) => {\n let changed = false;\n if (x >= bar.x && x <= bar.x + bar.width) {\n if (!bar.hovered) {\n changed = true;\n }\n bar.hovered = true;\n }\n else {\n if (bar.hovered) {\n changed = true;\n }\n bar.hovered = false;\n }\n if (changed) {\n this.redrawBuffer = true;\n }\n });\n });\n return this;\n }\n updateDataGroups(dataGroups) {\n if (
|
|
248
|
+
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ ERangeType: () => (/* binding */ ERangeType),\n/* harmony export */ \"default\": () => (/* binding */ BarsPlugin)\n/* harmony export */ });\n/* harmony import */ var _AbstractDiagramPlugin__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AbstractDiagramPlugin */ \"./src/plugin/AbstractDiagramPlugin.ts\");\n/**\n * Library BarsPlugin\n * Created 05.05.24\n *\n * @author Christoph Ehlers\n */\n\nvar ERangeType;\n(function (ERangeType) {\n ERangeType[\"ZERO_BASED\"] = \"zero_based\";\n ERangeType[\"MIN_MAX\"] = \"min_max\";\n})(ERangeType || (ERangeType = {}));\nclass BarsPlugin extends _AbstractDiagramPlugin__WEBPACK_IMPORTED_MODULE_0__[\"default\"] {\n barGroups = [];\n hoverPosition = { x: 0, y: 0 };\n rangeType = ERangeType.MIN_MAX;\n constructor(props = {}) {\n super({\n animationSpeed: 1,\n enableAnimation: true,\n padding: 0,\n ...props,\n });\n }\n drawBuffer() {\n this.barGroups.map((group) => {\n group.map((bar) => {\n this.bufferCtx.fillStyle = bar.color;\n const hover = this.hoverPosition.x >= bar.x && this.hoverPosition.x <= bar.x + bar.width;\n this.bufferCtx.fillRect(bar.x - (hover ? 1 : 0), bar.y, bar.width + (hover ? 2 : 0), bar.height);\n });\n });\n super.drawBuffer();\n }\n handleHover(x, y) {\n this.hoverPosition = { x, y };\n this.barGroups.map((group) => {\n group.map((bar) => {\n let changed = false;\n if (x >= bar.x && x <= bar.x + bar.width) {\n if (!bar.hovered) {\n changed = true;\n }\n bar.hovered = true;\n }\n else {\n if (bar.hovered) {\n changed = true;\n }\n bar.hovered = false;\n }\n if (changed) {\n this.redrawBuffer = true;\n }\n });\n });\n return this;\n }\n updateDataGroups(dataGroups) {\n if (this._dataGroupsChanged) {\n this.redrawBuffer = true;\n this._dataGroups = dataGroups;\n this.barGroups = [];\n const maxDataLength = dataGroups.length === 0 ? 0 : Math.max(...dataGroups.map((group) => group.data.length));\n if (maxDataLength === 0) {\n // Nothing (left) to draw - e.g. after the data was cleared at runtime.\n this.updateAnimations();\n return { dataGroups: this._dataGroups };\n }\n let maxValue = Math.max(...dataGroups.map((group) => group.infos.max));\n const minValue = Math.min(...dataGroups.map((group) => group.infos.min));\n const range = (maxValue - minValue) === 0 ? 1 : maxValue - minValue;\n //const minValueZeroDiff = minValue < 0 ? Math.abs(minValue) : 0;\n const viewHeight = this.getDrawAreaRect().h;\n const barWidth = (this.bufferCtx.canvas.width / (maxDataLength * dataGroups.length));\n //const zeroY = this.getDrawAreaRect().y + this.getDrawAreaRect().h - (minValueZeroDiff * viewHeight / maxValue);\n this._dataGroups.map((group, groupIndex) => {\n group.data.map((data, index) => {\n while (this.barGroups.length <= index) {\n this.barGroups.push([]);\n }\n const drawArea = this.getDrawAreaRect();\n const percentageValue = Math.round((data.value - minValue) / range * 100);\n const height = (viewHeight / 100) * Math.round(percentageValue);\n const y = viewHeight - (viewHeight / 100) * Math.round(percentageValue);\n const bar = {\n height, // this.getProperty('enableAnimation',false) ? 1 : data.value * viewHeight / maxValue,\n destinationH: 10,\n destinationY: y, //drawArea.y + drawArea.h - (data.valueEnd * viewHeight / maxValue),\n x: (groupIndex * barWidth) + (index * barWidth * dataGroups.length) + drawArea.x + 1,\n y: y, //this.getProperty('enableAnimation',false) ? drawArea.h - barHeight : drawArea.y + drawArea.h - (data.valueEnd * viewHeight / maxValue),\n width: barWidth - 2,\n color: group.color\n };\n this.barGroups[index].push(bar);\n });\n });\n }\n this.updateAnimations();\n return { dataGroups: this._dataGroups };\n }\n updateAnimations() {\n this.barGroups.map((group) => {\n group.map((bar) => {\n if (bar.y > bar.destinationY) {\n this.redrawBuffer = true;\n bar.y -= Math.min(1 * this.getProperty('animationSpeed', 1), bar.y - bar.destinationY);\n }\n if (bar.height < bar.destinationH) {\n this.redrawBuffer = true;\n bar.height += Math.min(1 * this.getProperty('animationSpeed', 1), bar.destinationH - bar.height);\n }\n });\n });\n return this;\n }\n getName() {\n return \"BarsPlugin\";\n }\n}\n\n\n//# sourceURL=webpack://@cehlers88/chart/./src/plugin/BarsPlugin.ts?\n}");
|
|
249
249
|
|
|
250
250
|
/***/ },
|
|
251
251
|
|
|
@@ -267,7 +267,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
|
|
|
267
267
|
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
268
268
|
|
|
269
269
|
"use strict";
|
|
270
|
-
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ ERangeType: () => (/* binding */ ERangeType),\n/* harmony export */ \"default\": () => (/* binding */ DiagramLine)\n/* harmony export */ });\n/* harmony import */ var _AbstractDiagramPlugin__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AbstractDiagramPlugin */ \"./src/plugin/AbstractDiagramPlugin.ts\");\n/* harmony import */ var _Event_TooltipEvent__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Event/TooltipEvent */ \"./src/Event/TooltipEvent.ts\");\n/**\n * Library DiagramLine\n * Created 26.11.22\n *\n * @author Christoph Ehlers\n */\n\n\nvar ERangeType;\n(function (ERangeType) {\n ERangeType[\"ZERO_BASED\"] = \"zero_based\";\n ERangeType[\"MIN_MAX\"] = \"min_max\";\n})(ERangeType || (ERangeType = {}));\nclass DiagramLine extends _AbstractDiagramPlugin__WEBPACK_IMPORTED_MODULE_0__[\"default\"] {\n bulletPointRadius = 2;\n bulletPointRadiusHover = 5;\n dataPoints = [];\n helpLines = [];\n hoverPosition = { x: 0, y: 0 };\n rangeType = ERangeType.MIN_MAX;\n syncGroupsPosition = false;\n zeroLineValue = 0;\n zeroLineValuePercentage = 0;\n constructor(props = {}) {\n super({\n fill: true,\n showBulletPoints: false,\n showHelpLines: false,\n showZeroLine: false,\n padding: 0,\n ...props\n });\n }\n drawHelpLines() {\n if (!this.getProperty('showHelpLines', false))\n return this;\n this.helpLines.map((helpLine) => {\n this.bufferCtx.strokeStyle = helpLine.color;\n this.bufferCtx.fillStyle = helpLine.color;\n this.bufferCtx.beginPath();\n this.bufferCtx.moveTo(super.getDrawAreaRect().x, helpLine.y);\n this.bufferCtx.lineTo(super.getDrawAreaRect().x + this.bufferCtx.canvas.width, helpLine.y);\n this.bufferCtx.stroke();\n this.bufferCtx.fillText(helpLine.label, super.getDrawAreaRect().x, helpLine.y);\n });\n return this;\n }\n drawBuffer() {\n const singlePercentageHeight = this.getDrawAreaRect().h / 100; // 1% height\n this.drawHelpLines();\n if (this._showZeroLine()) {\n this.bufferCtx.strokeStyle = '#000000';\n this.bufferCtx.beginPath();\n this.bufferCtx.moveTo(this.getDrawAreaRect().x, this.getDrawAreaRect().y + this.getDrawAreaRect().h - singlePercentageHeight * this.zeroLineValuePercentage);\n this.bufferCtx.lineTo(this.getDrawAreaRect().x + this.bufferCtx.canvas.width, this.getDrawAreaRect().y + this.getDrawAreaRect().h - singlePercentageHeight * this.zeroLineValuePercentage);\n this.bufferCtx.stroke();\n }\n //console.log('viewHeight', this.getDrawAreaRect().h, this);\n this.dataPoints.map(group => {\n this.bufferCtx.beginPath();\n let lastX = 0;\n group.map((dataPoint, index) => {\n this.bufferCtx.strokeStyle = dataPoint.color;\n this.bufferCtx.fillStyle = dataPoint.color + '88';\n this.bufferCtx.lineWidth = dataPoint.isHighlighted ? 2 : 1;\n if (index === 0) {\n if (this.getProperty('fill', false)) {\n this.bufferCtx.moveTo(dataPoint.x, this.getDrawAreaRect().y + this.getDrawAreaRect().h);\n this.bufferCtx.lineTo(dataPoint.x, dataPoint.y);\n return;\n }\n this.bufferCtx.moveTo(dataPoint.x, dataPoint.y);\n }\n else {\n this.bufferCtx.lineTo(dataPoint.x, dataPoint.y);\n }\n lastX = dataPoint.x;\n });\n if (this.getProperty('fill', false)) {\n this.bufferCtx.lineTo(lastX, this.getDrawAreaRect().y + this.getDrawAreaRect().h);\n this.bufferCtx.fill();\n }\n this.bufferCtx.stroke();\n });\n if (this.getProperty('showBulletPoints', false)) {\n this.dataPoints.map(group => {\n group.map((dataPoint) => {\n const mouseDistance = Math.sqrt(Math.pow(this.hoverPosition.x - dataPoint.x, 2) + Math.pow(this.hoverPosition.y - dataPoint.y, 2));\n if (mouseDistance < this.bulletPointRadiusHover) {\n _Event_TooltipEvent__WEBPACK_IMPORTED_MODULE_1__[\"default\"].dispatch('test', {});\n }\n this.bufferCtx.fillStyle = dataPoint.color;\n this.bufferCtx.beginPath();\n this.bufferCtx.arc(dataPoint.x, dataPoint.y, (mouseDistance < this.bulletPointRadiusHover ? this.bulletPointRadiusHover : this.bulletPointRadius), 0, 2 * Math.PI);\n this.bufferCtx.fill();\n });\n });\n }\n return this;\n }\n handleHover(x, y) {\n this.hoverPosition = { x, y };\n return this;\n }\n updateDataGroups(dataGroups) {\n if (
|
|
270
|
+
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ ERangeType: () => (/* binding */ ERangeType),\n/* harmony export */ \"default\": () => (/* binding */ DiagramLine)\n/* harmony export */ });\n/* harmony import */ var _AbstractDiagramPlugin__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AbstractDiagramPlugin */ \"./src/plugin/AbstractDiagramPlugin.ts\");\n/* harmony import */ var _Event_TooltipEvent__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Event/TooltipEvent */ \"./src/Event/TooltipEvent.ts\");\n/**\n * Library DiagramLine\n * Created 26.11.22\n *\n * @author Christoph Ehlers\n */\n\n\nvar ERangeType;\n(function (ERangeType) {\n ERangeType[\"ZERO_BASED\"] = \"zero_based\";\n ERangeType[\"MIN_MAX\"] = \"min_max\";\n})(ERangeType || (ERangeType = {}));\nclass DiagramLine extends _AbstractDiagramPlugin__WEBPACK_IMPORTED_MODULE_0__[\"default\"] {\n bulletPointRadius = 2;\n bulletPointRadiusHover = 5;\n dataPoints = [];\n helpLines = [];\n hoverPosition = { x: 0, y: 0 };\n rangeType = ERangeType.MIN_MAX;\n syncGroupsPosition = false;\n zeroLineValue = 0;\n zeroLineValuePercentage = 0;\n constructor(props = {}) {\n super({\n fill: true,\n showBulletPoints: false,\n showHelpLines: false,\n showZeroLine: false,\n padding: 0,\n ...props\n });\n }\n drawHelpLines() {\n if (!this.getProperty('showHelpLines', false))\n return this;\n this.helpLines.map((helpLine) => {\n this.bufferCtx.strokeStyle = helpLine.color;\n this.bufferCtx.fillStyle = helpLine.color;\n this.bufferCtx.beginPath();\n this.bufferCtx.moveTo(super.getDrawAreaRect().x, helpLine.y);\n this.bufferCtx.lineTo(super.getDrawAreaRect().x + this.bufferCtx.canvas.width, helpLine.y);\n this.bufferCtx.stroke();\n this.bufferCtx.fillText(helpLine.label, super.getDrawAreaRect().x, helpLine.y);\n });\n return this;\n }\n drawBuffer() {\n const singlePercentageHeight = this.getDrawAreaRect().h / 100; // 1% height\n this.drawHelpLines();\n if (this._showZeroLine()) {\n this.bufferCtx.strokeStyle = '#000000';\n this.bufferCtx.beginPath();\n this.bufferCtx.moveTo(this.getDrawAreaRect().x, this.getDrawAreaRect().y + this.getDrawAreaRect().h - singlePercentageHeight * this.zeroLineValuePercentage);\n this.bufferCtx.lineTo(this.getDrawAreaRect().x + this.bufferCtx.canvas.width, this.getDrawAreaRect().y + this.getDrawAreaRect().h - singlePercentageHeight * this.zeroLineValuePercentage);\n this.bufferCtx.stroke();\n }\n //console.log('viewHeight', this.getDrawAreaRect().h, this);\n this.dataPoints.map(group => {\n this.bufferCtx.beginPath();\n let lastX = 0;\n group.map((dataPoint, index) => {\n this.bufferCtx.strokeStyle = dataPoint.color;\n this.bufferCtx.fillStyle = dataPoint.color + '88';\n this.bufferCtx.lineWidth = dataPoint.isHighlighted ? 2 : 1;\n if (index === 0) {\n if (this.getProperty('fill', false)) {\n this.bufferCtx.moveTo(dataPoint.x, this.getDrawAreaRect().y + this.getDrawAreaRect().h);\n this.bufferCtx.lineTo(dataPoint.x, dataPoint.y);\n return;\n }\n this.bufferCtx.moveTo(dataPoint.x, dataPoint.y);\n }\n else {\n this.bufferCtx.lineTo(dataPoint.x, dataPoint.y);\n }\n lastX = dataPoint.x;\n });\n if (this.getProperty('fill', false)) {\n this.bufferCtx.lineTo(lastX, this.getDrawAreaRect().y + this.getDrawAreaRect().h);\n this.bufferCtx.fill();\n }\n this.bufferCtx.stroke();\n });\n if (this.getProperty('showBulletPoints', false)) {\n this.dataPoints.map(group => {\n group.map((dataPoint) => {\n const mouseDistance = Math.sqrt(Math.pow(this.hoverPosition.x - dataPoint.x, 2) + Math.pow(this.hoverPosition.y - dataPoint.y, 2));\n if (mouseDistance < this.bulletPointRadiusHover) {\n _Event_TooltipEvent__WEBPACK_IMPORTED_MODULE_1__[\"default\"].dispatch('test', {});\n }\n this.bufferCtx.fillStyle = dataPoint.color;\n this.bufferCtx.beginPath();\n this.bufferCtx.arc(dataPoint.x, dataPoint.y, (mouseDistance < this.bulletPointRadiusHover ? this.bulletPointRadiusHover : this.bulletPointRadius), 0, 2 * Math.PI);\n this.bufferCtx.fill();\n });\n });\n }\n return this;\n }\n handleHover(x, y) {\n this.hoverPosition = { x, y };\n return this;\n }\n updateDataGroups(dataGroups) {\n if (!this._dataGroupsChanged)\n return { dataGroups };\n this._dataGroups = dataGroups;\n if (dataGroups.length === 0 || dataGroups.every((dataGroup) => dataGroup.data.length === 0)) {\n // Nothing (left) to draw - e.g. after the data was cleared at runtime.\n this.dataPoints = [];\n this.helpLines = [];\n return { dataGroups };\n }\n const maxValue = Math.max(...dataGroups.map((group) => group.infos.max));\n const minValue = Math.min(...this._dataGroups.map((group) => group.infos.min), (this._showZeroLine() ? 0 : maxValue));\n this.zeroLineValue = Math.min(0, ...dataGroups.map((group) => group.infos.min)) * -1;\n this.zeroLineValuePercentage = this.zeroLineValue / (maxValue + this.zeroLineValue) * 100;\n const groupWithMostData = this._dataGroups.reduce((prev, current) => prev.data.length > current.data.length ? prev : current);\n const pointGap = this.calcPointGap(groupWithMostData);\n const largestDecimalStep = Math.max(...this._dataGroups.map((group) => group.infos.largestDecimalStep));\n const globalRange = (maxValue - minValue) === 0 ? 1 : maxValue - minValue;\n this.helpLines = [];\n for (let i = 1; i <= 10; i++) {\n let height = (this.getDrawAreaRect().h / 100) * Math.round(((i * largestDecimalStep) - minValue) / globalRange * 100);\n if (largestDecimalStep * i < minValue || largestDecimalStep * i > maxValue) {\n continue;\n }\n this.helpLines.push({\n color: '#ee4444',\n y: Math.round(this.getDrawAreaRect().h - height),\n label: (i * largestDecimalStep).toString()\n });\n }\n this.dataPoints = this._dataGroups.map((dataGroup) => {\n return dataGroup.data.map((dataPoint, index) => {\n let height = this.getDrawAreaRect().h - (this.getDrawAreaRect().h / 100) * Math.round((dataPoint.value - minValue) / globalRange * 100);\n if (dataPoint.empty)\n return undefined;\n return {\n ...dataPoint,\n x: this.getDrawAreaRect().x + pointGap * index,\n y: height,\n color: dataGroup.color,\n };\n }).filter((dataPoint) => dataPoint !== undefined);\n });\n return { dataGroups };\n }\n getDrawAreaRect() {\n const { x, y, h, w } = super.getDrawAreaRect();\n const manipulator = 0; //(this.getProperty('showBulletPoints', false) ? this.bulletPointRadiusHover : 0);\n return {\n x: x + manipulator,\n y: y + manipulator,\n h: h - (manipulator * 2),\n w: w - (manipulator * 2)\n };\n }\n getName() {\n return \"DiagramLine\";\n }\n _showZeroLine() {\n return this.getProperty('showZeroLine', false);\n }\n calcPointGap(dataGroup) {\n if (dataGroup.data.length < 2) {\n return this.getDrawAreaRect().w - (this.bulletPointRadius * 2);\n }\n return (this.getDrawAreaRect().w - (this.bulletPointRadius * 2)) / (dataGroup.data.length - 1);\n /*return this.getDrawAreaRect().w /\n (this.getProperty('viewSize', -1) === -1 ?\n (this.syncGroupsPosition ? Math.max(...this._dataGroups.map((group) => group.data.length - 1)) : dataGroup.data.length - 1) :\n this.getProperty('viewSize', -1) - 1)\n ;*/\n }\n}\n\n\n//# sourceURL=webpack://@cehlers88/chart/./src/plugin/DiagramLine.ts?\n}");
|
|
271
271
|
|
|
272
272
|
/***/ },
|
|
273
273
|
|
|
@@ -278,7 +278,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
|
|
|
278
278
|
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
279
279
|
|
|
280
280
|
"use strict";
|
|
281
|
-
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ EnrichGroupInfosPlugin)\n/* harmony export */ });\n/* harmony import */ var _AbstractPlugin__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AbstractPlugin */ \"./src/plugin/AbstractPlugin.ts\");\n/**\n * Library EnrichGroupInfosPlugin\n * Created 05.05,24\n *\n * @author Christoph Ehlers\n */\n\nclass EnrichGroupInfosPlugin extends _AbstractPlugin__WEBPACK_IMPORTED_MODULE_0__[\"default\"] {\n constructor() {\n super();\n this._priority = 1;\n }\n updateDataGroups(dataGroups) {\n if (
|
|
281
|
+
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ EnrichGroupInfosPlugin)\n/* harmony export */ });\n/* harmony import */ var _AbstractPlugin__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AbstractPlugin */ \"./src/plugin/AbstractPlugin.ts\");\n/**\n * Library EnrichGroupInfosPlugin\n * Created 05.05,24\n *\n * @author Christoph Ehlers\n */\n\nclass EnrichGroupInfosPlugin extends _AbstractPlugin__WEBPACK_IMPORTED_MODULE_0__[\"default\"] {\n constructor() {\n super();\n this._priority = 1;\n }\n updateDataGroups(dataGroups) {\n if (!this._dataGroupsChanged)\n return { dataGroups: this._dataGroups };\n this._dataGroups = dataGroups.map((dataGroup) => {\n const values = dataGroup.data.map((data) => data.value);\n const valueStarts = dataGroup.data.map((data) => data.valueStart ?? data.value);\n // A group may be empty (e.g. right after clearing or before the\n // first value was added), so the infos have to stay finite.\n const min = values.length === 0 ? 0 : Math.min(...valueStarts);\n const max = values.length === 0 ? 0 : Math.max(...values);\n const range = max - min;\n return {\n ...dataGroup,\n infos: {\n ...dataGroup.infos,\n largestDecimalStep: Math.max(this.getLargestDecimalStep(max), 0),\n max,\n min,\n range,\n valuePercentage: values.map((value) => range === 0 ? 0 : (value - min) / range * 100)\n }\n };\n });\n return {\n dataGroups: this._dataGroups\n };\n }\n getLargestDecimalStep(x) {\n if (x <= 0) {\n return 0;\n }\n return Math.pow(10, Math.floor(Math.log10(x)));\n }\n getName() {\n return \"EnrichGroupInfosPlugin\";\n }\n}\n\n\n//# sourceURL=webpack://@cehlers88/chart/./src/plugin/EnrichGroupInfosPlugin.ts?\n}");
|
|
282
282
|
|
|
283
283
|
/***/ },
|
|
284
284
|
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import { IChartPlugin } from "./IChartPlugin";
|
|
2
|
+
import { TDataGroup } from "../type/TDataGroup";
|
|
3
|
+
import { IChartEngine } from "./IChartEngine";
|
|
2
4
|
export interface ICanvasDiagram {
|
|
3
5
|
addPlugin(plugin: any): ICanvasDiagram;
|
|
6
|
+
addDataGroup(dataGroup: TDataGroup): ICanvasDiagram;
|
|
7
|
+
addValue(value: any, groupName?: string): ICanvasDiagram;
|
|
8
|
+
clearData(): ICanvasDiagram;
|
|
9
|
+
getDataGroup(group: string | number): TDataGroup | undefined;
|
|
10
|
+
getDataGroups(): TDataGroup[];
|
|
11
|
+
getEngine(): IChartEngine | undefined;
|
|
4
12
|
getPlugin(pluginName: string): IChartPlugin | undefined;
|
|
13
|
+
removeDataGroup(group: string | number): ICanvasDiagram;
|
|
14
|
+
removeValue(group: string | number, dataIndex: number): ICanvasDiagram;
|
|
15
|
+
setData(dataDefinition: string | any[] | object): ICanvasDiagram;
|
|
16
|
+
setDataGroups(dataGroups: TDataGroup[]): ICanvasDiagram;
|
|
17
|
+
setValue(group: string | number, dataIndex: number, value: any): ICanvasDiagram;
|
|
5
18
|
start(): ICanvasDiagram;
|
|
19
|
+
stop(): ICanvasDiagram;
|
|
6
20
|
}
|
|
@@ -4,7 +4,15 @@ export interface IChartEngine {
|
|
|
4
4
|
addValue(value: any, groupName?: string): IChartEngine;
|
|
5
5
|
addDataGroup(dataGroup: TDataGroup): IChartEngine;
|
|
6
6
|
addPlugin(plugin: IChartPlugin): IChartEngine;
|
|
7
|
+
clearData(): IChartEngine;
|
|
8
|
+
getDataGroup(group: string | number): TDataGroup | undefined;
|
|
9
|
+
getDataGroups(): TDataGroup[];
|
|
7
10
|
getPlugin(pluginName: string): IChartPlugin;
|
|
11
|
+
removeDataGroup(group: string | number): IChartEngine;
|
|
12
|
+
removeValue(group: string | number, dataIndex: number): IChartEngine;
|
|
13
|
+
setData(dataDefinition: string | any[] | object): IChartEngine;
|
|
14
|
+
setDataGroups(dataGroups: TDataGroup[]): IChartEngine;
|
|
15
|
+
setValue(group: string | number, dataIndex: number, value: any): IChartEngine;
|
|
8
16
|
draw(): IChartEngine;
|
|
9
17
|
update(): IChartEngine;
|
|
10
18
|
}
|
|
@@ -6,8 +6,6 @@ export default abstract class AbstractDiagramPlugin extends AbstractPlugin {
|
|
|
6
6
|
viewSize?: number;
|
|
7
7
|
[key: string]: any;
|
|
8
8
|
});
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
};
|
|
12
|
-
protected updateBufferSize(dataGroups: any): number;
|
|
9
|
+
protected onDataGroupsChanged(dataGroups: TDataGroup[]): void;
|
|
10
|
+
protected updateBufferSize(dataGroups: TDataGroup[]): number;
|
|
13
11
|
}
|
|
@@ -19,7 +19,9 @@ export default abstract class AbstractPlugin implements IChartPlugin {
|
|
|
19
19
|
protected bufferCtx: CanvasRenderingContext2D;
|
|
20
20
|
protected ctx: CanvasRenderingContext2D;
|
|
21
21
|
protected redrawBuffer: boolean;
|
|
22
|
+
protected _dataGroupsChanged: boolean;
|
|
22
23
|
private _buffer;
|
|
24
|
+
private _dataGroupsSignature;
|
|
23
25
|
private _stateChangedListener;
|
|
24
26
|
private _drawAreaRect;
|
|
25
27
|
private _properties;
|
|
@@ -57,5 +59,17 @@ export default abstract class AbstractPlugin implements IChartPlugin {
|
|
|
57
59
|
setEntityRegistry(entityRegistry: EntityRegistry): AbstractPlugin;
|
|
58
60
|
setProperty(propertyName: string, value: any): AbstractPlugin;
|
|
59
61
|
init(): AbstractPlugin;
|
|
62
|
+
/**
|
|
63
|
+
* Hook for plugins that have to prepare themselves (e.g. resize their
|
|
64
|
+
* buffer) before the changed data is processed.
|
|
65
|
+
*/
|
|
66
|
+
protected onDataGroupsChanged(dataGroups: TDataGroup[]): void;
|
|
60
67
|
protected createBuffer(canvasElement: HTMLCanvasElement, width?: number | null, height?: number | null): void;
|
|
68
|
+
/**
|
|
69
|
+
* Compares the given data groups by content against the ones seen by the
|
|
70
|
+
* last update and remembers the result in `_dataGroupsChanged`. Comparing
|
|
71
|
+
* by content (instead of holding on to the data groups themselves) is what
|
|
72
|
+
* makes manipulations of already known data groups visible.
|
|
73
|
+
*/
|
|
74
|
+
private detectDataGroupsChange;
|
|
61
75
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cehlers88/chart",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "A library to create charts using JavaScript and Canvas-Element.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"publishConfig": {
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"@types/jest": "^29.5.13",
|
|
35
35
|
"css-loader": "^7.1.2",
|
|
36
36
|
"jest": "^29.7.0",
|
|
37
|
+
"jest-environment-jsdom": "^29.7.0",
|
|
37
38
|
"style-loader": "^4.0.0",
|
|
38
39
|
"ts-jest": "^29.2.5",
|
|
39
40
|
"ts-loader": "^9.5.1",
|