You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor项目Bootstrap进度条移动浏览器过渡行为异常求助

Blazor中Bootstrap进度条移动端启停后无法重置的问题解决

问题现象

开发的Blazor项目中,使用Bootstrap进度条结合CSS transition实现分段动画,在桌面端及浏览器模拟器中正常,但真实移动浏览器存在异常:首次点击停止后,再次启动时进度条无法正确重置为100%,即便设置了transition: none,仍会缓慢增长,后续反复启停均失效。

问题根源

移动端浏览器的CSS渲染引擎会对连续的样式变更进行优化合并,当重置进度条时,transition: none的设置和宽度变更可能被合并执行,导致浏览器未及时禁用过渡效果,仍沿用之前的过渡动画参数,从而出现进度条异常缓慢增长的情况。

解决方案

方案1:拆分样式更新步骤,强制浏览器重绘

通过异步等待让浏览器先完成无过渡样式的应用,再启动动画定时器。修改StartProgressBar方法为异步:

async void StartProgressBar()
{
    _startButtonIsDisabled = true;
    _stopButtonIsDisabled = false;
    _timerStartTime = DateTime.Now;

    // 重置进度条状态
    _counter = -1;
    ResetProgressBar();
    StateHasChanged();
    
    // 等待浏览器完成重绘,确保transition:none生效
    await Task.Delay(1);

    _timer = new Timer(TimerCallback, null, 0, (int)_t1 * 1000);
}

同时,在StopProgressBar方法中也添加重绘等待,确保停止时样式正确生效:

async void StopProgressBar()
{
    _startButtonIsDisabled = false;
    _stopButtonIsDisabled = true;
    _timer.Dispose();
    
    var ts = DateTime.Now - _timerStartTime;
    _progressPercent = (int)(100 * (1 - ts.TotalMilliseconds / (_tend*1_000)));
    _transition = "none";
    
    StateHasChanged();
    await Task.Delay(1);
}

方案2:使用CSS类管理过渡状态(更稳定)

避免直接修改内联样式,通过切换CSS类来控制过渡效果,减少浏览器样式合并的影响:

  1. 添加CSS样式到项目中:
.progress-bar.no-transition {
    transition: none !important;
}
.progress-bar.transition-t1 {
    transition: width 4s linear;
}
.progress-bar.transition-t2 {
    transition: width 4s linear;
}
.progress-bar.transition-tend {
    transition: width 8s linear;
}
  1. 修改进度条的Razor代码:
<div class="progress-bar @_transitionClass" style="width: @_progressPercent%; background-color: @_progressColor;"></div>
  1. 更新代码逻辑中的过渡控制:
@code {
    // 替换原_transition字段为_transitionClass
    private string _transitionClass = "no-transition";
    
    private void TimerCallback(object? o)
    {
        _counter++;
        switch (_counter)
        {
            case 0:
                _progressPercent = (int)(100 * (1 - _t1 / _tend));
                _transitionClass = "transition-t1";
                InvokeAsync(StateHasChanged);
                break;
            case 1:
                _progressPercent = (int)(100 * (1 - _t2 / _tend));
                _progressColor = "orange";
                _transitionClass = "transition-t2";
                InvokeAsync(StateHasChanged);
                _timer.Change(1000*(int)(_t2-_t1), Timeout.Infinite);
                break;
            case 2:
                _progressPercent = 0;
                _progressColor = "red";
                _transitionClass = "transition-tend";
                InvokeAsync(StateHasChanged);
                _timer.Change(1000*(int)(_tend-_t2), Timeout.Infinite);
                break;
            case 3:
                InvokeAsync(StateHasChanged);
                _timer.Dispose();
                break;
        }
    }
    
    void ResetProgressBar()
    {
        _progressPercent = 100;
        _progressColor = "green";
        _transitionClass = "no-transition";
    }
    
    void StopProgressBar()
    {
        _startButtonIsDisabled = false;
        _stopButtonIsDisabled = true;
        _timer.Dispose();
        var ts = DateTime.Now - _timerStartTime;
        _progressPercent = (int)(100 * (1 - ts.TotalMilliseconds / (_tend*1_000)));
        _transitionClass = "no-transition";
    }
}

原理说明

通过拆分异步更新或使用CSS类切换,让浏览器有足够时间处理样式变更,确保transition: none在进度条宽度重置前生效,避免移动端浏览器的样式合并优化导致的动画残留问题。

内容的提问来源于stack exchange,提问作者akasolace

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 23:17:15