Skip to content

Commit 8ce906e

Browse files
committed
Allow the component to take relative values for width and height.
1 parent e0e9bc8 commit 8ce906e

File tree

2 files changed

+52
-43
lines changed

2 files changed

+52
-43
lines changed

src/index.js

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ import { CanvasRenderer } from './renderers/';
66
type fillStyle = string | CanvasGradient | CanvasPattern;
77

88
type Props = {
9-
/** The width of the canvas element, in pixels */
10-
width: number,
11-
/** The height of the canvas element, in pixels */
12-
height: number,
9+
/** The CSS width of the element */
10+
width: number | string,
11+
/** The CSS height of the element */
12+
height: number | string,
1313
/** The total number of steps to complete the ring */
1414
steps: number,
1515
/** The current step */
@@ -154,36 +154,42 @@ export class RadialProgress extends React.Component<Props, State> {
154154
);
155155
};
156156
const label = (steps, proportion) => {
157-
return (
158-
<div
159-
className="RadialProgressIndicator__label"
160-
style={{
161-
position: 'absolute',
162-
top: 0,
163-
left: 0,
164-
width: this.props.width,
165-
height: this.props.height,
166-
lineHeight: `${this.props.height}px`,
167-
textAlign: 'center',
168-
fontSize: `${this.props.height / 4}px`,
169-
color: this.props.ringFgColour,
170-
}}
171-
>
172-
{this.props.text(steps, proportion)}
173-
</div>
174-
);
157+
if (this.graphic && this.graphic.canvas) {
158+
const rect = this.graphic.canvas.getBoundingClientRect();
159+
const diameter = Math.min(rect.height, rect.width);
160+
const style = {
161+
position: 'absolute',
162+
textAlign: 'center',
163+
color: this.props.ringFgColour,
164+
fontSize: `${diameter / 4}px`,
165+
};
166+
return (
167+
<div className="RadialProgressIndicator__label" style={style}>
168+
{this.props.text(steps, proportion)}
169+
</div>
170+
);
171+
}
172+
return null;
175173
};
176174
const startProportion = this.props.startStep / this.props.steps;
177175
const endProportion = this.props.step / this.props.steps;
178176
const proportion =
179177
startProportion +
180178
(endProportion - startProportion) * this.getProportion();
181179
return (
182-
<div className="RadialProgressIndicator" style={{ position: 'relative' }}>
180+
<div
181+
className="RadialProgressIndicator"
182+
style={{
183+
position: 'relative',
184+
width: this.props.width,
185+
height: this.props.height,
186+
display: 'flex',
187+
justifyContent: 'center',
188+
alignItems: 'center',
189+
}}
190+
>
183191
<CanvasRenderer
184192
ref={ref => (this.graphic = ref)}
185-
width={this.props.width}
186-
height={this.props.height}
187193
proportion={proportion}
188194
showIntermediateProgress={this.props.showIntermediateProgress}
189195
segmented={this.props.segmented}

src/renderers/index.js

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ type fillStyle = string | CanvasGradient | CanvasPattern;
99
type Props = {
1010
backgroundColour: fillStyle,
1111
backgroundTransparent: boolean,
12-
height: number,
1312
proportion: number,
1413
ringBgColour: fillStyle,
1514
ringFgColour: fillStyle,
@@ -18,14 +17,12 @@ type Props = {
1817
showIntermediateProgress: boolean,
1918
segmented: boolean,
2019
steps: number,
21-
width: number,
2220
};
2321

2422
export class CanvasRenderer extends React.Component<Props> {
2523
static defaultProps = {
2624
backgroundColour: '#fff',
2725
backgroundTransparent: true,
28-
height: 100,
2926
proportion: 0,
3027
ringBgColour: '#ccc',
3128
ringFgColour: '#3c763d',
@@ -34,32 +31,38 @@ export class CanvasRenderer extends React.Component<Props> {
3431
showIntermediateProgress: false,
3532
segmented: true,
3633
steps: 360,
37-
width: 100,
3834
};
3935

4036
ctx: CanvasRenderingContext2D;
4137

4238
canvas: HTMLCanvasElement | null;
4339

4440
componentDidMount = () => {
45-
if (this.canvas) {
46-
this.ctx = getCanvasContext(this.canvas);
47-
this.draw();
41+
if (this.canvas !== null) {
42+
// Assign canvas to local variable to work around a flow refinement invalidation.
43+
// https://flow.org/en/docs/lang/refinements/#toc-refinement-invalidations
44+
const canvas = this.canvas;
45+
this.ctx = getCanvasContext(canvas);
46+
this.draw(canvas);
4847
}
4948
};
5049

51-
componentDidUpdate() {
52-
if (this.canvas) {
53-
this.draw();
50+
componentDidUpdate = () => {
51+
if (this.canvas !== null) {
52+
this.draw(this.canvas);
5453
}
55-
}
54+
};
55+
56+
draw = (canvasElement: HTMLCanvasElement) => {
57+
const rect = canvasElement.getBoundingClientRect();
58+
const width = rect.width;
59+
const height = rect.height;
5660

57-
draw = () => {
58-
const x = this.props.width * 0.5;
59-
const y = this.props.height * 0.5;
61+
const x = width * 0.5;
62+
const y = height * 0.5;
6063

6164
const radius = radiusProportion => {
62-
return (this.props.width / 2) * radiusProportion;
65+
return (Math.min(width, height) / 2) * radiusProportion;
6366
};
6467

6568
const step = Math.floor(this.props.steps * this.props.proportion);
@@ -69,7 +72,7 @@ export class CanvasRenderer extends React.Component<Props> {
6972
const stepDegree = (360 / this.props.steps) * step;
7073

7174
// Clear the canvas
72-
this.ctx.clearRect(0, 0, this.props.width, this.props.height);
75+
this.ctx.clearRect(0, 0, width, height);
7376

7477
// Draw the background circle
7578
drawSegment(this.ctx, x, y, radius(1), 0, 360);
@@ -128,8 +131,8 @@ export class CanvasRenderer extends React.Component<Props> {
128131
<canvas
129132
ref={ref => (this.canvas = ref)}
130133
style={{
131-
width: this.props.width,
132-
height: this.props.height,
134+
width: '100%',
135+
height: '100%',
133136
}}
134137
/>
135138
);

0 commit comments

Comments
 (0)