Skip to content

Chart.Relayout() doesn't work untill browser window is resized #475

@DannyMarsman

Description

@DannyMarsman

In my blazor app I use a RadzenSplitter to split my menu with the chart and using this splitter I want to resize my chart to the available size. I use the Relayout function from the Plotly.blazor library but this doesn't work untill I resize my browser window. Afterwards the relayout is working.

I'm using Plotly.Blazor 6.0.2.

Image

@page "/"

@using BlazorPlotlyPoc.Data
@using Plotly.Blazor.LayoutLib
@using Plotly.Blazor.LayoutLib.LegendLib

<div class="slider-container">
    <RadzenSplitter Resize="@TriggerRefresh">
        <RadzenSplitterPane Size="30%" Min="350px">
            <div>
                Test
            </div>
        </RadzenSplitterPane>
        <RadzenSplitterPane Collapsible="false">
            <PlotlyChart style="height: 60vh; min-height: 350px" @bind-Config="config" @bind-Layout="layout" @bind-Data="data" @ref="chart" />
            <button class="btn btn-primary" @onclick="@DownloadImage">Download</button>
        </RadzenSplitterPane>
    </RadzenSplitter>
</div>

@code
{
    // [CascadingParameter]
    // private MudTheme Theme { get; set; }

    private List<string> dateRange = ["Jan", "Feb"];
    private PlotlyChart chart;
    private Config config;
    private Layout layout;
    private IList<ITrace> data;
    private Color colors = new Color()
    {
        Products = new List<Product>
        {
            new Product
            {
                Name = "Your Hospital",
                Revenues = new List<Revenue>
                {
                    new Revenue
                    {
                        Name = "Other",
                        ColorCode = "#F28F1D",
                        DataItems = new List<DataItem>{ new DataItem { X = "Jan", Y = 4 }, new DataItem { X = "Feb", Y = 3 }, new DataItem { X = "Mar", Y = 3 }, new DataItem { X = "Apr", Y = 3 }, new DataItem { X = "May", Y = 3 }, new DataItem { X = "Jun", Y = 3 }, new DataItem { X = "Jul", Y = 3 }, new DataItem { X = "Aug", Y = 3 }, new DataItem { X = "Sep", Y = 3 }, new DataItem { X = "Okt", Y = 3 }, new DataItem { X = "Nov", Y = 3  }, new DataItem { X = "Dec", Y = 3 } }
                    },
                    new Revenue
                    {
                        Name = "Isolated Valve",
                        ColorCode = "#F6C619",
                        DataItems = new List<DataItem>{ new DataItem { X = "Jan", Y = 3 }, new DataItem { X = "Feb", Y = 2 }, new DataItem { X = "Mar", Y = 3 }, new DataItem { X = "Apr", Y = 3 }, new DataItem { X = "May", Y = 3 }, new DataItem { X = "Jun", Y = 3 }, new DataItem { X = "Jul", Y = 3 }, new DataItem { X = "Aug", Y = 3 }, new DataItem { X = "Sep", Y = 3 }, new DataItem { X = "Okt", Y = 3 }, new DataItem { X = "Nov", Y = 3  }, new DataItem { X = "Dec", Y = 3 } }
                    },
                    new Revenue
                    {
                        Name = "Isolated CABG",
                        ColorCode = "#FADD75",
                        DataItems = new List<DataItem>{ new DataItem { X = "Jan", Y = 2 }, new DataItem { X = "Feb", Y = 1 }, new DataItem { X = "Mar", Y = 3 }, new DataItem { X = "Apr", Y = 3 }, new DataItem { X = "May", Y = 3 }, new DataItem { X = "Jun", Y = 3 }, new DataItem { X = "Jul", Y = 3 }, new DataItem { X = "Aug", Y = 3 }, new DataItem { X = "Sep", Y = 3 }, new DataItem { X = "Okt", Y = 3 }, new DataItem { X = "Nov", Y = 3  }, new DataItem { X = "Dec", Y = 3 } }
                    }
                }
            },
            new Product
            {
                Name = "All Hospitals",
                Revenues = new List<Revenue>
                {
                    new Revenue
                    {
                        Name = "Other",
                        ColorCode = "#F28F1D",
                        DataItems = new List<DataItem>{ new DataItem { X = "Jan", Y = 5 }, new DataItem { X = "Feb", Y = 4 }, new DataItem { X = "Mar", Y = 3 }, new DataItem { X = "Apr", Y = 3 }, new DataItem { X = "May", Y = 3 }, new DataItem { X = "Jun", Y = 3 }, new DataItem { X = "Jul", Y = 3 }, new DataItem { X = "Aug", Y = 3 }, new DataItem { X = "Sep", Y = 3 }, new DataItem { X = "Okt", Y = 3 }, new DataItem { X = "Nov", Y = 3  }, new DataItem { X = "Dec", Y = 3 } }
                    },
                    new Revenue
                    {
                        Name = "Isolated Valve",
                        ColorCode = "#F6C619",
                        DataItems = new List<DataItem>{ new DataItem { X = "Jan", Y = 4 }, new DataItem { X = "Feb", Y = 3 }, new DataItem { X = "Mar", Y = 3 }, new DataItem { X = "Apr", Y = 3 }, new DataItem { X = "May", Y = 3 }, new DataItem { X = "Jun", Y = 3 }, new DataItem { X = "Jul", Y = 3 }, new DataItem { X = "Aug", Y = 3 }, new DataItem { X = "Sep", Y = 3 }, new DataItem { X = "Okt", Y = 3 }, new DataItem { X = "Nov", Y = 3  }, new DataItem { X = "Dec", Y = 3 } }
                    },
                    new Revenue
                    {
                        Name = "Isolated CABG",
                        ColorCode = "#FADD75",
                        DataItems = new List<DataItem>{ new DataItem { X = "Jan", Y = 3 }, new DataItem { X = "Feb", Y = 2 }, new DataItem { X = "Mar", Y = 3 }, new DataItem { X = "Apr", Y = 3 }, new DataItem { X = "May", Y = 3 }, new DataItem { X = "Jun", Y = 3 }, new DataItem { X = "Jul", Y = 3 }, new DataItem { X = "Aug", Y = 3 }, new DataItem { X = "Sep", Y = 3 }, new DataItem { X = "Okt", Y = 3 }, new DataItem { X = "Nov", Y = 3  }, new DataItem { X = "Dec", Y = 3 } }
                    }
                }
            }
        }
    };

    /// <inheritdoc />
    protected override void OnInitialized()
    {
        config = new Config
            {
                Responsive = true,
                AutoSizable = true,
            };

        layout = new Layout
            {
                YAxis = 
                [
                new Plotly.Blazor.LayoutLib.YAxis()
                {
                    ShowTickLabels = true,
                    ShowGrid = true,
                    RangeMode = Plotly.Blazor.LayoutLib.YAxisLib.RangeModeEnum.NonNegative
                },
                new Plotly.Blazor.LayoutLib.YAxis(){
                    Visible = false,
                    Matches = "y",
                    Overlaying = "y",
                    Anchor = "x",
                    RangeMode = Plotly.Blazor.LayoutLib.YAxisLib.RangeModeEnum.NonNegative
                } 
                ],
                BarMode = BarModeEnum.Relative,
                ShowLegend = true,
                HoverMode = HoverModeEnum.XUnified,
                Legend = new List<Legend>
                {
                    new()
                    {
                        Title = new  Plotly.Blazor.LayoutLib.LegendLib.Title() {
                          Text =  "Procedure Type",
                        },
                        Orientation = OrientationEnum.V,
                    }
                }
            };

        data = new List<ITrace>();

        int productIndex = 0;
        foreach (var product in colors.Products)
        {
            foreach (var revenue in product.Revenues)
            {
                int index = 0;
                if (productIndex > 0)
                {
                    // https://graphicdesign.stackexchange.com/questions/113007/how-to-determine-the-equivalent-opaque-rgb-color-for-a-given-partially-transpare
                    // calculate new RGB color based on opacity
                    double opacity = 0.6;
                    string hexColor = revenue.ColorCode.Substring(1);
                    int argb = Int32.Parse(hexColor, System.Globalization.NumberStyles.HexNumber);
                    System.Drawing.Color baseColor = System.Drawing.Color.FromArgb(argb);
                    int r = (int)(255 - opacity * (255 - baseColor.R));
                    int g = (int)(255 - opacity * (255 - baseColor.G));
                    int b = (int)(255 - opacity * (255 - baseColor.B));

                    string colorCodeWithOpacity = $"#{r:X2}{g:X2}{b:X2}";

                    data.Add(new Bar
                        {
                            X = revenue.DataItems.Select(d => d.X as object).ToList(),
                            Y = revenue.DataItems.Select(d => d.Y as object).ToList(),
                            Name = revenue.Name,
                            YAxis = $"y{productIndex + 1}",
                            OffsetGroup = $"{productIndex}",
                            Offset = (decimal)(((productIndex) * (0.45)) - 0.44),
                            Width = (decimal)0.44,
                            LegendGroup = product.Name,
                            LegendGroupTitle = new Plotly.Blazor.Traces.BarLib.LegendGroupTitle
                            {
                                Text = product.Name,
                            },
                            ShowLegend = true,

                            Marker = new Plotly.Blazor.Traces.BarLib.Marker
                            {
                                Color = colorCodeWithOpacity
                            },
                            CustomData = [$"{product.Name}, {revenue.Name}", $"{product.Name}, {revenue.Name}", $"{product.Name}, {revenue.Name}", $"{product.Name}, {revenue.Name}", $"{product.Name}, {revenue.Name}", $"{product.Name}, {revenue.Name}", $"{product.Name}, {revenue.Name}", $"{product.Name}, {revenue.Name}", $"{product.Name}, {revenue.Name}", $"{product.Name}, {revenue.Name}", $"{product.Name}, {revenue.Name}", $"{product.Name}, {revenue.Name}"],
                            HoverTemplate = "%{x}: %{y:}<br>%{customdata}<extra></extra>",
                        });
                }
                else
                {
                    data.Add(new Bar
                        {
                            X = revenue.DataItems.Select(d => d.X as object).ToList(),
                            Y = revenue.DataItems.Select(d => d.Y as object).ToList(),
                            Name = revenue.Name,
                            YAxis = $"y{productIndex + 1}",
                            OffsetGroup = $"{productIndex}",
                            Offset = (decimal)(((productIndex) * (0.45)) - 0.44),
                            Width = (decimal)0.44,
                            LegendGroup = product.Name,
                            LegendGroupTitle = new Plotly.Blazor.Traces.BarLib.LegendGroupTitle
                            {
                                Text = product.Name,
                            },
                            ShowLegend = true,

                            Marker = new Plotly.Blazor.Traces.BarLib.Marker
                            {
                                Color = revenue.ColorCode,
                            },
                            CustomData = [$"{product.Name}, {revenue.Name}", $"{product.Name}, {revenue.Name}", $"{product.Name}, {revenue.Name}", $"{product.Name}, {revenue.Name}", $"{product.Name}, {revenue.Name}", $"{product.Name}, {revenue.Name}", $"{product.Name}, {revenue.Name}", $"{product.Name}, {revenue.Name}", $"{product.Name}, {revenue.Name}", $"{product.Name}, {revenue.Name}", $"{product.Name}, {revenue.Name}", $"{product.Name}, {revenue.Name}"],
                            HoverTemplate = "%{x}: %{y:}<br>%{customdata}<extra></extra>",
                        });
                }

                index ++;
            }
            productIndex++;
        }

        data.Add(new Bar
            {
                LegendGroup = "Procedure Type",
                LegendGroupTitle = new Plotly.Blazor.Traces.BarLib.LegendGroupTitle
                {
                    Text = "Procedure Type",
                },
                ShowLegend = true,
                Visible = Plotly.Blazor.Traces.BarLib.VisibleEnum.LegendOnly,
            });

        base.OnInitialized();
    }
    private async Task DownloadImage()
    {
        await chart.DownloadImage(ImageFormat.Png, 400, 800, "Bar Chart");
    }

    protected async Task TriggerRefresh()
    {
        await chart.Relayout();
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions