☰
闪白切换:五平台UI过渡效果实现与调优指南
2026/10/28 16:23:52 网站建设 项目流程

1. 先搞清楚「闪白切换」到底是个什么东西

「闪白切换」这个词最近在 UI 圈子里被提得挺多,本质上它是一种页面或控件状态切换时的瞬时过曝过渡效果——切换发生的瞬间,界面整体或局部快速闪一下白色(或者接近白色的高亮),然后新内容浮现出来。视觉上有点像老式相机闪光灯打了一下,或者游戏里切换场景时那一帧白屏过场。

这个效果解决的问题很具体:状态切换的突兀感。不管是 Tab 切换、路由跳转、主题变更还是弹窗出现,如果新旧内容直接硬切,用户的视觉系统会有一个短暂的"断裂感",尤其是大面积深色背景切换时更明显。加一层几十到两百毫秒的白色过曝过渡,相当于给视觉系统一个"缓冲垫",让注意力平滑地从一个状态滑到另一个状态。

适合谁来参考?如果你是在做桌面端(Winform、WPF、WinUI3、Avalonia)或者 Web 端的前端/客户端开发,并且手头有需要做状态过渡的场景,这篇内容基本可以直接抄作业。我会把五个平台的实现思路、核心代码结构、参数调优和踩坑经验都摊开讲,不管你是刚接触动画的新手还是做过不少过渡效果的老手,都能找到能用的东西。

先给一个整体认知:闪白切换的核心不是"白",而是时间曲线 + 透明度叠加 + 渲染层级三件事的配合。白只是一个载体,真正决定效果好坏的是这三者的参数怎么调。下面我按平台逐个拆,但在此之前先把通用原理讲透,因为五个平台的差异主要在 API 层面,底层逻辑是同一套。

2. 通用原理拆解:为什么是"闪白"而不是"闪黑"

2.1 视觉暂留与过曝过渡的生理基础

人眼对亮度变化的敏感度远高于对色相变化的敏感度。当界面从深色内容切到浅色内容(或者反过来),亮度差会在视网膜上形成一个强烈的对比信号,大脑会把这个信号解读为"发生了大事",注意力被强行拉走。闪白切换的做法是:在切换的瞬间插入一个高亮度帧,把这次亮度突变"吸收"进一个更平滑的亮度包络里。

打个比方,你从暗房间走到亮房间,眼睛会不适应;但如果中间有一道柔光帘,过渡就自然多了。闪白就是那道柔光帘——它把"突变"变成了"渐变",只不过这个渐变非常短,短到用户意识不到中间发生了什么,只留下一个"切换很顺"的印象。

这里有个关键参数:闪白的持续时间。太短(低于 60ms)人眼几乎感知不到,效果等于没做;太长(超过 300ms)就会变成明显的"白屏",用户会觉得卡顿或者加载慢。实测下来,80ms 到 180ms是比较舒服的区间,具体取值要看切换内容的面积和对比度。

2.2 三层结构:遮罩层、内容层、时序控制

不管哪个平台,闪白切换的 DOM/视觉树结构都可以抽象成三层:

  • 底层内容层:旧内容,切换开始时逐渐淡出或被覆盖
  • 中间遮罩层:一个纯白(或接近白)的矩形,透明度从 0 快速升到峰值再降回 0
  • 顶层新内容层:新内容,在遮罩峰值附近开始淡入

时序上,遮罩层的透明度曲线通常是一个"快升慢降"的包络:上升段用 30% 的时间冲到峰值(比如 0.85 透明度),下降段用 70% 的时间回落。这个不对称是有讲究的——上升快是为了"抢在用户注意到突变之前盖住",下降慢是为了让新内容"浮"出来而不是"砸"出来。

注意:遮罩层的峰值透明度不建议拉到 1.0 纯白。实测 0.8 到 0.9 之间效果最好,纯白会显得刺眼,尤其在深色主题下。这个细节很多教程不会提,但实际调的时候差别很明显。

2.3 缓动函数的选择逻辑

闪白切换的缓动不能用标准的 ease-in-out,因为它的上升和下降需要不同的曲线。我的经验是:

  • 上升段用ease-out或自定义的快速衰减曲线,让透明度在极短时间内冲到峰值
  • 下降段用ease-in或cubic-bezier(0.4, 0, 0.2, 1)这类先慢后快的曲线,让白色"退潮"时有一个加速离开的感觉

