Back to Components

Donut Chart

Charts & Rings
7 months ago

About

DonutChart Component

A reusable, animated donut chart component for React Native with smooth spring animations and configurable gap spacing.

Features

  • Smooth Animations - Spring-based animations with configurable delays
  • 📊 Gap Spacing - Configurable gaps between chart segments
  • 🎨 Customizable Colors - Each segment can have its own color
  • 📱 Responsive - Works on all screen sizes
  • 🎯 TypeScript Support - Full type safety with interfaces
  • Performance Optimized - Uses React Native Reanimated for 60fps

Usage

Basic Example

typescript
import { DonutChart } from '@/components/donut-chart'; const categories = [ { id: 'category-1', name: 'CATEGORY 1', value: 100, percentage: 50, color: '#FF9500', }, { id: 'category-2', name: 'CATEGORY 2', value: 50, percentage: 25, color: '#FFCC00', }, ]; <DonutChart categories={categories} sizeConfig={{ size: 280, strokeWidth: 20, gapSize: 12, }} animationDelay={200} />

With Custom Sizing

typescript
<DonutChart categories={data} sizeConfig={{ size: 200, // Smaller chart strokeWidth: 15, // Thinner stroke gapSize: 8, // Smaller gaps }} animationDelay={0} // No delay disableAnimation={false} />

Props

DonutChart Props

PropTypeRequiredDefaultDescription
categoriesChartCategory[]-Array of data categories
sizeConfigSizeConfig{ size: 280, strokeWidth: 20, gapSize: 12 }Chart sizing configuration
animationDelaynumber0Delay before animation starts (ms)
disableAnimationbooleanfalseDisable all animations

ChartCategory

PropertyTypeRequiredDescription
idstringUnique identifier for the category
namestringDisplay name for the category
valuenumberNumerical value for the category
percentagenumberPercentage of total (0-100)
colorstringHex color for chart segment
iconkeyof typeof Ionicons.glyphMapIonicons icon name (optional)

SizeConfig

PropertyTypeRequiredDefaultDescription
sizenumber280Chart diameter in pixels
strokeWidthnumber20Stroke width of chart segments
gapSizenumber12Gap size in degrees between segments

Chart Features

Gap Spacing

  • Default Gap: 12 degrees between segments
  • Configurable: Can be adjusted via sizeConfig.gapSize
  • Automatic Adjustment: Segments are proportionally reduced to accommodate gaps

Animation

  • Spring Physics: Uses damping: 15, stiffness: 100 for initial animation
  • Staggered Animation: 100ms delay between each category
  • Smart Updates: Smooth transitions when data changes
  • Disable Option: Can turn off animations completely

Sizing

  • Diameter: Configurable via sizeConfig.size
  • Stroke Width: Configurable via sizeConfig.strokeWidth
  • Responsive: Automatically scales to container

Examples

You can play with gap size and animation delay to get the desired effect. You can also use the disableAnimation prop to turn off animations completely. Gap size is automatically adjusted to accommodate the gap size between segments.

Small Chart

typescript
<DonutChart categories={smallData} sizeConfig={{ size: 150, strokeWidth: 12, gapSize: 8, }} animationDelay={100} />

Large Chart

typescript
<DonutChart categories={largeData} sizeConfig={{ size: 400, strokeWidth: 25, gapSize: 15, }} animationDelay={300} />

Static Chart (No Animation)

typescript
<DonutChart categories={staticData} sizeConfig={{ size: 280, strokeWidth: 20, gapSize: 12, }} disableAnimation={true} />

Complete Demo Example

typescript
import { DonutChart } from '@/components/charts/donut-chart'; const sampleCategories = [ { id: 'claude-4-sonnet', name: 'CLAUDE-4-SONNET', value: 117.89, percentage: 73, color: '#FF9500', }, { id: 'claude-4-opus', name: 'CLAUDE-4-OPUS', value: 35.54, percentage: 22, color: '#FFCC00', }, { id: 'auto', name: 'AUTO', value: 4.93, percentage: 3, color: '#8E8E93', }, ]; export const DonutChartDemo = () => { const totalValue = sampleCategories.reduce((sum, category) => sum + category.value, 0); return ( <View style={styles.chartContainer}> <View style={styles.chartWrapper}> <DonutChart categories={sampleCategories} sizeConfig={{ size: 280, strokeWidth: 20, gapSize: 12, }} animationDelay={1000} disableAnimation={false} /> <View style={styles.chartCenter}> <Text style={styles.totalValue}>{totalValue.toFixed(2)}</Text> <Text style={styles.totalUnit}>USD</Text> </View> </View> </View> ); };

Dependencies

  • react-native-reanimated: For smooth animations
  • react-native-svg: For SVG chart rendering
  • @expo/vector-icons: For optional icon support

Performance

  • 60fps Animations: Uses shared values for optimal performance
  • Efficient Rendering: SVG-based with minimal re-renders
  • Memory Management: Proper cleanup of animated values
  • Optimized Calculations: Pre-calculated values for smooth updates

Customization

Custom Gap Size

To change the gap between segments, use the sizeConfig.gapSize prop:

typescript
<DonutChart categories={data} sizeConfig={{ size: 280, strokeWidth: 20, gapSize: 8, // Smaller gaps }} />

Custom Animation Timing

The spring configuration can be modified in the component:

typescript
// Faster animations const SPRING_CONFIG = { damping: 10, stiffness: 150, }; // Slower animations const SPRING_CONFIG = { damping: 25, stiffness: 80, };

Posted by

E

eren

@eren