如何为Blazor中的状态转换设置动画?

时间:2019-05-20 11:22:06

标签: c# blazor

在我的Blazor组件中,我经常根据条件语句来渲染组件,例如

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

或者从循环中获取,例如

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

当我更改状态时,我想为状态转换设置动画,以便组件淡入/淡出。在上面的示例中,当IsCustomer发生更改时,或者在SalesOrders集合中添加或删除记录时,可能会发生这种情况。

动画添加组件

我可以看到添加组件时如何通过具有CSS类的组件实现该效果,该CSS类具有在组件渲染时发生的动画淡入-例如如Chris Sainty's excellent toast example

所示

动画删除组件

我想不出在删除组件时会怎么做,因为当该部分DOM重新呈现时,该组件会停止存在?

React拥有react-transition-group来处理过渡期,但是到目前为止,我在Blazor中找不到类似的东西吗?

有什么方法可以添加动画以删除Blazor中的组件吗?

动画页面过渡

另一个经常被动画化的状态转换是改变“页面”。再说一次,我现在找不到在Blazor中做到这一点的方法吗?实际上,这只是删除旧页面组件和添加新页面组件的动画,但是在某些框架中,这是在路由级别而不是组件级别完成的-目前我在Blazor的任何一个级别都找不到任何东西?

5 个答案:

答案 0 :(得分:3)

Blazor没有涵盖这种情况,为此,您将需要使用CSS。很难给出一个具体的示例,因为它取决于您希望动画的工作方式以及哪种样式,但是我建议您检查一下CSS过渡和关键帧。

这里有一些很好的资源

正如您在问题处理中提到的那样,我目前还无法确定要删除的项目。因此,不幸的是,我无济于事。

答案 1 :(得分:3)

解决方法

我们可以使用 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;
}

我在 CSS 中使用了@width@height@AnimTime变量来表明可能性是无限的。 我应该注意,Blazor组件中的keyframes应该以符号(@@)的两倍开头。

BlazorFiddle上观看实时演示,仅在JSFiddle上观看html + CSS。

另一个窍门

如果用户单击 close X 之类的按钮,则可以在鼠标向下滑动期间挤压0.1s或0.2s的短动画-向上。按下鼠标会触发动画,但是按下鼠标会删除组件。我在here

之前进行了编码

答案 2 :(得分:0)

对于组件移除方面:

根据Chris Sainty的回答,目前似乎没有任何方法可以解决或处理从渲染树/ DOM中删除组件的问题。

我在AspNetCore存储库中为此添加了一个GitHub feature request,如果发生这种情况,我将对其进行更新。

答案 3 :(得分:0)

我决定采用以下方法在元素被blazor从DOM中删除之前处理​​元素的淡出。这是使用Task.Delay的一种解决方法,其折衷之处在于,因为我使用Task.Delay的指定时间(以毫秒为单位),此时间需要与您在CSS中用于过渡的持续时间保持一致-否则元素可能会被blazor删除在转换完成之前(或之后):

可重用的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;       
    }
}

答案 4 :(得分:0)

关于这个问题的页面过渡动画部分......

blazor 中的转换并不是一蹴而就的。您必须考虑重置状态和保留状态模式,例如在移回之前的路线并需要保留滚动位置时需要这样做。使用 css 的过渡动画是实现此目的的好方法。有一种解决方案允许使用您选择的任何转换方法(此处的答案中的其他地方提供了示例)。

我建议您查看这个 nuget 包和 github 存储库,它们存在以解决这个确切的问题。

https://github.com/JByfordRew/BlazorTransitionableRoute