如果用统一的线性曲线,整个效果会显得机械、没有"呼吸感"。这一点在 Web 端用 CSS transition 时尤其要注意,因为默认的ease曲线在短时长下表现并不理想。

3. Web 端实现:CSS 变量 + 伪元素是最轻的方案

3.1 结构设计与 DOM 开销控制

Web 端做闪白切换,最忌讳的是为了一个过渡效果往 DOM 里塞一堆额外节点。我的做法是用一个全局伪元素或者一个固定定位的遮罩 div,通过切换 class 来触发动画,而不是每次切换都创建销毁节点。

具体结构可以是这样:在 body 下放一个<div class="flash-overlay"></div>,CSS 里给它position: fixed; inset: 0; background: #fff; opacity: 0; pointer-events: none; z-index: 9999;。切换时给它加一个flash-active类,用 CSS animation 跑完整个包络,动画结束后自动回到 opacity 0。

.flash-overlay { position: fixed; inset: 0; background: #ffffff; opacity: 0; pointer-events: none; z-index: 9999; will-change: opacity; } .flash-overlay.flash-active { animation: flashPulse 160ms cubic-bezier(0.4, 0, 0.2, 1) forwards; } @keyframes flashPulse { 0% { opacity: 0; } 30% { opacity: 0.85; } 100% { opacity: 0; } }

这里will-change: opacity是为了让浏览器提前把这一层提升为合成层,避免动画过程中触发重绘。pointer-events: none保证遮罩不会拦截用户的点击事件,这个细节如果漏了,切换瞬间的点击会丢失,体验很糟糕。

3.2 触发时机与内容切换的配合

关键点在于:遮罩动画的峰值时刻要和内容切换的时刻对齐。如果内容在遮罩还没到峰值时就切了,用户会看到新旧内容同时存在的"鬼影";如果内容切得太晚,遮罩已经退了一半,突变又暴露出来了。

我的做法是用requestAnimationFrame或者setTimeout把内容切换卡在动画的 30% 位置附近。以 160ms 的动画为例,30% 大约是 48ms,所以内容切换放在setTimeout(switchContent, 48)里执行。这个数值不是死的,你可以根据实际动画时长按比例算。

function flashSwitch(switchFn, duration = 160) { const overlay = document.querySelector('.flash-overlay'); overlay.classList.remove('flash-active'); // 强制重排,确保动画能重新触发 void overlay.offsetWidth; overlay.classList.add('flash-active'); setTimeout(switchFn, duration * 0.3); setTimeout(() => overlay.classList.remove('flash-active'), duration); }

void overlay.offsetWidth这一行是踩坑踩出来的——如果不强制重排,连续快速切换时浏览器会合并动画,第二次闪白直接不触发。这个技巧在需要重复触发 CSS animation 的场景里是标配。

3.3 深色主题下的适配策略

深色主题下闪白会非常刺眼,这时候不能直接用纯白。我的处理是把遮罩颜色做成 CSS 变量,深色主题下换成rgba(255,255,255,0.6)或者干脆用主题的强调色做低透明度叠加。实测深色主题下峰值透明度降到 0.5 到 0.6 之间,配合稍微长一点的下降段(比如 200ms),观感会柔和很多。

另外,如果页面本身有prefers-reduced-motion的用户偏好,记得用媒体查询把这个动画关掉或者降级成简单的透明度渐变。这是无障碍的基本要求,不是可选项。

4. WPF 实现:Storyboard 加 Rectangle 覆盖层

4.1 视觉树布局与覆盖层放置

WPF 里做闪白,最直接的方式是在根 Grid 里叠一个Rectangle,Fill设为白色,Opacity初始为 0,IsHitTestVisible="False"防止拦截输入。这个 Rectangle 要放在视觉树的最上层,Panel.ZIndex给个大值。

<Grid> <ContentPresenter x:Name="MainContent" /> <Rectangle x:Name="FlashOverlay" Fill="White" Opacity="0" IsHitTestVisible="False" Panel.ZIndex="9999" /> </Grid>

用 Rectangle 而不是 Border 是因为 Rectangle 的渲染开销更小,而且不需要处理圆角、边框这些额外属性。IsHitTestVisible="False"对应 Web 端的pointer-events: none,作用一样。

4.2 Storyboard 的时序编排

WPF 的动画用 Storyboard 编排最清晰。核心是两条DoubleAnimationUsingKeyFrames,一条控制 Opacity 的上升下降,另一条(可选)控制内容的切换时机。不过内容切换本身不是动画能做的,需要在 Storyboard 的某个时间点用Completed事件或者KeyTime回调来触发。

var storyboard = new Storyboard(); var opacityAnimation = new DoubleAnimationUsingKeyFrames(); opacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.Zero))); opacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(0.85, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(48)), new CubicEase { EasingMode = EasingMode.EaseOut })); opacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(160)), new CubicEase { EasingMode = EasingMode.EaseIn })); Storyboard.SetTarget(opacityAnimation, FlashOverlay); Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath("Opacity")); storyboard.Children.Add(opacityAnimation);

