Add ability to render a custom cap over the progress circle

Adds two new props

* padding - adds space around the circle to allow for a cap that bleeds over without clipping
* renderCap - a function that returns the Svg component to draw
This commit is contained in:
Alec Winograd 2019-09-13 16:39:14 -05:00
parent 9bfb51e5be
commit 5a11d0ea4f
2 changed files with 43 additions and 10 deletions

16
index.d.ts vendored
View File

@ -129,6 +129,22 @@ declare module 'react-native-circular-progress' {
*
*/
onAnimationComplete?: (event: { finished: boolean }) => void;
/**
* Padding applied around the circle to allow for a cap that bleeds outside its boundary
*
* @type {number}
* @default 0
*/
padding?: number;
/**
* Function that's invoked during rendering to draw at the tip of the progress circle
*
*/
renderCap?: (payload: {
center: { x: number; y: number };
}) => React.ReactNode;
}
export class AnimatedCircularProgress extends React.Component<

View File

@ -36,31 +36,44 @@ export default class CircularProgress extends React.PureComponent {
fill,
children,
childrenContainerStyle,
padding,
renderCap,
} = this.props;
const maxWidthCircle = backgroundWidth ? Math.max(width, backgroundWidth) : width;
const sizeWithPadding = size / 2 + padding / 2;
const radius = size / 2 - maxWidthCircle / 2 - padding / 2;
const backgroundPath = this.circlePath(
size / 2,
size / 2,
size / 2 - maxWidthCircle / 2,
sizeWithPadding,
sizeWithPadding,
radius,
0,
arcSweepAngle
);
const currentFillAngle = (arcSweepAngle * this.clampFill(fill)) / 100;
const circlePath = this.circlePath(
size / 2,
size / 2,
size / 2 - maxWidthCircle / 2,
sizeWithPadding,
sizeWithPadding,
radius,
0,
(arcSweepAngle * this.clampFill(fill)) / 100
currentFillAngle
);
const coordinate = this.polarToCartesian(
sizeWithPadding,
sizeWithPadding,
radius,
currentFillAngle
);
const cap = this.props.renderCap ? this.props.renderCap({ center: coordinate }) : null;
const offset = size - maxWidthCircle * 2;
const localChildrenContainerStyle = {
...{
position: 'absolute',
left: maxWidthCircle,
top: maxWidthCircle,
left: maxWidthCircle + padding / 2,
top: maxWidthCircle + padding / 2,
width: offset,
height: offset,
borderRadius: offset / 2,
@ -73,7 +86,7 @@ export default class CircularProgress extends React.PureComponent {
return (
<View style={style}>
<Svg width={size} height={size} style={{ backgroundColor: 'transparent' }}>
<Svg width={size + padding} height={size + padding}>
<G rotation={rotation} originX={size / 2} originY={size / 2}>
{backgroundColor && (
<Path
@ -93,6 +106,7 @@ export default class CircularProgress extends React.PureComponent {
fill="transparent"
/>
)}
{cap}
</G>
</Svg>
{children && <View style={localChildrenContainerStyle}>{children(fill)}</View>}
@ -114,6 +128,8 @@ CircularProgress.propTypes = {
arcSweepAngle: PropTypes.number,
children: PropTypes.func,
childrenContainerStyle: ViewPropTypes.style,
padding: PropTypes.number,
renderCap: PropTypes.func,
};
CircularProgress.defaultProps = {
@ -121,4 +137,5 @@ CircularProgress.defaultProps = {
rotation: 90,
lineCap: 'butt',
arcSweepAngle: 360,
paddinig: 0,
};