
Vertical Step indicator
May 06, 2023
1 min
React Native component for creating animated, circular progress. Useful for displaying users points for example.
You can configure the CircularProgress-component by passing the following props:
Name | Type | Default value | Description |
---|---|---|---|
size | number|Animated.Value | required | Width and height of circle |
width | number | required | Thickness of the progress line |
backgroundWidth | number | width | Thickness of background circle |
fill | number (0-100) | 0 | Current progress / fill |
tintColor | string | black | Color of the progress line |
tintTransparency | boolean | true | Transparency of the progress line |
backgroundColor | string | If unspecified, no background line will be rendered | |
rotation | number (-360 - 360) | 90 | Angle from which the progress starts from |
lineCap | string | butt | Shape used at ends of progress line. Possible values: butt, round, square |
arcSweepAngle | number (0-360) | 360 | If you don’t want a full circle, specify the arc angle |
style | ViewPropTypes.style | Extra styling for the main container | |
children | function | Pass a function as a child. It received the current fill-value as an argument | |
childrenContainerStyle | ViewPropTypes.style | Extra styling for the children container | |
padding | number | 0 | Padding applied around the circle to allow for a cap that bleeds outside its boundary |
dashedBackground | object | { width: 0, gap: 0 } | Bar background as dashed type |
dashedTint | object | { width: 0, gap: 0 } | Bar tint as dashed type |
renderCap | function | undefined | Function that’s invoked during rendering to draw at the tip of the progress circle |
The following props can further be used on AnimatedCircularProgress
:
Name | Type | Default value | Description |
---|---|---|---|
prefill | number (0-100) | 0 | Initial fill-value before animation starts |
duration | number | 500 | Duration of animation in ms |
delay | number | 0 | Delay of animation in ms |
easing | function | Easing.out(Easing.ease) | Animation easing function |
onAnimationComplete | function | Function that’s invoked when the animation completes (both on mount and if called with .animate() ) | |
onFillChange | function | Function that returns current progress on every change | |
tintColorSecondary | string | the same as tintColor | To change fill color from tintColor to tintColorSecondary as animation progresses |
AnimatedCircularProgress
also exposes the following functions:
Name | Arguments | Description |
---|---|---|
animate | (toVal: number, duration: number, ease: function) | Animate the progress bar to a specific value |
reAnimate | (prefill: number, toVal: number, duration: number, ease: function) | Re-run animation with a specified prefill-value |
Install this component and react-native-svg
:
npm i --save react-native-circular-progress react-native-svg
Link native code for SVG:
react-native link react-native-svg
import React from 'react';import { StyleSheet, Text, PanResponder, View, PanResponderInstance } from 'react-native';import { AnimatedCircularProgress } from 'react-native-circular-progress';const MAX_POINTS = 500;export default class App extends React.Component {state = {isMoving: false,pointsDelta: 0,points: 325,};_panResponder : PanResponderInstance;_circularProgressRef: React.RefObject<AnimatedCircularProgress>;constructor(props: Readonly<{}>) {super(props);this._circularProgressRef = React.createRef();this._panResponder = PanResponder.create({onStartShouldSetPanResponder: (evt, gestureState) => true,onStartShouldSetPanResponderCapture: (evt, gestureState) => true,onMoveShouldSetPanResponder: (evt, gestureState) => true,onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,onPanResponderGrant: (evt, gestureState) => {this.setState({ isMoving: true, pointsDelta: 0 });},onPanResponderMove: (evt, gestureState) => {if (this._circularProgressRef.current) {this._circularProgressRef.current.animate(0, 0);}// For each 2 pixels add or subtract 1 pointthis.setState({ pointsDelta: Math.round(-gestureState.dy / 2) });},onPanResponderTerminationRequest: (evt, gestureState) => true,onPanResponderRelease: (evt, gestureState) => {if (this._circularProgressRef.current) {this._circularProgressRef.current.animate(100, 3000);}let points = this.state.points + this.state.pointsDelta;console.log(Math.min(points, MAX_POINTS));this.setState({isMoving: false,points: points > 0 ? Math.min(points, MAX_POINTS) : 0,pointsDelta: 0,});},});}render() {const fill = (this.state.points / MAX_POINTS) * 100;return (<View style={styles.container} {...this._panResponder.panHandlers}><AnimatedCircularProgresssize={200}width={3}backgroundWidth={30}fill={fill}tintColor="#00e0ff"backgroundColor="#3d5875">{fill => <Text style={styles.points}>{Math.round((MAX_POINTS * fill) / 100)}</Text>}</AnimatedCircularProgress><AnimatedCircularProgresssize={120}width={15}backgroundWidth={5}fill={fill}tintColor="#00ff00"tintColorSecondary="#ff0000"backgroundColor="#3d5875"arcSweepAngle={240}rotation={240}lineCap="round"/><AnimatedCircularProgresssize={100}width={25}fill={0}tintColor="#00e0ff"onAnimationComplete={() => console.log('onAnimationComplete')}ref={this._circularProgressRef}backgroundColor="#3d5875"arcSweepAngle={180}/><Text style={[styles.pointsDelta, this.state.isMoving && styles.pointsDeltaActive]}>{this.state.pointsDelta >= 0 && '+'}{this.state.pointsDelta}</Text></View>);}}const styles = StyleSheet.create({points: {textAlign: 'center',color: '#7591af',fontSize: 50,fontWeight: '100',},container: {flex: 1,justifyContent: 'space-between',alignItems: 'center',backgroundColor: '#152d44',padding: 50,},pointsDelta: {color: '#4c6479',fontSize: 50,fontWeight: '100',},pointsDeltaActive: {color: '#fff',},});
Coming Soon…
Quick Links
Legal Stuff