Blazorise icon indicating copy to clipboard operation
Blazorise copied to clipboard

[Bug]: Chart: Zoom plugin not working correctly in streaming line chart

Open technyon opened this issue 1 year ago • 15 comments

Blazorise Version

1.6.0

What Blazorise provider are you running on?

Bootstrap5

Link to minimal reproduction or a simple code snippet

ChartZoomDemo.zip

Steps to reproduce

-> Download the attached solution and run it.

I've modifed the chart streaming example and added the zoom plugin. What I need is a streaming chart that can be zoomed and panned. It only works partiall unfortunately.

What is expected?

Using the mouse and modifier keys, it's possible to

  • zoom the chart with the mouse wheel (this works)
  • drag-select the chart. This kind-of works. The chart shows data of the selected region, but doesn't actually zoom into the selected data.
  • pan the chart. This doesn't work at all.

What is actually happening?

See above.

What browsers do you see the problem on?

Chrome, Microsoft Edge, Firefox

Any additional comments?

According to the documentation of the plugins, they can be used at the same time. I'm not sure why it doesn't work, maybe something is missing in blazorise to support the interaction between the plugins?

technyon avatar Aug 01 '24 04:08 technyon

Hello @technyon

Can you try the zoom plugin with the following options?

private ChartZoomPluginOptions lineChartZoomOptions = new()
{
    Zoom = new()
    {
        Mode = "xy",
        Wheel = new()
        {
            Enabled = true
        },
        Pinch = new()
        {
            Enabled = true
        },
        Drag = new()
        {
            Enabled = true
        }
    },
    Pan = new ChartZoomPanOptions()
    {
        Enabled = true,
        Mode = "xy"
    },
    Limits = new()
    {
        X = new()
        {
            Min = -200,
            Max = 200,
            MinRange = 50
        },
        Y = new()
        {
            Min = -200,
            Max = 200,
            MinRange = 50
        }
    },
    Transition = new ChartZoomTransitionOptions()
    {
        Animation = new ChartAnimation()
        {
            Duration = 1000,
            Easing = "easeOutCubic"
        }
    }
};

stsrki avatar Aug 19 '24 17:08 stsrki

My observations:

  • dragging isn't really helpful, it only filters data around the selected area, but doesn't zoom on it. I've disabled it, it's nice to have for me
  • I can still zoom in and out with the mousewheel
  • Panning still doesn't work. Dragging the mouse pointer does nothing unfortunately - I've also tried setting a modifer key for panning, no luck either.

technyon avatar Aug 21 '24 07:08 technyon

@stsrki So is this a problem with Blazorise or with how the plugins themselves work?

David-Moreira avatar Aug 24 '24 15:08 David-Moreira

I can confirm that the pan does not work. I honestly have no idea why, as the values seem to be well passed into zoom.js

@stsrki Could you please take a look, I need some fresh eyes on this, I just can't figure it out.

David-Moreira avatar Aug 24 '24 17:08 David-Moreira

I can also confirm that we pass all the values correctly to the zoom.js. The only thing that I can notice that we don't have is the onZoomComplete update logic.

Taken from https://www.chartjs.org/chartjs-plugin-zoom/samples/basic.html

const zoomOptions = {
  limits: {
    x: {min: -200, max: 200, minRange: 50},
    y: {min: -200, max: 200, minRange: 50}
  },
  pan: {
    enabled: true,
    mode: 'xy',
  },
  zoom: {
    wheel: {
      enabled: true,
    },
    pinch: {
      enabled: true
    },
    mode: 'xy',
    onZoomComplete({chart}) {
      // This update is needed to display up to date zoom level in the title.
      // Without this, previous zoom level is displayed.
      // The reason is: title uses the same beforeUpdate hook, and is evaluated before zoom.
      chart.update('none');
    }
  }
};

stsrki avatar Aug 24 '24 18:08 stsrki

I think I hard coded it, and still didn't work.

David-Moreira avatar Aug 24 '24 21:08 David-Moreira

What about trying it on a regular, non-streaming chart? Maybe they don't play nicely together?

stsrki avatar Aug 25 '24 04:08 stsrki

I tried every kind of damn chart. Even the one from their sample.

David-Moreira avatar Aug 25 '24 08:08 David-Moreira

Would changing the ChartStreamingOptions / Delay dynamically be an option. It allows shifting data, I'm actually using it to display historical data by shifting back a few months. Passing something like "Delay + dynamic offset" to chartjs could work. "Dynamic offset" would need to be modified by panning.

technyon avatar Aug 29 '24 02:08 technyon

Not sure if that would help. We already have a way of updating options by calling the Update method.

stsrki avatar Aug 29 '24 07:08 stsrki

So what's the way forward then?

technyon avatar Aug 30 '24 02:08 technyon

We're still finding a solution. It's not going to be easy but we're not going to leave it.

stsrki avatar Aug 30 '24 07:08 stsrki

ok thanks

technyon avatar Sep 02 '24 02:09 technyon

nice one..

The pan functionality doesn't work on any of the charts in Blazorise. This appears to be a behavior (or bug?) of the Chart.js Zoom plugin or the library itself. It seems to be tied to the specifics of how Blazorise interacts with the plugin.

If you initialize the chart with options where pan is enabled, it will work as expected. However, Blazorise handles things differently: it first initializes the chart and then updates the plugin options. This means the chart starts with pan disabled, and when Blazorise tries to enable it, it fails due to what seems to be a bug in the Chart.js Zoom plugin.

I have reported this issue to the Chart.js Zoom plugin. I recommend waiting for their response before taking any actions on our side. While the fix itself isn't complicated, I want to avoid introducing unnecessary workarounds into the Blazorise codebase.

Temporary Workaround

A workaround exists for now: you can force the plugin options during chart initialization. Specifically, define the options object with pan.enabled set to true before passing it to the chart. If pan.enabled is false at initialization, it won't activate later.

Here’s a full example of a working pan feature. This example uses a line chart without streaming, but I suspect streaming is not the issue here. Let me know if this temporary fix works for you, @technyon.

@page "/"
@using Blazorise.Charts.Zoom
@rendermode InteractiveServer

<LineChart @ref="lineChart" TItem="double" OptionsObject="options">
    <ChartZoom TItem="double" Options="@lineChartZoomOptions"/>
</LineChart>

@code{
    LineChart<double> lineChart;

    object options = new
    {
        plugins = new
        {
            zoom = new
            {
                pan = new
                {
                    enabled = true,
                },
            }
        }
    };

    private ChartZoomPluginOptions lineChartZoomOptions = new()
    {
        Zoom = new()
        {
            Mode = "x",
            Wheel = new()
            {
                Enabled = true,
            },
        },
        Pan = new() { Enabled = true, Mode = "xy" }
    };

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if ( firstRender )
        {
            await lineChart.Clear();

            await lineChart.AddLabelsDatasetsAndUpdate(
            Enumerable.Range( 0, 9 ).Select( x => x.ToString() ).ToList(), 
            
            new LineChartDataset<double>
            {
                Label = "# of randoms",
                Data = Enumerable.Range( 0, 9 ).Select( _ => Random.Shared.NextDouble() * 100 ).ToList(),
                Fill = true,
                PointRadius = 3,
            } );
        }
    }

}

tesar-tech avatar Jan 18 '25 11:01 tesar-tech

Hi,

Thank you the workaround works for now.

technyon avatar Jan 20 '25 04:01 technyon