react-native-ballast-charts
v1.0.0
Published
High-performance interactive charts for React Native with advanced gap handling and financial data visualization
Maintainers
Readme
React Native Ballast Charts
A high-performance, interactive chart library for React Native with advanced gap handling and financial data visualization.
Features
- 📊 Interactive Charts: Touch-responsive charts with crosshair and tooltip support
- 🎯 High Performance: Optimized for 60fps with React Native Reanimated worklets
- 📈 Smooth Curves: Multiple smoothing algorithms (Bézier, Catmull-Rom, Cardinal)
- ⏸️ Advanced Gap Handling: Both proportional and fixed-width gap visualization
- 🎨 Customizable Styling: Comprehensive theming and styling options
- 📱 React Native Optimized: Built specifically for mobile performance
Screenshots
| Line Chart | Distribution Chart |
|------------|-------------------|
|
|
|
| Interactive stock price chart with smooth curves and gap handling | Distribution visualization with optimized padding |
Installation
npm install react-native-ballast-chartsPeer Dependencies
This library requires the following peer dependencies:
npm install react-native-reanimated react-native-gesture-handler react-native-svgFollow the installation guides for each:
Quick Start
import { Chart } from 'react-native-ballast-charts';
const MyChart = () => {
const data = {
x: [1640995200000, 1641081600000, 1641168000000], // timestamps
y: [100, 120, 110] // values
};
return (
<Chart
data={data}
width={300}
height={200}
lineStyle={{
color: '#007AFF',
width: 2,
smoothing: 'bezier'
}}
/>
);
};Gap Handling
This library provides sophisticated gap handling for time series data with missing periods.
Gap Detection
Gaps are automatically detected when the time interval between consecutive data points exceeds a threshold:
<Chart
data={data}
gaps={{
enabled: true,
threshold: 2.5 // Gap detected when interval > 2.5x median interval
}}
/>Proportional Gaps (Default)
By default, gaps are rendered proportionally to their time duration:
<Chart
data={data}
gaps={{
enabled: true,
threshold: 2.5,
style: {
color: '#999',
width: 1,
dashArray: '4 4'
}
}}
/>Behavior: A 1-week gap will appear larger than a 1-day gap, proportional to their time difference.
Fixed Width Gaps
For consistent visual representation regardless of gap duration:
<Chart
data={data}
gaps={{
enabled: true,
threshold: 2.5,
fixedWidthGaps: true,
fixedWidth: 40, // All gaps appear as exactly 40px
style: {
color: '#999',
width: 1,
dashArray: '2 3'
}
}}
/>Behavior: All gaps appear as the same visual width (40px by default), regardless of their actual time duration.
How Fixed Width Gaps Work
- Gap Detection: Identifies time periods where data is missing
- Segment Division: Divides the timeline into continuous data segments separated by gaps
- Consistent Scaling: Applies uniform time-to-pixel scaling across all segments
- Fixed Gap Insertion: Inserts exactly
fixedWidthpixels between segments
Example: With a 1-week dataset containing weekend gaps:
- Proportional: Weekend gaps appear larger than weekday gaps
- Fixed Width: All gaps appear identical (e.g., 40px), maintaining visual consistency
When to Use Fixed Width Gaps
- Financial Charts: Trading hours vs. market closures
- Business Metrics: Weekdays vs. weekends
- Sensor Data: Regular maintenance periods
- Any scenario where gap duration shouldn't distort visual analysis
Gap Configuration Options
interface GapConfig {
enabled: boolean; // Enable gap detection
threshold?: number; // Gap threshold multiplier (default: 2.0)
fixedWidthGaps?: boolean; // Use fixed width gaps
fixedWidth?: number; // Fixed gap width in pixels (default: 40)
style?: {
color?: string; // Gap indicator color
width?: number; // Gap indicator line width
dashArray?: string; // Dash pattern (e.g., "4 4", "2 3")
};
}Chart Props
Core Props
interface ChartProps {
data: ChartData; // Chart data
width: number; // Chart width
height: number; // Chart height
padding?: Padding; // Chart padding
style?: ViewStyle; // Container styling
}
interface ChartData {
x: number[]; // X-axis data (usually timestamps)
y: number[]; // Y-axis data (values)
}Styling Props
interface LineStyle {
color?: string; // Line color
width?: number; // Line width
opacity?: number; // Line opacity
smoothing?: 'none' | 'bezier' | 'catmull-rom' | 'cardinal';
tension?: number; // Curve tension (0-1)
}
interface FillStyle {
enabled?: boolean; // Enable area fill
color?: string; // Fill color
opacity?: number; // Fill opacity
}Interaction Props
interface InteractionConfig {
enabled?: boolean; // Enable touch interactions
onDrag?: (x: number, y: number, index: number) => void;
onDragStart?: (x: number, y: number, index: number) => void;
onDragEnd?: (x: number, y: number, index: number) => void;
onTap?: (x: number, y: number, index: number) => void;
dragLineStyle?: LineStyle; // Crosshair styling
}Complete Example
<Chart
data={{ x: timestamps, y: prices }}
width={350}
height={200}
padding={{ top: 20, right: 20, bottom: 40, left: 60 }}
lineStyle={{
color: '#007AFF',
width: 2,
opacity: 1,
smoothing: 'bezier',
tension: 0.3
}}
fillStyle={{
enabled: true,
color: '#007AFF',
opacity: 0.1
}}
gaps={{
enabled: true,
threshold: 2.5,
fixedWidthGaps: true,
fixedWidth: 40,
style: {
color: '#999',
width: 1,
dashArray: '2 3'
}
}}
interaction={{
enabled: true,
onDrag: (x, y, index) => {
console.log('Dragging:', { x, y, index });
},
dragLineStyle: {
color: '#FF3B30',
width: 1,
opacity: 0.8
}
}}
axes={{
x: {
show: true,
style: { lineColor: '#E5E5E7', labelStyle: { color: '#8E8E93' } }
},
y: {
show: true,
style: { lineColor: '#E5E5E7', labelStyle: { color: '#8E8E93' } }
}
}}
/>Performance Considerations
- Worklet Optimization: Touch interactions run on the UI thread for 60fps performance
- Data Scaling: Coordinate calculations are memoized and optimized
- SVG Rendering: Efficient path generation with minimal DOM updates
- Memory Management: Automatic cleanup of gesture handlers and animations
TypeScript Support
The library is fully typed with comprehensive TypeScript definitions. All props, configs, and callback signatures include complete type information.
Migration Notes
From Proportional to Fixed Width Gaps
// Before (proportional gaps)
gaps={{ enabled: true, threshold: 2.5 }}
// After (fixed width gaps)
gaps={{
enabled: true,
threshold: 2.5,
fixedWidthGaps: true,
fixedWidth: 40
}}Breaking Changes
None. Fixed width gaps are an additive feature that doesn't affect existing implementations.
Troubleshooting
Gaps Not Appearing
- Verify
gaps.enabled: true - Check that
thresholdvalue is appropriate for your data intervals - Ensure data actually contains time gaps (missing periods)
Unexpected Gap Sizes
- Proportional gaps: Gap size reflects actual time duration
- Fixed width gaps: All gaps appear as
fixedWidthpixels regardless of duration
Performance Issues
- Reduce data point density for large datasets
- Consider data downsampling for initial render
- Use
React.memofor chart container components
Contributing
This library is part of the Ballast investment application. For contributions or issues, please follow the project's standard development workflow.
