fl_chart icon indicating copy to clipboard operation
fl_chart copied to clipboard

When using LineChart with implicit animations (duration and curve parameters)

Open pingplass123 opened this issue 2 months ago • 2 comments

When using LineChart with implicit animations (duration and curve parameters), switching between datasets with significantly different Y-axis ranges causes vertical lines/glitches to appear during the animation transition. This happens because the chart tries to animate between data points with very different values (e.g., from ~200 range to ~460 range). The issue is particularly noticeable when: Switching between different assets/stocks with different price ranges The Y-axis min/max values change dramatically Using cutOffY and applyCutOffY for baseline-based gradients

To Reproduce Complete reproducible code in main.dart:

import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'FL Chart Animation Issue',
      theme: ThemeData.dark(),
      home: const ChartAnimationIssue(),
    );
  }
}

class ChartAnimationIssue extends StatefulWidget {
  const ChartAnimationIssue({super.key});

  @override
  State<ChartAnimationIssue> createState() => _ChartAnimationIssueState();
}

class _ChartAnimationIssueState extends State<ChartAnimationIssue> {
  bool showFirstDataset = true;

  // Dataset 1: Price range ~200-250
  List<FlSpot> get dataset1 => [
        const FlSpot(0, 202.81),
        const FlSpot(1, 205.20),
        const FlSpot(2, 203.50),
        const FlSpot(3, 207.83),
        const FlSpot(4, 206.10),
        const FlSpot(5, 208.50),
        const FlSpot(6, 207.20),
      ];

  // Dataset 2: Price range ~440-465 (very different range)
  List<FlSpot> get dataset2 => [
        const FlSpot(0, 454.14),
        const FlSpot(1, 448.20),
        const FlSpot(2, 451.80),
        const FlSpot(3, 462.07),
        const FlSpot(4, 458.50),
        const FlSpot(5, 465.89),
        const FlSpot(6, 463.20),
      ];

  @override
  Widget build(BuildContext context) {
    final currentData = showFirstDataset ? dataset1 : dataset2;
    final minY = currentData.map((e) => e.y).reduce((a, b) => a < b ? a : b);
    final maxY = currentData.map((e) => e.y).reduce((a, b) => a > b ? a : b);
    final startPrice = currentData.first.y;

    return Scaffold(
      appBar: AppBar(
        title: const Text('FL Chart Animation Issue'),
      ),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(16.0),
            child: ElevatedButton(
              onPressed: () {
                setState(() {
                  showFirstDataset = !showFirstDataset;
                });
              },
              child: Text(
                showFirstDataset
                    ? 'Switch to Dataset 2 (465 range)'
                    : 'Switch to Dataset 1 (202 range)',
              ),
            ),
          ),
          Expanded(
            child: Padding(
              padding: const EdgeInsets.all(16.0),
              child: LineChart(
                duration: const Duration(milliseconds: 250),
                curve: Curves.easeInOut,
                LineChartData(
                  gridData: FlGridData(
                    show: true,
                    drawVerticalLine: false,
                    getDrawingHorizontalLine: (value) {
                      // Baseline at start price
                      if ((value - startPrice).abs() < (maxY - minY) * 0.02) {
                        return FlLine(
                          color: Colors.white.withValues(alpha: 0.5),
                          strokeWidth: 1,
                          dashArray: [4, 4],
                        );
                      }
                      return FlLine(
                        color: Colors.white.withValues(alpha: 0.1),
                        strokeWidth: 0.5,
                      );
                    },
                  ),
                  titlesData: const FlTitlesData(
                    show: false,
                  ),
                  borderData: FlBorderData(show: false),
                  lineBarsData: [
                    LineChartBarData(
                      spots: currentData,
                      isCurved: true,
                      color: Colors.green,
                      barWidth: 1.5,
                      isStrokeCapRound: true,
                      dotData: const FlDotData(show: false),
                      belowBarData: BarAreaData(
                        show: true,
                        cutOffY: startPrice,
                        applyCutOffY: true,
                        gradient: LinearGradient(
                          colors: [
                            Colors.green.withValues(alpha: 0.3),
                            Colors.green.withValues(alpha: 0.05),
                          ],
                          begin: Alignment.topCenter,
                          end: Alignment.bottomCenter,
                        ),
                      ),
                    ),
                  ],
                  minX: 0,
                  maxX: 6,
                  minY: minY - (maxY - minY) * 0.1,
                  maxY: maxY + (maxY - minY) * 0.1,
                ),
              ),
            ),
          ),
          const Padding(
            padding: EdgeInsets.all(16.0),
            child: Text(
              'Issue: When switching between datasets with very different Y-axis ranges,\n'
              'vertical lines/glitches appear during the animation transition.',
              textAlign: TextAlign.center,
              style: TextStyle(color: Colors.red),
            ),
          ),
        ],
      ),
    );
  }
}

Steps to reproduce: Run the code above Tap the button to switch between datasets Observe vertical lines/glitches appearing during the animation transition Expected behavior The chart should smoothly animate between different datasets without showing vertical line artifacts, similar to how financial apps like Yahoo Finance handle chart transitions.

Screenshots Image

Versions Flutter version: 3.35.4 (channel stable) Dart version: 3.9.2 fl_chart version: 1.0.0

pingplass123 avatar Nov 06 '25 19:11 pingplass123

Hi @imaNNeo

pingplass123 avatar Nov 07 '25 08:11 pingplass123

https://github.com/user-attachments/assets/7df3e20a-f5b5-4ccc-a09d-3473393fdada

I can not spot what would be an issue here. For me it looks like it's working. See my Attached video.

Version: fl_chart: ^1.1.1

piranha771 avatar Nov 11 '25 09:11 piranha771