1

I have issue with re-rendering rive animation after I leave default page "/". When I return back (/counter -> /) animation is not displayed anymore but js modul is being called in the code so I am not sure how can I deal with this problem.

here is a code:

Index.razor->

@page "/"
@inject IJSRuntime JSRuntime

<canvas id="canvas" width="500" height="500"></canvas>

@code {
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await JSRuntime.InvokeAsync<IJSObjectReference>("import", "./Pages/Index.razor.js");
        }
    }
}

Index.razor.js ->

const r = new rive.Rive({
    src: 'bear.riv',
    canvas: document.getElementById('canvas'),
    autoplay: true,
    })

Index.html ->

    <script src="_framework/blazor.webassembly.js"></script>
    <script src="https://unpkg.com/@rive-app/canvas@1.0.79"></script>

Any advice would be much appreciated. Thank you!

Laftek
  • 33
  • 3

1 Answers1

0

The problem is that that "import" will only happen once and your animation will keep running (I think) against the old canvas. That means you probably have a memory leak too.

A solution would look like this:

@implements IAsyncDisposable
...
IJSObjectReference? rivWrapper;

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {                        
        rivWrapper = await JSRuntime.InvokeAsync<IJSObjectReference>("import", "./Pages/Index.razor.js");
        await rivWrapper.InvokeVoidAsync("createRive");         
    }
}

public async ValueTask DisposeAsync()
{
    await rivWrapper!.DisposeAsync();
}

and the JS

export function createRive() {        
    const r = new rive.Rive({
        src: 'bear.riv',
        canvas: document.getElementById('canvas'),
        autoplay: true,
    });
}

Note that I'm very weak on Javascript, this might still leak. See this for further reference about adding a dispose().

H H
  • 263,252
  • 30
  • 330
  • 514