Skip to content

Commit 700f976

Browse files
committed
Do not unnessarily call getComputedStyles() if component does not use classes
1 parent 6a3a4ac commit 700f976

1 file changed

Lines changed: 33 additions & 24 deletions

File tree

packages/layerchart/src/lib/utils/canvas.ts

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@ export const DEFAULT_FILL = 'rgb(0, 0, 0)';
77

88
const CANVAS_STYLES_ELEMENT_ID = '__layerchart_canvas_styles_id';
99

10+
type StyleOptions = Partial<
11+
Omit<CSSStyleDeclaration, 'fillOpacity' | 'strokeWidth' | 'opacity'> & {
12+
fillOpacity?: number | string;
13+
strokeWidth?: number | string;
14+
opacity?: number | string;
15+
}
16+
>;
17+
1018
export type ComputedStylesOptions = {
11-
styles?: Partial<
12-
Omit<CSSStyleDeclaration, 'fillOpacity' | 'strokeWidth' | 'opacity'> & {
13-
fillOpacity?: number | string;
14-
strokeWidth?: number | string;
15-
opacity?: number | string;
16-
}
17-
>;
19+
styles?: StyleOptions;
1820
classes?: ClassValue | null;
1921
};
2022

@@ -79,26 +81,33 @@ function render(
7981
// console.count('render');
8082

8183
// TODO: Consider memoizing? How about reactiving to CSS variable changes (light/dark mode toggle)
82-
const computedStyles = getComputedStyles(ctx.canvas, styleOptions);
84+
let resolvedStyles: StyleOptions;
85+
if (styleOptions.classes == null) {
86+
// Skip resolving styles if no classes are provided
87+
resolvedStyles = styleOptions.styles ?? {};
88+
} else {
89+
const computedStyles = getComputedStyles(ctx.canvas, styleOptions);
90+
resolvedStyles = computedStyles;
91+
}
8392

8493
// Adhere to CSS paint order: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order
8594
const paintOrder =
86-
computedStyles?.paintOrder === 'stroke' ? ['stroke', 'fill'] : ['fill', 'stroke'];
95+
resolvedStyles?.paintOrder === 'stroke' ? ['stroke', 'fill'] : ['fill', 'stroke'];
8796

88-
if (computedStyles?.opacity) {
89-
ctx.globalAlpha = Number(computedStyles?.opacity);
97+
if (resolvedStyles?.opacity) {
98+
ctx.globalAlpha = Number(resolvedStyles?.opacity);
9099
}
91100

92101
// Text properties
93-
ctx.font = `${computedStyles.fontWeight} ${computedStyles.fontSize} ${computedStyles.fontFamily}`; // build string instead of using `computedStyles.font` to fix/workaround `tabular-nums` returning `null`
102+
ctx.font = `${resolvedStyles.fontWeight} ${resolvedStyles.fontSize} ${resolvedStyles.fontFamily}`; // build string instead of using `computedStyles.font` to fix/workaround `tabular-nums` returning `null`
94103

95104
// TODO: Hack to handle `textAnchor` with canvas. Try to find a better approach
96-
if (computedStyles.textAnchor === 'middle') {
105+
if (resolvedStyles.textAnchor === 'middle') {
97106
ctx.textAlign = 'center';
98-
} else if (computedStyles.textAnchor === 'end') {
107+
} else if (resolvedStyles.textAnchor === 'end') {
99108
ctx.textAlign = 'right';
100109
} else {
101-
ctx.textAlign = computedStyles.textAlign as CanvasTextAlign; // TODO: Handle/map `justify` and `match-parent`?
110+
ctx.textAlign = resolvedStyles.textAlign as CanvasTextAlign; // TODO: Handle/map `justify` and `match-parent`?
102111
}
103112

104113
// TODO: Handle `textBaseline` / `verticalAnchor` (Text)
@@ -110,8 +119,8 @@ function render(
110119
// ctx.textBaseline = 'ideographic';
111120

112121
// Dashed lines
113-
if (computedStyles.strokeDasharray.includes(',')) {
114-
const dashArray = computedStyles.strokeDasharray
122+
if (resolvedStyles.strokeDasharray?.includes(',')) {
123+
const dashArray = resolvedStyles.strokeDasharray
115124
.split(',')
116125
.map((s) => Number(s.replace('px', '')));
117126
ctx.setLineDash(dashArray);
@@ -125,13 +134,13 @@ function render(
125134
(styleOptions.styles?.fill as any) instanceof CanvasPattern ||
126135
!styleOptions.styles?.fill?.includes('var'))
127136
? styleOptions.styles.fill
128-
: computedStyles?.fill;
137+
: resolvedStyles?.fill;
129138

130139
if (fill && !['none', DEFAULT_FILL].includes(fill)) {
131140
const currentGlobalAlpha = ctx.globalAlpha;
132141

133-
const fillOpacity = Number(computedStyles?.fillOpacity);
134-
const opacity = Number(computedStyles?.opacity);
142+
const fillOpacity = Number(resolvedStyles?.fillOpacity);
143+
const opacity = Number(resolvedStyles?.opacity);
135144
ctx.globalAlpha = fillOpacity * opacity;
136145

137146
ctx.fillStyle = fill;
@@ -146,13 +155,13 @@ function render(
146155
((styleOptions.styles?.stroke as any) instanceof CanvasGradient ||
147156
!styleOptions.styles?.stroke?.includes('var'))
148157
? styleOptions.styles?.stroke
149-
: computedStyles?.stroke;
158+
: resolvedStyles?.stroke;
150159

151160
if (stroke && !['none'].includes(stroke)) {
152161
ctx.lineWidth =
153-
typeof computedStyles?.strokeWidth === 'string'
154-
? Number(computedStyles?.strokeWidth?.replace('px', ''))
155-
: (computedStyles?.strokeWidth ?? 1);
162+
typeof resolvedStyles?.strokeWidth === 'string'
163+
? Number(resolvedStyles?.strokeWidth?.replace('px', ''))
164+
: (resolvedStyles?.strokeWidth ?? 1);
156165

157166
ctx.strokeStyle = stroke;
158167
render.stroke(ctx);

0 commit comments

Comments
 (0)