【问题标题】:blazor , task.delay, css manipulationblazor,task.delay,css 操作
【发布时间】:2021-06-14 18:36:56
【问题描述】:

我想在 blazor 中创建渐变效果,例如 https://gradienta.io/editor 移动角度滑块。 我想通过使用 task.delay 函数来做到这一点,但只显示了 1 和 3,我在这里缺少的是 2 没有显示。 最终我想把它放在一个循环中,以设置运动的渐变。

<div class="box-size" style=@myStyle>
       @content
    </div>
}

@code {
    public string myStyle = "";
    public string content = "";

    protected override async Task OnInitializedAsync()
    {
                
        myStyle = "background-image: linear-gradient(80deg, #FF0055 0%, #000066 100%)";
        content = "1";
        await Task.Delay(5000);
        myStyle = "background-image: linear-gradient(160deg, #FF0044 0%, #000066 100%)";
        content = "2";
        await Task.Delay(5000);
        myStyle = "background-image: linear-gradient(240deg, #FF0011 0%, #000066 100%)";
        content = "3";
       

    }

【问题讨论】:

  • 可能需要利用 StateHasChanged,但您是否有理由不使用 CSS @keyframes
  • 只是想尝试一下 blazor 和异步任务。看看是否可以对渐变 css 进行动画处理。
  • OnInitalized 是一个非常奇怪的地方来放置一些活跃的东西。尝试不同的事件,或在事件处理程序中运行您的代码。另外,如果您正在制作动画,我希望您使用的是 WASM。如果您使用的是服务器,那么它很可能在家里工作得很好,然后由于 ping 问题而变得非常粗糙。

标签: c# css async-await blazor


【解决方案1】:

这在 MS Docs 中得到解决:An asynchronous handler involves multiple asynchronous phases

TLDR:Task 接收者只能观察到它们的最终完成,而不是中间的异步状态。 ComponentBase 将在任务第一次返回和最终完成时自动触发重新渲染。因此,您必须手动调用 StateHasChanged 以在这些中间点触发重新渲染。

protected override async Task OnInitializedAsync()
{                
    myStyle = "background-image: linear-gradient(80deg, #FF0055 0%, #000066 100%)";
    content = "1";
    // first return, renders here automatically

    await Task.Delay(5000);
    myStyle = "background-image: linear-gradient(160deg, #FF0044 0%, #000066 100%)";
    content = "2";
    // intermediate point, manual invocation required
    StateHasChanged();

    await Task.Delay(5000);
    myStyle = "background-image: linear-gradient(240deg, #FF0011 0%, #000066 100%)";
    content = "3";  
    // completion, renders here automatically
}

【讨论】:

    【解决方案2】:

    Blazor 将在您的方法中的第一个 await 处自动调用 StateHasChanged()(这将呈现并显示第 1 步)。

    然后它会在您的方法结束时再次自动调用 StateHasChanged() - 这将呈现第 3 步。

    要查看第 2 步,您需要在中间额外调用 StateHasChanged()

    protected override async Task OnInitializedAsync()
        {
                    
            myStyle = "background-image: linear-gradient(80deg, #FF0055 0%, #000066 100%)";
            content = "1";
            await Task.Delay(5000);
            myStyle = "background-image: linear-gradient(160deg, #FF0044 0%, #000066 100%)";
            content = "2";
            StateHasChanged(); // This will render Step 2
            await Task.Delay(5000);
            myStyle = "background-image: linear-gradient(240deg, #FF0011 0%, #000066 100%)";
            content = "3";      
        }
    

    【讨论】:

      【解决方案3】:

      我认为动画颜色(和形状)的更好选择是使用内联 svg。

      SVG 具有内置动画功能。

      【讨论】:

        【解决方案4】:

        在 blazor 中创建渐变效果,例如 https://gradienta.io/editor 移动角度滑块

        渐变角度不是受支持的动画类型。此处的其他答案不会为角度设置动画。

        动画角度: (我只会在 WASM 中这样做)

        AnimatedBackground.razor

        <div class="css-selector" style="width:200px;height:200px;">
        </div>
        <style>
            :root {
                --angle: @($"{Angle}deg");
            }
        </style>
        
        

        AnimatedBackground.razor.cs

        public partial class AnimatedBackground: IDisposable
        {
            [Inject]
            private IAnimationTickService TickService { get; set; }
        
            private double Angle { get; set; }
        
            protected override void OnInitialized()
            {
                TickService.TimerSyncEvent += AnimationTickService_OnTick;
            }
        
            private void AnimationTickService_OnTick(object sender, EventArgs e)
            {
                const double duration = 20;
                const double fps = AnimationTickService.FPS;
                const double incAmount = (360/fps)/duration;
                Angle += incAmount;
                Angle %= 360;
                InvokeAsync(StateHasChanged);
            }
        
            public void Dispose()
            {
                TickService.TimerSyncEvent -= AnimationTickService_OnTick;
            }
        }
        
        

        AnimatedBackground.razor.css

        .css-selector {
            background: linear-gradient(var(--angle), #FF0055 0%, #000066 100%);
            background-size: 600% 600%;
        }
        

        AnimationTickService.cs

        public class AnimationTickService : IDisposable
        {
            private readonly Timer timer;
            public const double FPS = 25;
            public AnimationTickService()
            {
                timer = new Timer();
                timer.Interval = 1000.0 / FPS;
                timer.Elapsed += Timer_Elapsed;
                timer.AutoReset = true;
                timer.Start();
            }
        
            public event EventHandler TimerSyncEvent;
            
            private void Timer_Elapsed(object sender, ElapsedEventArgs e)
                => TimerSyncEvent?.Invoke(sender, e);
            
            public void Dispose()
            {
                timer.Stop();
                timer.Dispose();
            }
        }
        
        

        Program.cs

           builder.Services.AddScoped< AnimationTickService>();
        

        尽量避免这样做,使用纯 css 方法。您可以为background-postion 设置动画,然后颜色停止以使用infinate 动画获得类似的结果。

        Pure CSS Similar effect

        【讨论】:

          猜你喜欢
          • 2015-01-04
          • 1970-01-01
          • 2021-07-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-02-24
          • 2019-01-05
          • 1970-01-01
          相关资源
          最近更新 更多