|
| 1 | +# RLAreaChart |
| 2 | + |
| 3 | + |
| 4 | + |
| 5 | +A versatile area chart for raylib supporting overlapped, stacked, and 100% stacked visualization modes with smooth animations. |
| 6 | + |
| 7 | +## Features |
| 8 | + |
| 9 | +- Three visualization modes (Overlapped, Stacked, Percent) |
| 10 | +- Smooth data transitions with configurable animation speed |
| 11 | +- Multiple series support with individual colors and opacity |
| 12 | +- Customizable grid, axes, and labels |
| 13 | +- Legend display |
| 14 | +- X-axis label support |
| 15 | + |
| 16 | +## Constructor |
| 17 | + |
| 18 | +```cpp |
| 19 | +RLAreaChart(Rectangle aBounds, RLAreaChartMode aMode = RLAreaChartMode::STACKED, |
| 20 | + const RLAreaChartStyle& rStyle = {}); |
| 21 | +``` |
| 22 | +
|
| 23 | +**Parameters:** |
| 24 | +- `aBounds` - The rectangle defining the chart's position and size |
| 25 | +- `aMode` - Visualization mode (OVERLAPPED, STACKED, or PERCENT) |
| 26 | +- `rStyle` - Optional style configuration |
| 27 | +
|
| 28 | +## Chart Modes |
| 29 | +
|
| 30 | +```cpp |
| 31 | +enum class RLAreaChartMode { |
| 32 | + OVERLAPPED, // Areas overlap with transparency showing layering |
| 33 | + STACKED, // Areas stack on top of each other |
| 34 | + PERCENT // 100% stacked (normalized to percentage) |
| 35 | +}; |
| 36 | +``` |
| 37 | + |
| 38 | +### Mode Descriptions |
| 39 | + |
| 40 | +| Mode | Description | Use Case | |
| 41 | +|------|-------------|----------| |
| 42 | +| `OVERLAPPED` | Series overlap with transparency | Comparing trends across series | |
| 43 | +| `STACKED` | Series stack vertically | Showing cumulative totals | |
| 44 | +| `PERCENT` | Normalized to 100% | Showing proportions over time | |
| 45 | + |
| 46 | +## Data Structures |
| 47 | + |
| 48 | +### Series Data |
| 49 | + |
| 50 | +```cpp |
| 51 | +struct RLAreaSeries { |
| 52 | + std::vector<float> mValues; // Data points |
| 53 | + Color mColor{80, 180, 255, 255}; // Series color |
| 54 | + std::string mLabel; // Legend label |
| 55 | + float mAlpha{0.6f}; // Fill opacity (0.0 - 1.0) |
| 56 | +}; |
| 57 | +``` |
| 58 | +
|
| 59 | +## Style Configuration |
| 60 | +
|
| 61 | +```cpp |
| 62 | +struct RLAreaChartStyle { |
| 63 | + // Background and grid |
| 64 | + bool mShowBackground{true}; |
| 65 | + Color mBackground{20, 22, 28, 255}; |
| 66 | + bool mShowGrid{true}; |
| 67 | + Color mGridColor{40, 44, 52, 255}; |
| 68 | + int mGridLines{5}; |
| 69 | +
|
| 70 | + // Axes |
| 71 | + Color mAxisColor{180, 180, 180, 255}; |
| 72 | + Color mLabelColor{200, 200, 200, 255}; |
| 73 | +
|
| 74 | + // Chart area |
| 75 | + float mPadding{40.0f}; |
| 76 | + float mLineThickness{2.0f}; |
| 77 | + bool mShowPoints{false}; |
| 78 | + float mPointRadius{4.0f}; |
| 79 | +
|
| 80 | + // Labels |
| 81 | + bool mShowLabels{true}; |
| 82 | + Font mLabelFont{}; |
| 83 | + int mLabelFontSize{12}; |
| 84 | +
|
| 85 | + // Legend |
| 86 | + bool mShowLegend{true}; |
| 87 | +
|
| 88 | + // Animation |
| 89 | + bool mSmoothAnimate{true}; |
| 90 | + float mAnimateSpeed{6.0f}; |
| 91 | +}; |
| 92 | +``` |
| 93 | + |
| 94 | +## Methods |
| 95 | + |
| 96 | +### Configuration |
| 97 | + |
| 98 | +| Method | Description | |
| 99 | +|--------|-------------| |
| 100 | +| `setBounds(Rectangle aBounds)` | Set the chart bounds | |
| 101 | +| `setMode(RLAreaChartMode aMode)` | Change visualization mode | |
| 102 | +| `setStyle(const RLAreaChartStyle& rStyle)` | Apply a style configuration | |
| 103 | +| `setXLabels(const std::vector<std::string>& rLabels)` | Set X-axis labels | |
| 104 | + |
| 105 | +### Data Management |
| 106 | + |
| 107 | +| Method | Description | |
| 108 | +|--------|-------------| |
| 109 | +| `setData(const std::vector<RLAreaSeries>& rSeries)` | Set data (immediate with entry animation) | |
| 110 | +| `setTargetData(const std::vector<RLAreaSeries>& rSeries)` | Set target data (smooth transition) | |
| 111 | + |
| 112 | +### Rendering |
| 113 | + |
| 114 | +| Method | Description | |
| 115 | +|--------|-------------| |
| 116 | +| `update(float aDt)` | Update animations (call each frame) | |
| 117 | +| `draw() const` | Render the chart | |
| 118 | + |
| 119 | +### Getters |
| 120 | + |
| 121 | +| Method | Description | |
| 122 | +|--------|-------------| |
| 123 | +| `getBounds() const` | Get current bounds | |
| 124 | +| `getMode() const` | Get current mode | |
| 125 | +| `getMaxValue() const` | Get current maximum Y value | |
| 126 | + |
| 127 | +## Usage Examples |
| 128 | + |
| 129 | +### Basic Stacked Area Chart |
| 130 | + |
| 131 | +```cpp |
| 132 | +#include "RLAreaChart.h" |
| 133 | + |
| 134 | +// Create chart |
| 135 | +Rectangle lBounds = {50, 50, 600, 400}; |
| 136 | +RLAreaChart lChart(lBounds, RLAreaChartMode::STACKED); |
| 137 | + |
| 138 | +// Prepare data |
| 139 | +std::vector<RLAreaSeries> lData; |
| 140 | + |
| 141 | +RLAreaSeries lSeries1; |
| 142 | +lSeries1.mLabel = "Product A"; |
| 143 | +lSeries1.mColor = Color{80, 180, 255, 255}; |
| 144 | +lSeries1.mValues = {10, 15, 20, 25, 30, 28, 32}; |
| 145 | +lData.push_back(lSeries1); |
| 146 | + |
| 147 | +RLAreaSeries lSeries2; |
| 148 | +lSeries2.mLabel = "Product B"; |
| 149 | +lSeries2.mColor = Color{255, 120, 80, 255}; |
| 150 | +lSeries2.mValues = {8, 12, 18, 22, 18, 20, 24}; |
| 151 | +lData.push_back(lSeries2); |
| 152 | + |
| 153 | +lChart.setData(lData); |
| 154 | + |
| 155 | +// Main loop |
| 156 | +while (!WindowShouldClose()) { |
| 157 | + float lDt = GetFrameTime(); |
| 158 | + lChart.update(lDt); |
| 159 | + |
| 160 | + BeginDrawing(); |
| 161 | + ClearBackground(RAYWHITE); |
| 162 | + lChart.draw(); |
| 163 | + EndDrawing(); |
| 164 | +} |
| 165 | +``` |
| 166 | + |
| 167 | +### Overlapped Mode with Transparency |
| 168 | + |
| 169 | +```cpp |
| 170 | +// Use overlapped mode for comparing trends |
| 171 | +RLAreaChart lChart(lBounds, RLAreaChartMode::OVERLAPPED); |
| 172 | + |
| 173 | +// Set lower alpha for better overlap visibility |
| 174 | +for (auto& rSeries : lData) { |
| 175 | + rSeries.mAlpha = 0.5f; |
| 176 | +} |
| 177 | + |
| 178 | +lChart.setData(lData); |
| 179 | +``` |
| 180 | +
|
| 181 | +### 100% Stacked (Percent Mode) |
| 182 | +
|
| 183 | +```cpp |
| 184 | +// Show proportions over time |
| 185 | +RLAreaChart lChart(lBounds, RLAreaChartMode::PERCENT); |
| 186 | +lChart.setData(lData); // Values automatically normalized to 100% |
| 187 | +``` |
| 188 | + |
| 189 | +### Smooth Data Transitions |
| 190 | + |
| 191 | +```cpp |
| 192 | +// Initial data |
| 193 | +lChart.setData(lInitialData); |
| 194 | + |
| 195 | +// Later, smoothly transition to new data |
| 196 | +lChart.setTargetData(lNewData); |
| 197 | + |
| 198 | +// In main loop - animation happens automatically |
| 199 | +lChart.update(lDt); |
| 200 | +``` |
| 201 | + |
| 202 | +### With X-Axis Labels |
| 203 | + |
| 204 | +```cpp |
| 205 | +std::vector<std::string> lMonths = { |
| 206 | + "Jan", "Feb", "Mar", "Apr", "May", "Jun" |
| 207 | +}; |
| 208 | +lChart.setXLabels(lMonths); |
| 209 | +``` |
| 210 | + |
| 211 | +### Custom Styling |
| 212 | + |
| 213 | +```cpp |
| 214 | +RLAreaChartStyle lStyle; |
| 215 | +lStyle.mBackground = Color{15, 18, 24, 255}; |
| 216 | +lStyle.mShowGrid = true; |
| 217 | +lStyle.mGridColor = Color{40, 45, 55, 255}; |
| 218 | +lStyle.mGridLines = 6; |
| 219 | +lStyle.mPadding = 50.0f; |
| 220 | +lStyle.mLineThickness = 2.5f; |
| 221 | +lStyle.mShowPoints = true; |
| 222 | +lStyle.mPointRadius = 4.0f; |
| 223 | +lStyle.mShowLegend = true; |
| 224 | +lStyle.mAnimateSpeed = 8.0f; |
| 225 | + |
| 226 | +RLAreaChart lChart(lBounds, RLAreaChartMode::STACKED, lStyle); |
| 227 | +``` |
| 228 | +
|
| 229 | +## Animation System |
| 230 | +
|
| 231 | +The chart supports smooth animations for: |
| 232 | +- **Entry animation**: Data grows from zero when first set |
| 233 | +- **Data transitions**: Smooth interpolation between old and new values |
| 234 | +- **Scale transitions**: Y-axis scale animates smoothly when data range changes |
| 235 | +
|
| 236 | +Animation is controlled by: |
| 237 | +- `mSmoothAnimate` - Enable/disable animations |
| 238 | +- `mAnimateSpeed` - Higher values = faster transitions (default: 6.0) |
| 239 | +
|
| 240 | +```cpp |
| 241 | +// Disable animations for immediate updates |
| 242 | +lStyle.mSmoothAnimate = false; |
| 243 | +
|
| 244 | +// Or make animations faster |
| 245 | +lStyle.mAnimateSpeed = 10.0f; |
| 246 | +``` |
| 247 | + |
| 248 | +## Performance Notes |
| 249 | + |
| 250 | +- Uses `DrawTriangleStrip` for efficient filled area rendering |
| 251 | +- Pre-allocates vectors to minimize per-frame allocations |
| 252 | +- Suitable for real-time data visualization |
| 253 | + |
| 254 | +## See Also |
| 255 | + |
| 256 | +- [RLTimeSeries](RLTimeSeries.md) - For streaming time-based data |
| 257 | +- [RLBarChart](RLBarChart.md) - For categorical comparisons |
| 258 | +- [RLScatterPlot](RLScatterPlot.md) - For point-based visualization |
| 259 | + |
0 commit comments