Skip to content

Commit

Permalink
feat!: Add Chart zoom and pan (#1793)
Browse files Browse the repository at this point in the history
* feat: Add Chart zoom and pan (WIP)

* feat: Allow zooming and panning freely for line chart

* fix: Scaling factor

* fix: Scaling in, translating to maxX/maxY and scaling out now keeps the translated/scaled values inside min/max bounds

* ref: Use Matrix3 for transformations

* feat: Get size from LineChart renderer

* ref: Improve code style

* feat: Improve scaling via mouse wheel

* ref: Use LayoutBuilder to get size for chart leaf

* feat: Allow scaling line chart

* feat: Allow panning via trackpad

* feat: Add panning and zooming for touch gestures

* feat: Add double tap gesture recognizer to render base chart

* test: Remove unused tests

* revert: Move vector_math dependency back to dev dependencies

* ref: Move scaling/panning logic to new `InteractiveLineChart` widget

* fix: Update bounds when widget is updated

* fix: Handle NaN bound values

* ref: Add BaseInteractiveChart and BaseInteractiveChartState

* ref: Use `BaseInteractiveChartState` in InteractiveLineChart

* feat: Add `InteractiveScatterChart`

* feat: Add FlTapEvent

* fix: Use FlTapEvent for scatter chart sample

* fix: TypeError when using touchCallbacks of InteractiveCharts

* feat: Add interactive bar chart

* revert: last 26 commits

* feat: Allow zooming and panning line chart (axis titles WIP)

* fix: Import of custom interactive viewer

* feat: Add scaling/panning to titles

* feat: Add parameters to control LineChart scale behavior

* feat: Add scaling to Line Chart Sample 1

* fix: Disable pan gesture recognizer when scaling is enabled

Otherwise pan gesture recognizer will consume touch events and InteractiveViewer's GestureDetector won't be notified.

* ref: Move interactive viewer inside axis chart scaffold to make it more reusable

* feat: Improve edge cases in line chart painter

* fix: Hide titles when they overflow chart bounds

* feat: Allow scaling via trackpad scroll

* feat!: Allow scaling bar charts

BREAKING CHANGE: `BarChart` is not `const` anymore, because we are asserting that start, center and end bar alignment can only be used with horizontal or none scaling.

* feat: Allow scaling and panning scatter chart

* ref: Remove scale axis parameter from line chart again

* ref: Set ScaleAxis.none as default on bar chart

* docs: Add documentation to public custom interactive viewer methods

* docs: Add docstring to update chart rect method

* test: Add tests for `BarChart`

* test: Add test for maxScale default value

* test: Minor refactorings on bar chart test

* test: Improve formatting of bar chart tests

* test: Add line chart tests

* feat: Add static list of ScaleAxis that allow scaling to ScaleAxis enum

* test: Add tests for scatter chart

* docs: Add documentation about scaling to `AxisChartScaffoldWidget`

* ref: Improve readability of `viewSize` getter in side titles widget

* ref: Improve readability of `axisOffset` in side titles widget

* fix: Add 1 pixel to `_getPositionsWithinChartRange` to avoid clipping titles at the edge of the chart

* ref: Make getPositionsWithinChartRange private

* fix: Draw all touch tooltips when bar chart is not scaled

* fix: Draw all touch tooltips when line chart is not scaled

* fix: Use dot height 0 when lineBarsData does not have lineData for showingTooltipSpots

* ref: Add docstrings and improve readability of AxisChartScaffoldWidget

* test: Add tests for AxisChartScaffoldWidget scaling and panning

* test: Improve line chart test formatting

* test: Add tests for chart renderers

* fix: Tests for Flutter v3.27.0

* ref: Create and reuse clipPaint property on painters

* ref: Use clipPaint in axis chart painter as well

* fix: Inflate chart rect for titles to avoid clipping

* feat: Allow passing transformation controller to control chart transformations

* fix: Keep transformation controller if both old and new widget controller is null

* feat: Add minScale and transformation controller param to bar, line and scatter chart

* test: Check that transformation controller is passed from axis chart scaffold widget to interactive viewer

* test: Add tests to check if chart rect is set to 0 when scaling goes to 1.0

* ref: Ignore custom interactive viewer in coverage

* ref: Use reuse Paint instance for clipping in bar chart painter

* ref: Use reuse Paint instance for clipping in line chart painter

* ref: Use reuse Paint instance for clipping in scatter chart painter

* test: Remove done todos

* test: Add tests for bar chart painter

* test: Add test for restoring canvas before and clipping again after drawing extra lines

* test: Add line chart painter test for minY == maxY

* Add Bitcoin price history as a line chart sample

* Add the zoom/scale feature in the line_chart_sample12

* Add the transformation controller buttons in the line_chart_sample12

* Add the url in the btc_last_year_price.json

* fix: Do not dispose external transformation controller

* ref: Rename bounding box to chartVirtualRect

* ref: Rename ScaleAxis to FlScaleAxis

* ref: Rename ScaleAxis to FlScaleAxis

* test: Add test for skipping drawing tooltip when outside of canvas

* test: Add tests for drawTouchTooltip to take dot height into account

* test: Add test for finding largest dot height

* fix: Check if widget is mounted before calling update virtual chart rect post frame callback

* fix: Make LineChartSample12 responsive to prevent overflow error

* ref: Rename variables to make purpose clearer

* ref: Use variable to improve null-check

* ref: Remove scaling from line chart sample1

* ref: Wrap transformation configuration in an object `FlTransformationConfig`

* chore: Update changelog and add migration guide

* docs: Add documentation for chart transformations

---------

Co-authored-by: imaNNeoFighT <iman.neofight@gmail.com>
  • Loading branch information
Peetee06 and imaNNeo authored Dec 19, 2024
1 parent ce9e849 commit 78db3f4
Show file tree
Hide file tree
Showing 48 changed files with 9,674 additions and 136 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
## newVersion
* **IMPROVEMENT** (by @Peetee06) Added functionality to control the transformation of axis-based charts using `FlTransformationConfig` class. You can now enable scaling and panning for `LineChart`, `BarChart` and `ScatterChart` using this class.
* **IMPROVEMENT** (by @Peetee06) Added some new unit tests in `bar_chart_data_extensions_test.dart`, `gradient_extension_test.dart` and fixed a typo in `bar_chart_data.dart`
* **BREAKING** (by @Peetee06) Fixed the equatable functionality in our BarChart. We hope it will not affect anything in our chart, but because the behaviour is changed, we marked it as a breaking change. (read more [here](https://github.com/imaNNeo/fl_chart/pull/1789#discussion_r1858371718))
* **BREAKING** (by @Peetee06) `BarChart` is not const anymore due to adding an assert to check if transformations are allowed depending on the `BarChartData.alignment` property.
* **IMPROVEMENT** (by AliAkberAakash) Minor typo fix in our line chart documentation, #1795

## 0.69.2
Expand Down
4 changes: 4 additions & 0 deletions example/assets/data/btc_last_year_price.json

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions example/lib/presentation/presentation_utils.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import 'package:flutter/cupertino.dart';
import 'package:intl/intl.dart';

class AppUtils {
static String getFormattedCurrency(
BuildContext context,
double value, {
bool noDecimals = true,
}) {
final germanFormat = NumberFormat.currency(
symbol: '€',
decimalDigits: noDecimals && value % 1 == 0 ? 0 : 2,
);
return germanFormat.format(value);
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import 'dart:async';
import 'dart:math';

import 'package:fl_chart/fl_chart.dart';
import 'package:fl_chart_app/presentation/resources/app_resources.dart';
import 'package:fl_chart_app/util/extensions/color_extensions.dart';
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';

class BarChartSample1 extends StatefulWidget {
Expand Down
2 changes: 2 additions & 0 deletions example/lib/presentation/samples/chart_samples.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import 'chart_sample.dart';
import 'line/line_chart_sample1.dart';
import 'line/line_chart_sample10.dart';
import 'line/line_chart_sample11.dart';
import 'line/line_chart_sample12.dart';
import 'line/line_chart_sample2.dart';
import 'line/line_chart_sample3.dart';
import 'line/line_chart_sample4.dart';
Expand Down Expand Up @@ -41,6 +42,7 @@ class ChartSamples {
LineChartSample(9, (context) => LineChartSample9()),
LineChartSample(10, (context) => const LineChartSample10()),
LineChartSample(11, (context) => const LineChartSample11()),
LineChartSample(12, (context) => const LineChartSample12()),
],
ChartType.bar: [
BarChartSample(1, (context) => BarChartSample1()),
Expand Down
Loading

0 comments on commit 78db3f4

Please sign in to comment.