mirror of
https://github.com/kevinsqi/react-circular-progressbar.git
synced 2026-01-18 15:55:06 +00:00
131 lines
3.3 KiB
TypeScript
131 lines
3.3 KiB
TypeScript
import React from 'react';
|
|
|
|
import {
|
|
VIEWBOX_WIDTH,
|
|
VIEWBOX_HEIGHT,
|
|
VIEWBOX_HEIGHT_HALF,
|
|
VIEWBOX_CENTER_X,
|
|
VIEWBOX_CENTER_Y,
|
|
} from './constants';
|
|
import Path from './Path';
|
|
import { CircularProgressbarDefaultProps, CircularProgressbarProps } from './types';
|
|
|
|
class CircularProgressbar extends React.Component<CircularProgressbarProps> {
|
|
static defaultProps: CircularProgressbarDefaultProps = {
|
|
background: false,
|
|
backgroundPadding: 0,
|
|
circleRatio: 1,
|
|
classes: {
|
|
root: 'CircularProgressbar',
|
|
trail: 'CircularProgressbar-trail',
|
|
path: 'CircularProgressbar-path',
|
|
text: 'CircularProgressbar-text',
|
|
background: 'CircularProgressbar-background',
|
|
},
|
|
counterClockwise: false,
|
|
className: '',
|
|
maxValue: 100,
|
|
minValue: 0,
|
|
strokeWidth: 8,
|
|
styles: {
|
|
root: {},
|
|
trail: {},
|
|
path: {},
|
|
text: {},
|
|
background: {},
|
|
},
|
|
text: '',
|
|
};
|
|
|
|
getBackgroundPadding() {
|
|
if (this.props.background) {
|
|
// Default padding to be the same as strokeWidth
|
|
// Compare to null because 0 is falsy
|
|
if (this.props.backgroundPadding == null) {
|
|
return this.props.strokeWidth;
|
|
}
|
|
return this.props.backgroundPadding;
|
|
}
|
|
// Don't add padding if not displaying background
|
|
return 0;
|
|
}
|
|
|
|
getPathRadius() {
|
|
// The radius of the path is defined to be in the middle, so in order for the path to
|
|
// fit perfectly inside the 100x100 viewBox, need to subtract half the strokeWidth
|
|
return VIEWBOX_HEIGHT_HALF - this.props.strokeWidth / 2 - this.getBackgroundPadding();
|
|
}
|
|
|
|
// Ratio of path length to trail length, as a value between 0 and 1
|
|
getPathRatio() {
|
|
const { value, minValue, maxValue } = this.props;
|
|
const boundedValue = Math.min(Math.max(value, minValue), maxValue);
|
|
return (boundedValue - minValue) / (maxValue - minValue);
|
|
}
|
|
|
|
render() {
|
|
const {
|
|
circleRatio,
|
|
className,
|
|
classes,
|
|
counterClockwise,
|
|
styles,
|
|
strokeWidth,
|
|
text,
|
|
} = this.props;
|
|
|
|
const pathRadius = this.getPathRadius();
|
|
const pathRatio = this.getPathRatio();
|
|
|
|
return (
|
|
<svg
|
|
className={`${classes.root} ${className}`}
|
|
style={styles.root}
|
|
viewBox={`0 0 ${VIEWBOX_WIDTH} ${VIEWBOX_HEIGHT}`}
|
|
data-test-id="CircularProgressbar"
|
|
>
|
|
{this.props.background ? (
|
|
<circle
|
|
className={classes.background}
|
|
style={styles.background}
|
|
cx={VIEWBOX_CENTER_X}
|
|
cy={VIEWBOX_CENTER_Y}
|
|
r={VIEWBOX_HEIGHT_HALF}
|
|
/>
|
|
) : null}
|
|
|
|
<Path
|
|
className={classes.trail}
|
|
counterClockwise={counterClockwise}
|
|
dashRatio={circleRatio}
|
|
pathRadius={pathRadius}
|
|
strokeWidth={strokeWidth}
|
|
style={styles.trail}
|
|
/>
|
|
|
|
<Path
|
|
className={classes.path}
|
|
counterClockwise={counterClockwise}
|
|
dashRatio={pathRatio * circleRatio}
|
|
pathRadius={pathRadius}
|
|
strokeWidth={strokeWidth}
|
|
style={styles.path}
|
|
/>
|
|
|
|
{text ? (
|
|
<text
|
|
className={classes.text}
|
|
style={styles.text}
|
|
x={VIEWBOX_CENTER_X}
|
|
y={VIEWBOX_CENTER_Y}
|
|
>
|
|
{text}
|
|
</text>
|
|
) : null}
|
|
</svg>
|
|
);
|
|
}
|
|
}
|
|
|
|
export default CircularProgressbar;
|