这里用EasingDoubleKeyFrame而不是普通DoubleAnimation,是因为需要给上升段和下降段配不同的缓动。普通 DoubleAnimation 只能配一条缓动曲线,做不到这种不对称包络。

4.3 内容切换的时机控制与线程问题

WPF 的 UI 线程模型决定了内容切换必须在 Dispatcher 上执行。我的做法是在 Storyboard 开始后,用DispatcherTimer或者Task.Delay配合Dispatcher.Invoke在 48ms 左右切换内容。

storyboard.Begin(); await Task.Delay(48); Dispatcher.Invoke(() => { MainContent.Content = newContent; });

这里有个坑:Task.Delay的精度在 Windows 上大约是 15ms 级别,所以实际切换时刻可能在 48ms 到 63ms 之间浮动。对于闪白这种短动画,这个抖动是可以接受的,因为遮罩的峰值区间本身有几十毫秒的容差。但如果你的动画时长压到 100ms 以下,这个抖动就会变得明显,这时候得用DispatcherTimer配DispatcherPriority.Render来提高精度。

实操心得:WPF 里如果动画和内容切换都在 UI 线程上跑,内容切换的那一帧可能会因为布局计算而卡顿,导致遮罩动画出现跳帧。解决办法是把新内容的布局计算提前做好(比如先Measure再切换),或者用RenderOptions.SetBitmapScalingMode之类的优化手段减少渲染压力。

5. WinUI3 实现:Composition API 是正解

5.1 为什么不用 Storyboard

WinUI3 虽然保留了 Storyboard 这套 XAML 动画体系,但对于闪白这种高频、短时的过渡,Composition API才是更合适的选择。原因有三:一是 Composition 动画跑在合成线程上,不占 UI 线程,不会因为主线程忙而卡顿;二是它的启动开销比 Storyboard 小得多;三是它可以直接操作视觉层,不需要经过 XAML 属性系统。

WinUI3 里做闪白,我会用一个SpriteVisual作为遮罩层,挂到根元素的Visual上,然后用Compositor.CreateScalarKeyFrameAnimation控制它的 Opacity。

5.2 Composition 动画的编排代码

var compositor = ElementCompositionPreview.GetElementVisual(this).Compositor; var overlay = compositor.CreateSpriteVisual(); overlay.Brush = compositor.CreateColorBrush(Colors.White); overlay.Size = new Vector2((float)ActualWidth, (float)ActualHeight); ElementCompositionPreview.SetElementChildVisual(FlashHost, overlay); var animation = compositor.CreateScalarKeyFrameAnimation(); animation.InsertKeyFrame(0f, 0f); animation.InsertKeyFrame(0.3f, 0.85f, compositor.CreateCubicBezierEasingFunction( new Vector2(0.4f, 0f), new Vector2(0.2f, 1f))); animation.InsertKeyFrame(1f, 0f, compositor.CreateCubicBezierEasingFunction( new Vector2(0.4f, 0f), new Vector2(0.2f, 1f))); animation.Duration = TimeSpan.FromMilliseconds(160); overlay.StartAnimation("Opacity", animation);

InsertKeyFrame的第二个参数是进度比例(0 到 1),不是时间。所以 0.3 对应 160ms 里的 48ms,和前面 Web 端的比例一致。这种按比例编排的方式在跨平台移植时特别方便,参数可以直接复用。

