Skip to content

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

@BC-clegras

Description

@BC-clegras

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:

line_chart_weird_animation.mp4

Describe the results you expected:

line_chart_good_animation_but_out_of_bounds.mp4

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:

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions