fleetback-react-native-progress
Version:
Progress indicators and spinners for React Native using ReactART
98 lines (86 loc) • 2.58 kB
JavaScript
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Shape as ARTShape, Path as ARTPath } from '@react-native-community/art';
const CIRCLE = Math.PI * 2;
function makeArcPath(x, y, startAngleArg, endAngleArg, radius, direction) {
let startAngle = startAngleArg;
let endAngle = endAngleArg;
if (endAngle - startAngle >= CIRCLE) {
endAngle = CIRCLE + (endAngle % CIRCLE);
} else {
endAngle = endAngle % CIRCLE;
}
startAngle = startAngle % CIRCLE;
const angle =
startAngle > endAngle
? CIRCLE - startAngle + endAngle
: endAngle - startAngle;
if (angle >= CIRCLE) {
return (new ARTPath())
.moveTo(x + radius, y)
.arc(0, radius * 2, radius, radius)
.arc(0, radius * -2, radius, radius)
.close();
}
const directionFactor = direction === 'counter-clockwise' ? -1 : 1;
endAngle *= directionFactor;
startAngle *= directionFactor;
const startSine = Math.sin(startAngle);
const startCosine = Math.cos(startAngle);
const endSine = Math.sin(endAngle);
const endCosine = Math.cos(endAngle);
const arcFlag = angle > Math.PI ? 1 : 0;
const reverseFlag = direction === 'counter-clockwise' ? 0 : 1;
return `M${x + radius * (1 + startSine)} ${y + radius - radius * startCosine}
A${radius} ${radius} 0 ${arcFlag} ${reverseFlag} ${x +
radius * (1 + endSine)} ${y + radius - radius * endCosine}`;
}
export default class Arc extends Component {
static propTypes = {
startAngle: PropTypes.number.isRequired, // in radians
endAngle: PropTypes.number.isRequired, // in radians
radius: PropTypes.number.isRequired,
offset: PropTypes.shape({
top: PropTypes.number,
left: PropTypes.number,
}),
strokeCap: PropTypes.string,
strokeWidth: PropTypes.number,
direction: PropTypes.oneOf(['clockwise', 'counter-clockwise']),
};
static defaultProps = {
startAngle: 0,
offset: { top: 0, left: 0 },
strokeCap: 'butt',
strokeWidth: 0,
direction: 'clockwise',
};
render() {
const {
startAngle,
endAngle,
radius,
offset,
direction,
strokeCap,
strokeWidth,
...restProps
} = this.props;
const path = makeArcPath(
(offset.left || 0) + strokeWidth / 2,
(offset.top || 0) + strokeWidth / 2,
startAngle,
endAngle,
radius - strokeWidth / 2,
direction
);
return (
<ARTShape
d={path}
strokeCap={strokeCap}
strokeWidth={strokeWidth}
{...restProps}
/>
);
}
}