5.3 尺寸同步与 DPI 适配

Composition 的 SpriteVisual 需要手动同步尺寸,窗口大小变化时要更新overlay.Size。这个如果漏了,遮罩在窗口缩放后会只覆盖一部分区域。我的做法是在SizeChanged事件里更新,并且用ActualWidth和ActualHeight而不是Width和Height,因为后者在布局完成前可能是 0。

DPI 方面,Composition 的坐标是逻辑像素,和 XAML 一致,所以不需要额外做 DPI 换算。但如果你的应用支持多显示器不同 DPI,切换显示器时记得重新计算尺寸,否则遮罩会出现偏移。

6. Avalonia 实现:跨平台下的动画一致性

6.1 Avalonia 动画体系的特点

Avalonia 的动画体系和 WPF 很像,也是 Storyboard + Animation 那一套,但它的渲染后端是跨平台的(Windows 上用 Direct2D,Linux 上用 Skia,macOS 上用 Metal),所以动画的时序精度和渲染表现在不同平台上会有细微差异。做闪白切换时,这个差异主要体现在动画启动延迟上——Avalonia 的动画启动比 WPF 稍慢一点,第一次触发时可能有 20ms 左右的额外延迟。

应对办法是预热:在应用启动时先跑一次不可见的闪白动画(Opacity 从 0 到 0.01 再回 0),让动画系统完成初始化。这样正式触发时就没有冷启动延迟了。

6.2 用 Transitions 还是 Animation

Avalonia 支持两种动画方式:Transitions(属性变化时自动过渡)和Animation(显式编排)。闪白切换我推荐用Animation,因为需要精确控制关键帧的时序,Transitions 的曲线控制粒度不够。

<Border x:Name="FlashOverlay" Background="White" Opacity="0" IsHitTestVisible="False" ZIndex="9999"> <Border.Animations> <Animation Duration="0:0:0.16" FillMode="Forward"> <KeyFrame Cue="0%" Opacity="0" /> <KeyFrame Cue="30%" Opacity="0.85"> <KeyFrame.Easing> <CubicEase EasingMode="EaseOut" /> </KeyFrame.Easing> </KeyFrame> <KeyFrame Cue="100%" Opacity="0"> <KeyFrame.Easing> <CubicEase EasingMode="EaseIn" /> </KeyFrame.Easing> </KeyFrame> </Animation> </Border.Animations> </Border>

Avalonia 的Cue属性用百分比表示时间点,和 WinUI3 的进度比例思路一致,移植起来很顺。

6.3 跨平台渲染差异的处理

实测下来,Avalonia 在 Linux(Skia 后端)上的透明度动画比 Windows 上稍微"钝"一点,同样的 160ms 动画,Linux 上看起来会慢半拍。这不是代码问题,是渲染管线的差异。我的处理是在 Linux 平台上把动画时长缩短 10% 到 15%,用平台检测做条件配置。

var duration = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? 140 : 160;

这种平台微调在跨平台开发里很常见,不要觉得是 hack,它是对渲染现实的尊重。当然,如果你的应用只跑 Windows,这段可以忽略。

7. Winform 实现:没有动画系统就自己造

7.1 Winform 的现实约束

Winform 是五个平台里最"原始"的——它没有内置的动画系统,没有 Composition,连双缓冲都要手动开。做闪白切换,本质上是在一个 Panel 上手动控制透明度并定时重绘。这条路能走通,但性能和观感都比前面几个平台差一截,所以我的建议是:如果项目允许,Winform 里优先考虑用 WPF 的 ElementHost 嵌入一个 WPF 遮罩层,动画质量会好很多。

但如果必须纯 Winform 实现,思路是用一个覆盖全窗体的Panel,BackColor设为白色,通过Timer定时修改它的BackColor的 Alpha 通道(或者用一个半透明 Panel 叠加),然后调用Invalidate触发重绘。

7.2 定时器驱动的透明度渐变

Winform 的Timer精度大约是 15ms,对于 160ms 的动画来说只有 10 帧左右,帧率偏低。要改善观感,可以把动画时长拉到 200ms 以上,或者用System.Diagnostics.Stopwatch做时间基准,在Tick里根据实际经过时间计算当前透明度,而不是依赖 Tick 次数。

