Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(a11y): add textures to fill options #1138

Merged
merged 27 commits into from
Jun 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
58f3a73
feat: texture: Add svg image to chart_types
ron-debajyoti Apr 18, 2021
9b95ddd
feat(textures): an example of allowing textures with colors, implemen…
ron-debajyoti Apr 24, 2021
4bfdb13
feat(textures): update package.json
ron-debajyoti Apr 24, 2021
9e79aff
feat(a11y): add partial refactor of textures implementation
ron-debajyoti May 9, 2021
66b0570
feat(a11y): add rotation attribute for textures
ron-debajyoti May 11, 2021
16b9525
Merge branch 'master' into texture-fill
ron-debajyoti May 11, 2021
8eb2b44
fix(a11y): refactor functions in xy_chart
ron-debajyoti May 12, 2021
9a2fe5d
Merge branch 'master' into texture-fill
ron-debajyoti May 20, 2021
df766a8
chore: cleanup area texture logic
nickofthyme May 27, 2021
10518c5
feat: add textures to rect fill styles
nickofthyme May 27, 2021
23b84a3
fix: broken bar story
nickofthyme May 27, 2021
4323470
Merge branch 'master' into texture-fill
nickofthyme May 27, 2021
741db93
Merge branch 'master' into texture-fill
nickofthyme May 28, 2021
eb0394b
fix: api ci check
nickofthyme May 28, 2021
883c2b4
Merge remote-tracking branch 'ron/texture-fill' into texture-fill
nickofthyme May 28, 2021
c701130
fix: linting ci check
nickofthyme May 28, 2021
e7a807e
test: fix failing tests, add new texture tests with canvas mocks
nickofthyme May 28, 2021
89c1532
test: add vrt test and update broken test
nickofthyme May 28, 2021
73d6244
fix: render nodeLabel formatted text into the nodes
monfera Jun 7, 2021
3504822
Merge branch 'master' into texture-fill
nickofthyme Jun 7, 2021
f1836e4
Merge remote-tracking branch 'ron/texture-fill' into texture-fill
nickofthyme Jun 7, 2021
a37df95
fix: also apply the dpi scaler to the pattern canvas itself
monfera Jun 7, 2021
4f31500
Merge branch 'master' into texture-fill
nickofthyme Jun 7, 2021
65a9ee6
Merge branch 'master' into texture-fill
nickofthyme Jun 8, 2021
8fa599c
Merge branch 'master' into texture-fill
nickofthyme Jun 8, 2021
d191ead
Merge remote-tracking branch 'ron/texture-fill' into texture-fill
nickofthyme Jun 8, 2021
be73881
chore: remove added texture
nickofthyme Jun 8, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ license_header.js
# Compiled source
src/utils/d3-delaunay/*
**/dist

