web-dev-qa-db-ja.com

Blazorで状態遷移をアニメーション化する方法は?

私のBlazorコンポーネントでは、次のような条件ステートメントに基づいてコンポーネントをレンダリングすることがよくあります。

@if (_contact.IsCustomer)
{
    <SalesOrdersList Customer="@_contact" />
}

またはループから、例えば.

@foreach(var salesOrder in _customer.SalesOrders)
{
    <SalesOrderSummary SalesOrder="@salesOrder" />
}

状態を変更するときに、状態遷移をアニメーション化して、コンポーネントがフェードイン/フェードアウトするようにします。上記の例では、IsCustomerが変更されたとき、またはSalesOrdersコレクションにレコードが追加または削除されたときに発生する可能性があります。

コンポーネントを追加するアニメーション

コンポーネントを追加するときに、コンポーネントがレンダリングされるときに発生するアニメーションのフェードインがあるCSSクラスを持つコンポーネントによって、これがどのように達成できるかを確認できます。 Chris Saintyの素晴らしいトーストの例 に示すように

コンポーネントの削除のアニメーション

コンポーネントを削除するときに、DOMのその部分が再レンダリングされるとコンポーネントが存在しなくなるので、それをどのように行うか考えられませんか?

Reactには react-transition-group があり、遷移の期間を扱いますが、現時点ではBlazorで同様のものを見つけることができませんか?

Blazorでコンポーネントを削除するためのアニメーションを追加する方法はありますか?

ページ遷移のアニメーション化

他のよくアニメーションされる状態遷移は、「ページ」の変更です。繰り返しますが、私は現在、Blazorでそれを行う方法を見つけることができませんか?効果的には、古いページコンポーネントを削除するためのアニメーションと新しいページコンポーネントを追加するための別のアニメーションにすることができますが、一部のフレームワークでは、コンポーネントレベルではなくルーティングレベルで行われます-現在、Blazorのどちらのレベルでも何も見つかりません?

8
tomRedox

Blazorはこのシナリオをカバーしていません。このため、CSSを使用する必要があります。アニメーションをどのように機能させたいか、またどのようなスタイルを使用するかに依存するため、具体的な例を示すのは難しいですが、CSSの遷移とキーフレームを確認することをお勧めします。

ここにいくつかの良いリソースがあります

あなたの質問で述べたように、削除されるアイテムの処理は、私がまだ理解できていないものです。だから残念ながら私はそれを手伝うことはできません。

4
Chris Sainty

更新:以下を使用するのではなく、GitHubにこれの改善されたソリューションを配置しました(Task.Delayに依存していません)。 https://github.com/dazinator/BlazorDeferredRemove

要素がblazorによってDOMから削除される前に、要素のフェードアウトを処理するための次のアプローチを採用しました。 Task.Delayを使用する回避策であり、妥協点は、ミリ秒単位で指定された時間でTask.Delayを使用しているため、この時間は、遷移のCSSで使用する期間に合わせる必要があります。それ以外の場合、要素はブレイザーによって削除される可能性があります。移行が完了する前(または後):

再利用可能なTransition.razorコンポーネント:

    <div class="@(ToggleActive ? ToggleTransitionOnCssClassName: ToggleTransitionOffCssClassName)">
        @ChildContent;
    </div>

    @code {

    [Parameter] RenderFragment ChildContent { get; set; }

    [Parameter] string ToggleTransitionOnCssClassName { get; set; } = "";
    [Parameter] string ToggleTransitionOffCssClassName { get; set; } = "";

    [Parameter] int TransitionDurationMilliseconds { get; set; } = 200;

    public bool ToggleActive { get; set; }

    [Parameter] EventCallback<bool> TransitionEnded { get; set; }

    public async Task ToggleTransition()
    {
        ToggleActive = !ToggleActive;
        await Task.Delay(TransitionDurationMilliseconds);
        await TransitionEnded.InvokeAsync(ToggleActive);
    }


    }

親ページまたはコンポーネントから同様に使用されます。

         @if (RenderThingy)
        {
            <Transition @ref="Transition" TransitionDurationMilliseconds="500" ToggleTransitionOnCssClassName="m-fadeOut" ToggleTransitionOffCssClassName="m-fadeIn" TransitionEnded="@TransitionComplete">
                <RenderThingy OnDismissed="@OnDismissed"></RenderThingy>
            </Transition>
        }