private Stopwatch _flashWatch; private Panel _overlay; private void StartFlash() { _overlay.Visible = true; _flashWatch = Stopwatch.StartNew(); _flashTimer.Start(); } private void FlashTimer_Tick(object sender, EventArgs e) { var elapsed = _flashWatch.ElapsedMilliseconds; double progress = Math.Min(elapsed / 200.0, 1.0); double opacity; if (progress < 0.3) { opacity = 0.85 * (progress / 0.3); } else { opacity = 0.85 * (1 - (progress - 0.3) / 0.7); } _overlay.BackColor = Color.FromArgb((int)(opacity * 255), 255, 255, 255); if (progress >= 1.0) { _flashTimer.Stop(); _overlay.Visible = false; } }

用 Stopwatch 做时间基准的好处是,即使 Timer 的 Tick 间隔不均匀,透明度的计算也是基于真实时间的,不会出现"动画忽快忽慢"的问题。这个技巧在 Winform 里做任何定时动画都适用。

7.3 双缓冲与闪烁抑制

Winform 的 Panel 默认不开双缓冲,透明度变化时会出现明显的闪烁。必须设置DoubleBuffered = true(通过子类化或者反射设置,因为它是 protected 属性),或者用SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true)。

public class FlashPanel : Panel { public FlashPanel() { SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true); UpdateStyles(); } }

注意:Winform 里半透明控件的渲染开销很大,如果遮罩层覆盖整个窗体,每帧重绘整个区域,低配机器上可能会掉帧。实测在 1080p 分辨率下,200ms 的动画大概能跑到 30 帧左右,勉强够用。如果追求更顺滑,还是回到前面说的 ElementHost 方案。

8. 五个平台的横向对比与选型建议

8.1 关键维度对照表

维度WebWPFWinUI3AvaloniaWinform
动画系统CSS AnimationStoryboardCompositionAnimation手动 Timer
渲染线程合成线程UI 线程合成线程UI 线程UI 线程
时序精度高中高中低
实现复杂度低中中中高
深色主题适配容易容易容易容易较麻烦
推荐动画时长120-180ms140-200ms120-180ms140-200ms200-250ms

这张表是我实际做下来总结的,不是理论值。可以看到 WinUI3 和 Web 因为跑在合成线程上,时序精度最高,动画时长可以压得更短;WPF 和 Avalonia 跑在 UI 线程,时长要留点余量;Winform 最受限,时长要拉长来弥补帧率不足。

8.2 选型的核心判断依据

选哪个平台的实现方式,核心看两点:你的应用跑在哪个平台,以及你对动画质量的要求有多高。如果是新项目,WinUI3 或 Avalonia 是首选,Composition 和跨平台动画体系都能给出不错的观感。如果是存量 WPF 项目,Storyboard 方案足够用,没必要为了一个过渡效果引入新框架。Web 端最灵活,CSS 方案几乎零成本。Winform 是最后的兜底,能用但别期待太高。

还有一个容易被忽略的点:闪白切换和页面路由/状态管理的耦合。如果你的应用有统一的路由层,闪白应该做成路由切换的中间件,而不是散落在各个页面的切换逻辑里。这样参数统一、行为一致,后期调优也方便。我在一个多页面应用里最初是每个页面自己调闪白,结果不同页面的时长和透明度各不相同,用户能感觉到"有的切换顺有的切换顿",后来统一收口到路由层才解决。

9. 常见问题与排查实录

9.1 闪白不触发或只触发一次

这是最高频的问题,尤其在 Web 和 WPF 上。Web 端的原因是 CSS animation 在同一个元素上重复添加同一个 class 时不会重新触发,必须强制重排(前面提到的void offsetWidth)。WPF 端的原因是 Storyboard 的Begin在动画未结束时再次调用会被忽略,需要先Stop再Begin,或者用Begin(this, true)的第二个参数开启可控模式。

9.2 遮罩层拦截了用户输入

Web 端漏了pointer-events: none,WPF 漏了IsHitTestVisible="False",Avalonia 漏了IsHitTestVisible="False",Winform 漏了在遮罩 Panel 上处理WM_NCHITTEST返回HTTRANSPARENT。这个问题的表现是切换瞬间点击没反应,用户会以为卡了。五个平台都要检查这一项。

