(elem: Element
, ctx: CanvasRenderingContext2D): void {
175 | const props = elem.getProps(['x', 'y', 'width', 'height', 'xMin', 'xMax', 'yMin', 'yMax']);
176 | if (props.xMin != null || props.xMax != null) {
177 | drawErrorBarHorizontal(props, props.xMin ?? null, props.xMax ?? null, elem.options as any, ctx);
178 | }
179 | if (props.yMin != null || props.yMax != null) {
180 | drawErrorBarVertical(props, props.yMin ?? null, props.yMax ?? null, elem.options as any, ctx);
181 | }
182 | }
183 |
184 | /**
185 | * @param {number} vMin
186 | * @param {number} vMax
187 | * @param {CanvasRenderingContext2D} ctx
188 | */
189 | function drawErrorBarArc(
190 | props: ArcProps,
191 | vMin: null | number | number[],
192 | vMax: null | number | number[],
193 | options: IErrorBarOptions,
194 | ctx: CanvasRenderingContext2D
195 | ) {
196 | ctx.save();
197 | ctx.translate(props.x, props.y); // move to center
198 |
199 | const angle = (props.startAngle + props.endAngle) / 2;
200 | const cosAngle = Math.cos(angle);
201 | const sinAngle = Math.sin(angle);
202 | // perpendicular
203 | const v = {
204 | x: -sinAngle,
205 | y: cosAngle,
206 | };
207 | const length = Math.sqrt(v.x * v.x + v.y * v.y);
208 | v.x /= length;
209 | v.y /= length;
210 |
211 | const bars = resolveMulti(vMin ?? props.outerRadius, vMax ?? props.outerRadius);
212 |
213 | bars.reverse().forEach(([mi, ma], j) => {
214 | const i = bars.length - j - 1;
215 |
216 | const minCos = mi * cosAngle;
217 | const minSin = mi * sinAngle;
218 | const maxCos = ma * cosAngle;
219 | const maxSin = ma * sinAngle;
220 |
221 | const halfHeight = calculateHalfSize(null, options, i);
222 | const eX = v.x * halfHeight;
223 | const eY = v.y * halfHeight;
224 |
225 | // center line
226 | ctx.lineWidth = resolveOption(options.errorBarLineWidth, i);
227 | ctx.strokeStyle = resolveOption(options.errorBarColor, i);
228 | ctx.beginPath();
229 | ctx.moveTo(minCos, minSin);
230 | ctx.lineTo(maxCos, maxSin);
231 | ctx.stroke();
232 |
233 | // whisker
234 | ctx.lineWidth = resolveOption(options.errorBarWhiskerLineWidth, i);
235 | ctx.strokeStyle = resolveOption(options.errorBarWhiskerColor, i);
236 | ctx.beginPath();
237 | ctx.moveTo(minCos + eX, minSin + eY);
238 | ctx.lineTo(minCos - eX, minSin - eY);
239 | ctx.moveTo(maxCos + eX, maxSin + eY);
240 | ctx.lineTo(maxCos - eX, maxSin - eY);
241 | ctx.stroke();
242 | });
243 |
244 | ctx.restore();
245 | }
246 |
247 | export function renderErrorBarArc(elem: any, ctx: CanvasRenderingContext2D): void {
248 | const props = elem.getProps(['x', 'y', 'startAngle', 'endAngle', 'rMin', 'rMax', 'outerRadius']);
249 | if (props.rMin != null || props.rMax != null) {
250 | drawErrorBarArc(props, props.rMin, props.rMax, elem.options as any, ctx);
251 | }
252 | }
253 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './elements';
2 | export * from './controllers';
3 |
--------------------------------------------------------------------------------
/src/index.umd.ts:
--------------------------------------------------------------------------------
1 | import { registry } from 'chart.js';
2 | import {
3 | BarWithErrorBarsController,
4 | LineWithErrorBarsController,
5 | PolarAreaWithErrorBarsController,
6 | ScatterWithErrorBarsController,
7 | } from './controllers';
8 | import { BarWithErrorBar, ArcWithErrorBar, PointWithErrorBar } from './elements';
9 |
10 | export * from '.';
11 |
12 | registry.addControllers(
13 | BarWithErrorBarsController,
14 | LineWithErrorBarsController,
15 | PolarAreaWithErrorBarsController,
16 | ScatterWithErrorBarsController
17 | );
18 | registry.addElements(BarWithErrorBar, ArcWithErrorBar, PointWithErrorBar);
19 |
--------------------------------------------------------------------------------
/tsconfig.c.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "build",
5 | "declaration": true,
6 | "declarationMap": true,
7 | "noEmit": true,
8 | "composite": true
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2018",
4 | "module": "ESNext",
5 | "lib": ["DOM", "ES2020"],
6 | "importHelpers": false,
7 | "declaration": false,
8 | "sourceMap": true,
9 | "strict": true,
10 | "removeComments": true,
11 | "verbatimModuleSyntax": false,
12 | "experimentalDecorators": true,
13 | "forceConsistentCasingInFileNames": true,
14 | "strictBindCallApply": true,
15 | "stripInternal": true,
16 | "resolveJsonModule": true,
17 | "noUnusedLocals": true,
18 | "noUnusedParameters": true,
19 | "noImplicitReturns": true,
20 | "noFallthroughCasesInSwitch": true,
21 | "moduleResolution": "Bundler",
22 | "jsx": "react",
23 | "esModuleInterop": true,
24 | "rootDir": "./src",
25 | "baseUrl": "./",
26 | "noEmit": true,
27 | "paths": {
28 | "@": ["./src"],
29 | "*": ["*", "node_modules/*"],
30 | // workaround for: https://github.com/vitest-dev/vitest/issues/4567
31 | "rollup/parseAst": ["./node_modules/rollup/dist/parseAst"]
32 | }
33 | },
34 | "include": ["src/**/*.ts", "src/**/*.tsx", "docs/**/*.tsx"]
35 | }
36 |
--------------------------------------------------------------------------------
/typedoc.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://typedoc.org/schema.json",
3 | "entryPoints": ["./src"],
4 | "plugin": ["typedoc-plugin-markdown", "typedoc-vitepress-theme"],
5 | "name": "chartjs-chart-error-bars",
6 | "out": "./docs/api",
7 | "docsRoot": "./docs/",
8 | "readme": "none",
9 | "sidebar": {
10 | "pretty": true
11 | },
12 | "theme": "default",
13 | "excludeExternals": true,
14 | "excludeInternal": true,
15 | "excludePrivate": true,
16 | "includeVersion": true,
17 | "categorizeByGroup": true,
18 | "cleanOutputDir": true,
19 | "hideGenerator": true
20 | }
21 |
--------------------------------------------------------------------------------
/vitest.config.ts:
--------------------------------------------------------------------------------
1 | ///