@code {

    Transition Transition { get; set; }
    bool RenderThingy {get; set;} = true;

    async Task OnDismissed()
    {
        await Transition.ToggleTransition();
    }
    private void TransitionComplete(bool toggleState)
    {
        RenderThingy = false;
    }
}

およびcss:

.m-fadeIn {
    visibility: visible;
    opacity: 1;
    animation: fadein 500ms;
}

@keyframes fadein {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

.m-fadeOut {
    animation: fadeout 500ms;
}

@keyframes fadeout {
    from {
        opacity: 1;
    }

    to {
        opacity: 0;       
    }
}
2
Darrell

回避策

[〜#〜] css [〜#〜]を使用して表示/非表示を切り替えることができます。コンポーネントが非表示のときにコンポーネントに渡されるハンドルnullパラメータを確認してください。

次のようなコンポーネントPersonがあるとします。

<style>
.container{
    display:inline-block;
    width:@width;
    height:@height;
    color:white;
    background-color:blue;
}
.fade-out{ 
   animation: fade @AnimTime linear forwards;
}
.spin-in{
   animation: spin @AnimTime linear forwards;
}

@@keyframes fade {
  0%   {opacity:1;}
  99%  {width:@width; height:@height;}
  100% {width:0px;height:0px; opacity:0;}
}
@@keyframes spin {
  0%   {width:0px;height:0px; transform: rotate(0deg);}
  99%  {width:@width; height:@height;}
  100% {width:@width;height:@height;transform: rotate(1440deg);}
}
</style>
<div class="container @(IsShown?"spin-in":"fade-out")">
    <span>@(Name??"")</span>
</div>
@code {
    string width="100px";
    string height="20px";

    [Parameter]
    public string Name { get; set; }

    [Parameter]
    public string AnimTime { get; set; } 

    [Parameter]
    public bool IsShown {get; set;}
}

以下のような別のページ/コンポーネントで使用します。

<button @onclick="(_=>{isShown=!isShown;})">Switch</button>
<span>Left hand of component</span>
<Person Name="Jack" AnimTime="2s" IsShown=@isShown/>
<span>Right hand of component</span>
@code{
    bool isShown=true;
}

@width@height@AnimTime[〜#〜] css [〜#〜]の変数は、可能性が無限であることを示しています。 Blazorコンポーネントのkeyframesは、ダブルアットシンボル(@@)。

BlazorFiddle のライブデモと JSFiddle のhtml + CSSのみをご覧ください。

別のトリック

ユーザーがcloseまたは[〜#〜] x [〜#〜]のようなボタンをクリックした場合マウスダウンからマウスアップまでの期間に、0.1秒または0.2秒の短いアニメーションをスクイーズできます。マウスダウンはアニメーションをトリガーしますが、マウスアップはコンポーネントを削除します。私はこれを前にコーディングしました ここ

1
Sorush

物事のコンポーネントの削除側について:

AspNetCoreリポジトリで削除するために GitHub機能リクエスト を追加しました。 MicrosoftのSteve Sandersonは、Blazorフレームワークが公開しているAPIを使用して、コンポーネントのアニメーション削除がすでに可能であるべきだと概説していますが、実装を簡単にするためにパッケージを作成する人から恩恵を受けるでしょう。

私が期待する解決策は、リストまたは単一の項目のいずれかをレンダリングし、アニメーション化できるように各項目の削除を遅らせるロジックを組み込んだアニメータコンポーネントを作成することです。 Blazorにはすでにテンプレートコンポーネント用の優れたプリミティブがあるので、結果のAPIはかなり素晴らしいはずです。これは基本的に、他のSPAフレームワークで使用されているのと同じソリューションです。

これは、ユーザーコードで実現可能であり、組み込みのフレームワーク機能を必要としません。簡単だと言っているわけではありませんが、コミュニティの誰かがそれをする時間を見つけてくれることを願っています。これは、いつか自分でやることになるかもしれませんが、短期的には他の優先事項があります。

dazinator /@Darrellがそれを採用し、- Blazor Deferred Remove Nugetパッケージを作成しました。私はまだそれを試していませんが、これを達成するために必要なもののようです。

Blazor.Animateパッケージ もあります。

1
tomRedox