9.3 深色主题下闪白刺眼

前面提过,峰值透明度要降到 0.5 到 0.6,或者把遮罩颜色从纯白改成带一点主题色的浅色。另外下降段可以适当拉长,让白色退得更柔和。这个调整没有标准值,得根据你的主题色和内容对比度实际调。

9.4 动画和内容切换不同步

表现是新旧内容同时可见,或者切换后遮罩还在。核心原因是内容切换的时机没有卡在遮罩峰值附近。排查方法是把遮罩的峰值透明度临时调到 1.0 并拉长动画到 1 秒,肉眼观察内容切换发生在遮罩的哪个阶段,然后调整setTimeout或Task.Delay的数值。

9.5 低配设备上掉帧

Winform 和 WPF 在低配机器上容易出现。Winform 的解法是拉长动画时长、减少重绘区域;WPF 的解法是确保遮罩层是独立的合成层(CacheMode设为BitmapCache),避免每帧重绘整个视觉树。

独家避坑:WPF 里给遮罩 Rectangle 加CacheMode="BitmapCache"能显著降低透明度动画的渲染开销,因为透明度变化只需要合成,不需要重新光栅化。这个设置在很多教程里被忽略,但对低配设备是救命的。

10. 参数调优的实战经验

10.1 时长、峰值、曲线的三角平衡

这三个参数是联动的,不能单独调。时长拉长,峰值可以适当降低;峰值提高,下降段要拉长;曲线越"陡",时长可以越短。我的经验是先定时长(根据平台帧率能力),再定峰值(根据主题明暗),最后调曲线(根据观感微调)。

一个实测好用的基准配置:时长 160ms,峰值 0.85,上升段占 30%,上升用 ease-out,下降用 cubic-bezier(0.4, 0, 0.2, 1)。这个配置在五个平台上都试过,观感一致且不刺眼。你可以以此为起点,根据实际内容面积和主题色做 ±20% 的调整。

10.2 内容面积对参数的影响

全屏切换和小控件切换的参数应该不同。全屏切换面积大,视觉冲击强,峰值要降(0.7 到 0.8),时长要拉(180ms 到 220ms);小控件切换面积小,可以更"脆"一点,峰值 0.9,时长 100ms 到 120ms。一刀切的参数在不同场景下观感差异很大,这是我做了多个项目后最深的体会。

10.3 连续快速切换的处理

用户快速连点 Tab 时,闪白动画可能还没结束就触发了下一次。这时候如果直接重新开始动画,会出现"闪白叠闪白"的频闪,非常难受。处理办法是节流:如果上一次动画还在进行中(比如距离上次触发不到 100ms),直接跳过闪白,只做内容切换。或者用动画的"打断重来"模式,让新动画从当前透明度继续,而不是从 0 重新开始。

Web 端可以用animation-play-state或者直接重置动画;WPF 端用Storyboard.Stop后重新Begin;WinUI3 的 Composition 动画天然支持打断,新动画会从当前值平滑过渡。这个细节决定了高频操作下的体验上限。

11. 我个人的几点实操体会

做闪白切换这件事,技术实现本身不难,难的是参数调优和场景适配。同一个 160ms 的动画,在全屏路由切换和 Tab 切换下的观感完全不同,必须分开配置。我最初图省事用了一套全局参数,结果用户反馈"有的地方闪得晃眼有的地方没感觉",后来按场景拆成三档(全屏、面板、控件)才解决。

另一个体会是不要过度使用。闪白切换适合用在"状态有明显变化"的场景,比如路由跳转、主题切换、大面板展开。如果每个小交互都加闪白,用户会觉得很吵。我见过一个项目在按钮点击、输入框聚焦、下拉菜单展开时都加了闪白,整个界面像在不停打闪光灯,体验极差。克制使用,只在真正需要"过渡感"的地方加,才是对的。

最后分享一个小技巧:调参阶段可以把动画时长临时放大 5 倍(比如 800ms),这样肉眼能清楚看到遮罩的上升下降曲线和内容切换的时机是否对齐,调好后再缩回正常时长。这个"慢放调试法"在五个平台上都适用,比盯着 160ms 的动画猜问题高效得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询