-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathcore.ts
143 lines (130 loc) · 3.66 KB
/
core.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
import { ChartJs } from "./deps.ts";
import { Rect2D, SvgCanvas, SvgCanvas2DGradient } from "./deps_server.ts";
class ChartSvgCanvas extends SvgCanvas {
public override clearRect(x: number, y: number, w: number, h: number): void {
this.save();
this.fillStyle = "transparent";
this.fillRect(x, y, w, h);
this.restore();
}
public resetTransform() {
this.setTransform(1, 0, 0, 1, 0, 0);
}
}
/** Underlying ChartJS defaults which can be modified. */
export const defaults: ChartJs.Defaults = ChartJs.defaults;
/** The set of chart options that are supported. Unsupported or fixed values
* are omitted from the underlying {@linkcode ChartJs.ChartOptions}. */
export type ChartOptions<TType extends ChartJs.ChartType = ChartJs.ChartType> =
Omit<
ChartJs.ChartOptions<TType>,
| "responsive"
| "responsiveAnimationDuration"
| "events"
| "legendCallback"
| "onHover"
| "onClick"
| "onResize"
| "hover"
| "animation"
>;
/** The configuration options that are settable when rendering a chart. */
export interface ChartConfiguration<
TType extends ChartJs.ChartType = ChartJs.ChartType,
TData = ChartJs.DefaultDataPoint<TType>,
TLabel = unknown,
> {
/** The width, in pixels, of the chart.
*
* Defaults to `768`.
*/
width?: number;
/** The height, in pixels, of the chart.
*
* Defaults to `384`.
*/
height?: number;
/** The type of chart.
*
* Defaults to `"line"`.
*/
type?: ChartJs.ChartType;
/** Data to be rendered in the chart. */
data: ChartJs.ChartData<TType, TData, TLabel>;
/** Options which can be configured on the chart. */
options?: ChartOptions;
/** Chart plugins to be registered for the chart. */
plugins?: ChartJs.Plugin[];
/** CSS class for the <svg> element of the chart. */
svgClass?: string;
/** CSS style for the <svg> element of the chart */
svgStyle?: string;
}
interface SvgCanvasExtras {
canvas?: {
width: number;
height: number;
style: Record<string, string>;
};
resetTransform?(): void;
}
/** Render a chart, returning a SVG string representation of the chart.
*
* This is a lower level function, where the `Chart` component and `renderChart`
* are intended for use within a Fresh application.
*/
export function chart<
TType extends ChartJs.ChartType = ChartJs.ChartType,
TData = ChartJs.DefaultDataPoint<TType>,
TLabel = unknown,
>(
{
width = 768,
height = 384,
type = "bar",
data,
options = {},
plugins,
svgClass,
svgStyle,
}: ChartConfiguration<TType, TData, TLabel> = { data: { datasets: [] } },
): string {
Object.assign(options, {
animation: false,
events: [],
responsive: false,
});
const ctx: ChartSvgCanvas & SvgCanvasExtras = new ChartSvgCanvas();
ctx.canvas = {
width,
height,
style: { width: `${width}px`, height: `${height}px` },
};
ctx.fontHeightRatio = 2;
// deno-lint-ignore no-explicit-any
const el: HTMLCanvasElement = { getContext: () => ctx } as any;
const savedGradient = globalThis.CanvasGradient;
globalThis.CanvasGradient = SvgCanvas2DGradient as typeof CanvasGradient;
try {
new ChartJs.Chart(el, { type, data, options, plugins });
} finally {
if (savedGradient) {
globalThis.CanvasGradient = savedGradient;
}
}
let svg = ctx.render(new Rect2D(0, 0, width, height), "px");
if (svgStyle) {
svg = svg.replace(
"<svg ",
`<svg style="${svgStyle.replaceAll('"', """)}" `,
);
}
if (svgClass) {
svg = svg.replace(
"<svg ",
`<svg class="${svgClass.replaceAll('"', """)}" `,
);
}
return svg;
}