flet-dev / flet

Flet enables developers to easily build realtime web, mobile and desktop apps in Python. No frontend experience required.
https://flet.dev
Apache License 2.0
11.2k stars 431 forks source link

Chart animation doesn't look right on a sliding data window #2024

Open BC-clegras opened 11 months ago

BC-clegras commented 11 months ago

Description

I am trying to use Flet to display a line chart of real time data. To do this, I'd like to be able to have a sliding window of data to show the last x seconds of data.

I am currently using the LineChart Control to display my data. When adding the first x data points to fill my graph, the animation looks as I believe it should. However, when the graph is filled and I start to try having a sliding window of data, the animation looks quite strange. The animation doesn't look weird if I don't remove the previous data from the graph, but then the previous data gets displayed outside the chart.

Code example to reproduce the issue:

import flet as ft
import random

def main(page: ft.Page):
    data = [
        ft.LineChartData(
            data_points=[
                ft.LineChartDataPoint(0, 3),
                ft.LineChartDataPoint(2.6, 2),
                ft.LineChartDataPoint(4.9, 5),
                ft.LineChartDataPoint(6.8, 3.1),
                ft.LineChartDataPoint(8, 4),
                ft.LineChartDataPoint(9.5, 3),
                ft.LineChartDataPoint(11, 4),
            ],
            stroke_width=5,
            color=ft.colors.CYAN,
            curved=False,  # True,
            stroke_cap_round=True,
            # dash_pattern=[5, 10],
        )
    ]

    page.x = 11

    chart = ft.LineChart(
        data_series=data,
        border=ft.border.all(3, ft.colors.with_opacity(0.2, ft.colors.ON_SURFACE)),
        horizontal_grid_lines=ft.ChartGridLines(interval=1, color=ft.colors.with_opacity(0.2, ft.colors.ON_SURFACE), width=1),
        vertical_grid_lines=ft.ChartGridLines(interval=1, color=ft.colors.with_opacity(0.2, ft.colors.ON_SURFACE), width=1),
        left_axis=ft.ChartAxis(
            labels=[
                ft.ChartAxisLabel(value=1, label=ft.Text("10K", size=14, weight=ft.FontWeight.BOLD)),
                ft.ChartAxisLabel(value=3, label=ft.Text("30K", size=14, weight=ft.FontWeight.BOLD)),
                ft.ChartAxisLabel(value=5, label=ft.Text("50K", size=14, weight=ft.FontWeight.BOLD)),
            ],
            labels_size=40,
        ),
        bottom_axis=ft.ChartAxis(
            labels=[
                ft.ChartAxisLabel(
                    value=2,
                    label=ft.Container(
                        ft.Text(
                            "MAR",
                            size=16,
                            weight=ft.FontWeight.BOLD,
                            color=ft.colors.with_opacity(0.5, ft.colors.ON_SURFACE),
                        ),
                        margin=ft.margin.only(top=10),
                    ),
                ),
                ft.ChartAxisLabel(
                    value=5,
                    label=ft.Container(
                        ft.Text(
                            "JUN",
                            size=16,
                            weight=ft.FontWeight.BOLD,
                            color=ft.colors.with_opacity(0.5, ft.colors.ON_SURFACE),
                        ),
                        margin=ft.margin.only(top=10),
                    ),
                ),
                ft.ChartAxisLabel(
                    value=8,
                    label=ft.Container(
                        ft.Text(
                            "SEP",
                            size=16,
                            weight=ft.FontWeight.BOLD,
                            color=ft.colors.with_opacity(0.5, ft.colors.ON_SURFACE),
                        ),
                        margin=ft.margin.only(top=10),
                    ),
                ),
            ],
            labels_size=32,
        ),
        tooltip_bgcolor=ft.colors.with_opacity(0.8, ft.colors.BLUE_GREY),
        min_y=0,
        max_y=6,
        min_x=0,
        max_x=11,
        expand=True,
        # animate=0, # Uncomment to turn off animations
    )

    def add_data(e):
        random.seed()
        val = random.randint(0, 500) / 100
        page.x += 1
        x = page.x

        data[0].data_points.append(ft.LineChartDataPoint(x, val))

        if len(data[0].data_points) > 20:
            chart.min_x = data[0].data_points[-20].x
            data[0].data_points.pop(0)  # Comment out to keep previous data, leads to data being out of bounds, but animation looks a lot better

        chart.max_x = page.x

        chart.update()

    plot_add_data = ft.ElevatedButton("Add data", on_click=add_data)

    page.add(ft.Row([plot_add_data, chart], expand=True))

ft.app(main)

Describe the results you received:

https://github.com/flet-dev/flet/assets/135861404/c8a7b4be-b54b-41ac-9e79-053c2ab92c08

Describe the results you expected:

https://github.com/flet-dev/flet/assets/135861404/0b2ea185-e854-4c5c-a05c-f41ef0f725f1

Basically, I would like to have the nice sliding animation that is in the second recording without the chart displaying out of bounds. The only difference between both recordings is that line 100 (data[0].data_points.pop(0)) is commented out in the second one.

Additional information you deem important (e.g. issue happens only occasionally):

Flet version (pip show flet):

Name: flet
Version: 0.10.3
Summary: Flet for Python - easily build interactive multi-platform apps in Python
Home-page:
Author: Appveyor Systems Inc.
Author-email: hello@flet.dev
License: Apache-2.0
Location: c:\users\clegras\appdata\local\programs\python\python310\lib\site-packages
Requires: copier, flet-runtime, packaging, qrcode, watchdog, websocket-client, websockets
Required-by:

Operating system:

Windows 10 Enterprise 22H2

Additional environment details:

FeodorFitsner commented 11 months ago

Yep, looks weird. I'll see if I can create Dart-only repro for this issue to see if it's fl_chart's issue of Flet's.

BC-clegras commented 11 months ago

Awesome, thank you very much!

FeodorFitsner commented 11 months ago

Nah, it works right in Flutter. Must be something in Flet 😳. I've tried this and that but no avail 🥹 Need more time to investigate. Will get back to this issue after some other items. Looks like the only "workaround" now is disabling animation. Sorry about that.

BC-clegras commented 11 months ago

Ok, thank you!