Creating a Circular File Download Progress Bar using SVG in React Native
Introduction: In this blog, we will learn how to create a circular download progress bar using Vector Graphics (G) in a React Native application. This progress bar can be used to show the progress of a file download in a visually appealing way.
Prerequisites:
- Basic understanding of React Native
- Familiarity with SVG
SVG Circular Progress Bar: SVG provides a powerful way to create vector-based graphics that can be scaled without losing quality. In this example, we will create a circular progress bar using SVG circles and paths.
The basic structure of the SVG component is as follows:
<Svg width={size} height={size}>
{/* Background Circle */}
<Circle
stroke="#D9D9D9"
fill="none"
cx={size / 2}
cy={size / 2}
r={radius}
strokeWidth={strokeWidth}
/>
{/* Progress Circle */}
<Circle
stroke="#00C282"
fill="none"
cx={size / 2}
cy={size / 2}
r={radius}
strokeDasharray={`${circum} ${circum}`}
strokeDashoffset={radius * Math.PI * 2 * (svgProgress / 100)}
strokeLinecap="round"
transform={`rotate(-90, ${size / 2}, ${size / 2})`}
strokeWidth={strokeWidth}
/>
</Svg>Here, we have two circles — one for the background and one for the progress. The background circle is filled with a light gray color, while the progress circle is filled with a green color.

The strokeDasharray and strokeDashoffset properties are used to create the progress effect. The strokeDasharray property defines the pattern of dashes and gaps used to stroke paths, while the strokeDashoffset property defines the distance into the dash pattern to start the stroke.
By adjusting the strokeDashoffset property based on the progress value, we can create the illusion of a progress bar.
Adding File Download Progress: To add file download progress to the progress bar, we need to update the strokeDashoffset property based on the progress value.
For example, if the progress value is 50, we can calculate the strokeDashoffset value as follows:
const strokeDashoffset = radius * Math.PI * 2 * (50 / 100);
We can then pass this value to the strokeDashoffset property of the progress circle.
<Circle stroke=”#217CF5" … strokeDashoffset={strokeDashoffset} … />
import React, { useEffect } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import RNFS from 'react-native-fs';
import { Alert } from 'react-native';
import {Svg, Circle, Path} from 'react-native-svg';
const FileDownloadDemo = () => {
const [percentage, setPercentage] = React.useState<number>(0);
const size = 100;
const strokeWidth = 7;
const radius = (size - strokeWidth) / 2;
const circum = radius * 2 * Math.PI;
const svgProgress = 100 - percentage;
const downloadFileBegin = () => {
console.log('Download Begin');
};
const downloadFileProgress = (data: any) => {
console.log('data',data,((100 * data.bytesWritten) / data.contentLength));
setPercentage(((100 * data.bytesWritten) / data.contentLength) | 0);
console.log('$$$$$$$$$$', percentage);
};
const handleDownload = async () => {
try {
const downloadPath = RNFS.DownloadDirectoryPath + '/sample-image.jpg';
RNFS.downloadFile({
begin: downloadFileBegin,
progress: downloadFileProgress,
fromUrl: 'https://images.unsplash.com/photo-1702579454504-999228374c5e?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxfDB8MXxyYW5kb218MHx8fHx8fHx8MTcwNDYxODMyOQ&ixlib=rb-4.0.3&q=80&w=1080',
toFile: downloadPath,
})
.promise.then((result) => {
console.log('Download successful:', result);
setPercentage(100);
// Alert.alert('File downloaded successfully');
})
.catch((error) => {
console.log('Failed to download file:', error);
// Alert.alert('File download failed');
});
} catch (error) {
console.log('FILE DOWNLOAD FAILED:', error);
Alert.alert('Download failed', 'There was an error while downloading the image.');
}
};
useEffect(() => {
// Optional: Perform any cleanup or additional logic after the download
return () => {
console.log('Component will unmount. Clean up if needed.');
};
}, []);
return (
<View style={{flex:1,justifyContent:'center',alignItems:'center'}}>
<View style={{paddingBottom:30}}>
<TouchableOpacity onPress={handleDownload} >
<Text >Start Download</Text>
</TouchableOpacity>
</View>
<Svg width={size} height={size}>
{/* Background Circle */}
<Circle
stroke="#D9D9D9"
fill="none"
cx={size / 2}
cy={size / 2}
r={radius}
strokeWidth={strokeWidth}
/>
{/* Progress Circle */}
<Circle
stroke="#00C282"
fill="none"
cx={size / 2}
cy={size / 2}
r={radius}
strokeDasharray={`${circum} ${circum}`}
strokeDashoffset={radius * Math.PI * 2 * (svgProgress / 100)}
strokeLinecap="round"
transform={`rotate(-90, ${size / 2}, ${size / 2})`}
strokeWidth={strokeWidth}
/>
</Svg>
</View>
);
};
export default FileDownloadDemo;Conclusion: In this blog, we learned how to create a circular file download progress bar using SVG in a React Native application. By using SVG circles and paths, we can create a visually appealing progress bar that can be scaled without losing quality. By updating the strokeDashoffset property based on the progress value, we can create the illusion of a progress bar.
“Unlock a World of Knowledge and Fun — Subscribe Now and Join the UNBOX Community!”
Comments
Post a Comment