# auto generated directories
integration/tmp
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ module.exports = {
files: ['stories/**/*.ts?(x)', 'docs/**/*.ts?(x)'],
rules: {
'@typescript-eslint/no-unsafe-call': 0,
'@typescript-eslint/no-unnecessary-type-assertion': 0,
},
},
{
Expand Down
46 changes: 46 additions & 0 deletions api/charts.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ export interface AreaSeriesStyle {
export interface AreaStyle {
fill?: Color | ColorVariant;
opacity: number;
texture?: TexturedStyles;
visible: boolean;
}

Expand Down Expand Up @@ -1585,6 +1586,7 @@ export interface RectBorderStyle {
export interface RectStyle {
fill?: Color | ColorVariant;
opacity: number;
texture?: TexturedStyles;
widthPixel?: Pixels;
widthRatio?: Ratio;
}
Expand Down Expand Up @@ -1962,6 +1964,50 @@ export interface TextStyle {
padding: number | SimplePadding;
}

// @public (undocumented)
export interface TexturedPathStyles extends TexturedStylesBase {
path: string | Path2D;
}

// @public (undocumented)
export interface TexturedShapeStyles extends TexturedStylesBase {
shape: TextureShape;
}

// @public
export type TexturedStyles = TexturedPathStyles | TexturedShapeStyles;

// @public (undocumented)
export interface TexturedStylesBase {
dash?: number[];
fill?: Color | ColorVariant;
offset?: Partial<Point> & {
global?: boolean;
};
opacity?: number;
rotation?: number;
shapeRotation?: number;
size?: number;
// Warning: (ae-forgotten-export) The symbol "Point" needs to be exported by the entry point index.d.ts
spacing?: Partial<Point> | number;
stroke?: Color | ColorVariant;
strokeWidth?: number;
}

// @public (undocumented)
export const TextureShape: Readonly<{
Line: "line";
Circle: "circle";
Square: "square";
Diamond: "diamond";
Plus: "plus";
X: "x";
Triangle: "triangle";
}>;

// @public (undocumented)
export type TextureShape = $Values<typeof TextureShape>;

// @public (undocumented)
export interface Theme {
// (undocumented)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
52 changes: 52 additions & 0 deletions integration/tests/stylings_stories.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { SeriesType } from '../../src';
import { common } from '../page_objects';

describe('Stylings stories', () => {
describe('Texture', () => {
describe.each([SeriesType.Bar, SeriesType.Area])('%s', (seriesType) => {
it(`should use custom path`, async () => {
await common.expectChartAtUrlToMatchScreenshot(
`http://localhost:9001/?path=/story/stylings--with-texture&knob-Use custom path_Texture=true&knob-Custom path_Texture=M -7.75 -2.5 l 5.9 0 l 1.85 -6.1 l 1.85 6.1 l 5.9 0 l -4.8 3.8 l 1.85 6.1 l -4.8 -3.8 l -4.8 3.8 l 1.85 -6.1 l -4.8 -3.8 z&knob-Use stroke color_Texture=true&knob-Stoke color_Texture=&knob-Stroke width_Texture=1&knob-Use fill color_Texture=true&knob-Fill color_Texture=&knob-Rotation (degrees)_Pattern=45&knob-Opacity_Texture=1&knob-Shape rotation (degrees)_Texture=0&knob-Shape size - custom path_Texture=20&knob-Shape spacing - x_Pattern=10&knob-Shape spacing - y_Pattern=0&knob-Pattern offset - x_Pattern=0&knob-Pattern offset - y_Pattern=0&knob-Apply offset along global coordinate axes_Pattern=true&knob-Series opacity_Series=1&knob-Show series fill_Series=&knob-Series color_Series=rgba(0,0,0,1)&knob-Series type_Series=${seriesType}`,
);
});

it(`should render texture with lines as shape`, async () => {
await common.expectChartAtUrlToMatchScreenshot(
`http://localhost:9001/?path=/story/stylings--with-texture&knob-Use custom path_Texture=&knob-Shape_Texture=line&knob-Use stroke color_Texture=true&knob-Stoke color_Texture=rgba(0,0,0,1)&knob-Stroke width_Texture=1&knob-Stroke dash_Texture[0]=10&knob-Stroke dash_Texture[1]= 5&knob-Use fill color_Texture=&knob-Fill color_Texture=rgba(30,165,147,0.28)&knob-Rotation (degrees)_Pattern=-45&knob-Opacity_Texture=1&knob-Shape rotation (degrees)_Texture=0&knob-Shape size_Texture=20&knob-Shape spacing - x_Pattern=0&knob-Shape spacing - y_Pattern=0&knob-Pattern offset - x_Pattern=0&knob-Pattern offset - y_Pattern=0&knob-Apply offset along global coordinate axes_Pattern=true&knob-Series opacity_Series=1&knob-Show series fill_Series=&knob-Series color_Series=rgba(0,0,0,1)&knob-Series type_Series=${seriesType}`,
);
});

it(`should allow any random texture customization`, async () => {
await common.expectChartAtUrlToMatchScreenshot(
`http://localhost:9001/?path=/story/stylings--texture-multiple-series&knob-Total series=4&knob-Show legend=&knob-Show series fill=&knob-Chart color=rgba(0,0,0,1)&knob-Shape_Randomized parameters=true&knob-Rotation_Randomized parameters=true&knob-Shape rotation_Randomized parameters=true&knob-Size_Randomized parameters=true&knob-X spacing_Randomized parameters=true&knob-Y spacing_Randomized parameters=true&knob-X offset_Randomized parameters=true&knob-Y offset_Randomized parameters=true&knob-Series type=${seriesType}&knob-Shape_Default parameters=circle&knob-Stroke width_Default parameters=1&knob-Rotation (degrees)_Default parameters=45&knob-Shape rotation (degrees)_Default parameters=0&knob-Shape size_Default parameters=20&knob-Opacity_Default parameters=1&knob-Shape spacing - x_Default parameters=10&knob-Shape spacing - y_Default parameters=10&knob-Pattern offset - x_Default parameters=0&knob-Pattern offset - y_Default parameters=0`,
);
});

it(`should use hover opacity for texture`, async () => {
await common.expectChartWithMouseAtUrlToMatchScreenshot(
`http://localhost:9001/?path=/story/stylings--texture-multiple-series&knob-Total series=4&knob-Show legend=true&knob-Show series fill=&knob-Chart color=rgba(0,0,0,1)&knob-Shape_Randomized parameters=true&knob-Rotation_Randomized parameters=&knob-Shape rotation_Randomized parameters=&knob-Size_Randomized parameters=true&knob-X spacing_Randomized parameters=&knob-Y spacing_Randomized parameters=&knob-X offset_Randomized parameters=&knob-Y offset_Randomized parameters=&knob-Series type=${seriesType}&knob-Shape_Default parameters=circle&knob-Stroke width_Default parameters=1&knob-Rotation (degrees)_Default parameters=45&knob-Shape rotation (degrees)_Default parameters=0&knob-Shape size_Default parameters=20&knob-Opacity_Default parameters=1&knob-Shape spacing - x_Default parameters=10&knob-Shape spacing - y_Default parameters=10&knob-Pattern offset - x_Default parameters=0&knob-Pattern offset - y_Default parameters=0`,
{ top: 45, right: 40 },
);
});
});
});
});
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@
"html-webpack-plugin": "^4.5.2",
"husky": "^4.3.6",
"jest": "^26.6.3",
"jest-canvas-mock": "^2.3.1",
"jest-extended": "^0.11.5",
"jest-image-snapshot": "^4.3.0",
"jest-matcher-utils": "^26.6.2",
Expand Down
14 changes: 8 additions & 6 deletions src/chart_types/xy_chart/renderer/canvas/areas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ interface AreaGeometriesProps {
}

/** @internal */
export function renderAreas(ctx: CanvasRenderingContext2D, props: AreaGeometriesProps) {
export function renderAreas(ctx: CanvasRenderingContext2D, imgCanvas: HTMLCanvasElement, props: AreaGeometriesProps) {
const { sharedStyle, highlightedLegendItem, areas, rotation, clippings, renderingArea } = props;

withContext(ctx, (ctx) => {
Expand All @@ -54,7 +54,7 @@ export function renderAreas(ctx: CanvasRenderingContext2D, props: AreaGeometries
rotation,
renderingArea,
(ctx) => {
renderArea(ctx, area, sharedStyle, clippings, highlightedLegendItem);
renderArea(ctx, imgCanvas, area, sharedStyle, clippings, highlightedLegendItem);
},
{ area: clippings, shouldClip: true },
);
Expand Down Expand Up @@ -96,15 +96,17 @@ export function renderAreas(ctx: CanvasRenderingContext2D, props: AreaGeometries

function renderArea(
ctx: CanvasRenderingContext2D,
imgCanvas: HTMLCanvasElement,
glyph: AreaGeometry,
sharedStyle: SharedGeometryStateStyle,
clippings: Rect,
highlightedLegendItem?: LegendItem,
) {
const { area, color, transform, seriesIdentifier, seriesAreaStyle, clippedRanges, hideClippedRanges } = glyph;
const geometryStateStyle = getGeometryStateStyle(seriesIdentifier, sharedStyle, highlightedLegendItem);
const fill = buildAreaStyles(color, seriesAreaStyle, geometryStateStyle);
renderAreaPath(ctx, transform, area, fill, clippedRanges, clippings, hideClippedRanges);
const styles = buildAreaStyles(ctx, imgCanvas, color, seriesAreaStyle, geometryStateStyle);

renderAreaPath(ctx, transform, area, styles, clippedRanges, clippings, hideClippedRanges);
}

function renderAreaLines(
Expand All @@ -116,7 +118,7 @@ function renderAreaLines(
) {
const { lines, color, seriesIdentifier, transform, seriesAreaLineStyle, clippedRanges, hideClippedRanges } = glyph;
const geometryStateStyle = getGeometryStateStyle(seriesIdentifier, sharedStyle, highlightedLegendItem);
const stroke = buildLineStyles(color, seriesAreaLineStyle, geometryStateStyle);
const styles = buildLineStyles(color, seriesAreaLineStyle, geometryStateStyle);

renderLinePaths(ctx, transform, lines, stroke, clippedRanges, clippings, hideClippedRanges);
renderLinePaths(ctx, transform, lines, styles, clippedRanges, clippings, hideClippedRanges);
}
21 changes: 19 additions & 2 deletions src/chart_types/xy_chart/renderer/canvas/bars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { withPanelTransform } from './utils/panel_transform';
/** @internal */
export function renderBars(
ctx: CanvasRenderingContext2D,
imgCanvas: HTMLCanvasElement,
barGeometries: Array<PerPanel<BarGeometry[]>>,
sharedStyle: SharedGeometryStateStyle,
clippings: Rect,
Expand All @@ -40,13 +41,22 @@ export function renderBars(
rotation?: Rotation,
) {
withContext(ctx, (ctx) => {
const barRenderer = renderPerPanelBars(ctx, clippings, sharedStyle, renderingArea, highlightedLegendItem, rotation);
const barRenderer = renderPerPanelBars(
ctx,
imgCanvas,
clippings,
sharedStyle,
renderingArea,
highlightedLegendItem,
rotation,
);
barGeometries.forEach(barRenderer);
});
}

function renderPerPanelBars(
ctx: CanvasRenderingContext2D,
imgCanvas: HTMLCanvasElement,
clippings: Rect,
sharedStyle: SharedGeometryStateStyle,
renderingArea: Dimensions,
Expand All @@ -66,7 +76,14 @@ function renderPerPanelBars(
bars.forEach((barGeometry) => {
const { x, y, width, height, color, seriesStyle, seriesIdentifier } = barGeometry;
const geometryStateStyle = getGeometryStateStyle(seriesIdentifier, sharedStyle, highlightedLegendItem);
const { fill, stroke } = buildBarStyles(color, seriesStyle.rect, seriesStyle.rectBorder, geometryStateStyle);
const { fill, stroke } = buildBarStyles(
ctx,
imgCanvas,
color,
seriesStyle.rect,
seriesStyle.rectBorder,
geometryStateStyle,
);
const rect = { x, y, width, height };
withContext(ctx, (ctx) => {
renderRect(ctx, rect, fill, stroke);
Expand Down
20 changes: 19 additions & 1 deletion src/chart_types/xy_chart/renderer/canvas/primitives/path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import { RGBtoString } from '../../../../../common/color_library_wrappers';
import { Rect, Stroke, Fill } from '../../../../../geoms/types';
import { withContext, withClipRanges } from '../../../../../renderers/canvas';
import { getRadians } from '../../../../../utils/common';
import { ClippedRanges } from '../../../../../utils/geometry';
import { Point } from '../../../../../utils/point';
import { renderMultiLine } from './line';
Expand Down Expand Up @@ -93,6 +94,23 @@ export function renderAreaPath(
function renderPathFill(ctx: CanvasRenderingContext2D, path: string, fill: Fill) {
const path2d = new Path2D(path);
ctx.fillStyle = RGBtoString(fill.color);
ctx.beginPath();
ctx.fill(path2d);

if (fill.texture) {
ctx.clip(path2d);

const rotation = getRadians(fill.texture.rotation ?? 0);
const { offset } = fill.texture;

if (offset && offset.global) ctx.translate(offset?.x ?? 0, offset?.y ?? 0);
if (rotation) ctx.rotate(rotation);
if (offset && !offset.global) ctx.translate(offset?.x ?? 0, offset?.y ?? 0);

ctx.fillStyle = fill.texture.pattern;

// Use oversized rect to fill rotation/offset beyond path
const rotationRectFillSize = ctx.canvas.clientWidth * ctx.canvas.clientHeight;
ctx.translate(-rotationRectFillSize / 2, -rotationRectFillSize / 2);
ctx.fillRect(0, 0, rotationRectFillSize, rotationRectFillSize);
Comment on lines +111 to +114
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@markov00 I'm not sure if there is a better approach than this but the idea is to allow rotation of the pattern. If I set the fillRect to the dimensions of the canvas it will likely not fill the entire path area with the repeated pattern, which ends up looking like this...

Screen.Recording.2021-05-28.at.12.59.51.PM.mp4

So I just multiply the height and width to provide a large enough area for rotating the pattern.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nickofthyme This is working fine for me with no gaps while filling the area, since we are translating the ctx before filling the rect (using ctx.fillRect)
Is there an exact case in which this error occurs ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No sorry for the confusion, this code is to handle the error shown in the screen recording. I'm just wondering if there is a better approach to solving this.

Also, I haven't tested shapes with large aspect ratios but I haven't seen a case where this code doesn't work.

Copy link
Member

@markov00 markov00 May 31, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the case of the a line pattern as shown in the example, probably a workaround for that is to render the pattern line with the double size (or at least L * Math.sqrt(L)): this can prevent issues when rotating a line, of L in length, in a LxL rotated square.

}
}
61 changes: 25 additions & 36 deletions src/chart_types/xy_chart/renderer/canvas/primitives/rect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

import { RGBtoString } from '../../../../../common/color_library_wrappers';
import { Rect, Fill, Stroke } from '../../../../../geoms/types';
import { withContext } from '../../../../../renderers/canvas';
import { getRadians } from '../../../../../utils/common';

/** @internal */
export function renderRect(
Expand All @@ -38,9 +40,32 @@ export function renderRect(
const y = rect.y + borderOffset;
const width = rect.width - borderOffset * 2;
const height = rect.height - borderOffset * 2;

drawRect(ctx, { x, y, width, height });
ctx.fillStyle = RGBtoString(fill.color);
ctx.fill();

if (fill.texture) {
const { texture } = fill;
withContext(ctx, (ctx) => {
drawRect(ctx, { x, y, width, height });
ctx.clip();

const rotation = getRadians(texture.rotation ?? 0);
const { offset } = texture;

if (offset && offset.global) ctx.translate(offset?.x ?? 0, offset?.y ?? 0);
if (rotation) ctx.rotate(rotation);
if (offset && !offset.global) ctx.translate(offset?.x ?? 0, offset?.y ?? 0);

ctx.fillStyle = texture.pattern;

// Use oversized rect to fill rotation/offset beyond path
const rotationRectFillSize = ctx.canvas.clientWidth * ctx.canvas.clientHeight;
ctx.translate(-rotationRectFillSize / 2, -rotationRectFillSize / 2);
ctx.fillRect(0, 0, rotationRectFillSize, rotationRectFillSize);
});
}
}

if (stroke && stroke.width > 0.001) {
Expand Down Expand Up @@ -74,39 +99,3 @@ function drawRect(ctx: CanvasRenderingContext2D, rect: Rect) {
ctx.lineTo(x, y + height);
ctx.lineTo(x, y);
}

/** @internal */
export function renderMultiRect(ctx: CanvasRenderingContext2D, rects: Rect[], fill?: Fill, stroke?: Stroke) {
if (!fill && !stroke && rects.length > 0) {
return;
}

const rectsLength = rects.length;
ctx.beginPath();
for (let i = 0; i < rectsLength; i++) {
const { width, height, x, y } = rects[i];
ctx.moveTo(x, y);
ctx.lineTo(x + width, y);
ctx.lineTo(x + width, y + height);
ctx.lineTo(x, y + height);
ctx.lineTo(x, y);
}

if (fill) {
ctx.fillStyle = RGBtoString(fill.color);
ctx.fill();
}
if (stroke && stroke.width > 0.001) {
// Canvas2d stroke ignores an exact zero line width
ctx.strokeStyle = RGBtoString(stroke.color);
ctx.lineWidth = stroke.width;
ctx.stroke();

if (stroke.dash) {
ctx.setLineDash(stroke.dash);
} else {
// Setting linecap with dash causes solid line
ctx.lineCap = 'square';
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import { Circle, Fill, Stroke } from '../../../../../geoms/types';
import { withContext } from '../../../../../renderers/canvas';
import { getRadians } from '../../../../../utils/common';
import { PointShape } from '../../../../../utils/themes/theme';
import { ShapeRendererFn } from '../../shapes_paths';
import { fillAndStroke } from './utils';
Expand All @@ -38,7 +39,7 @@ export function renderShape(
const [pathFn, rotation] = ShapeRendererFn[shape];
const { x, y, radius } = coordinates;
ctx.translate(x, y);
ctx.rotate((rotation * Math.PI) / 180);
ctx.rotate(getRadians(rotation));
ctx.beginPath();

const path = new Path2D(pathFn(radius));
Expand Down
Loading