C# WPF实现动画渐入暗黑明亮主题切换效果
效果图如下
最近在Bilibili的桌面端看到一个黑白主题切换的效果感觉,挺有意思。于是我使用WPF尝试实现该效果。
主要的切换效果,基本实现不过还存在一些小瑕疵,比如字体等笔刷不能跟随动画进入进行切换。因为Bilibili的客户端是用electron写的,前端使用的html,css确实太强了,这咱只能佩服。
实现思路
在文末已付上代码的地址
-
UI使用三段式的布局,那么第一列和第三列可以使用白色或黑色来进行主题底色的实现。而第二列则使用一个带透明度的灰色进行覆盖底色
-
切换主题时,需要两部分操作,一是切换底色,二是切换文本等前景色的资源字典。因此我准备了三个资源字典进行主题切换。Main用于存储不变的笔刷资源,Light和Dark分别保存在明亮和暗黑两种状态下显示不同的资源。
-
切换底色,如果使用切换字典的方式,则无法实现动态效果,于是,我在底图层下使用一个圆形的绘图,并在切换动作时进行简单的缩放动画即可(此处,我使用DataTrigger与切换按钮的状态进行绑定,在状态改变时触发动画效果)
<Ellipse Grid.ColumnSpan="3" Fill="#202020" RenderTransformOrigin="0.5,0.5" Margin="30" HorizontalAlignment="Left" VerticalAlignment="Bottom" Width="1" Height="1"><Ellipse.RenderTransform><TransformGroup><ScaleTransform x:Name="BackEllipseScale"/></TransformGroup></Ellipse.RenderTransform><Ellipse.Style><Style TargetType="Ellipse"><Style.Triggers><DataTrigger Binding="{Binding ElementName=ThemeToggle,Path=IsChecked}" Value="True"><Setter Property="Visibility" Value="Visible"/><DataTrigger.EnterActions><BeginStoryboard><Storyboard><DoubleAnimation Duration="0:0:0.5" To="3500" Storyboard.TargetProperty="RenderTransform.Children[0].ScaleX"><DoubleAnimation.EasingFunction><CubicEase EasingMode="EaseOut"/></DoubleAnimation.EasingFunction></DoubleAnimation><DoubleAnimation Duration="0:0:0.5" To="3500" Storyboard.TargetProperty="RenderTransform.Children[0].ScaleY"><DoubleAnimation.EasingFunction><CubicEase EasingMode="EaseOut"/></DoubleAnimation.EasingFunction></DoubleAnimation></Storyboard></BeginStoryboard></DataTrigger.EnterActions><DataTrigger.ExitActions><BeginStoryboard><Storyboard><DoubleAnimation Duration="0:0:0.5" To="0" Storyboard.TargetProperty="RenderTransform.Children[0].ScaleX"><DoubleAnimation.EasingFunction><CubicEase EasingMode="EaseOut"/></DoubleAnimation.EasingFunction></DoubleAnimation><DoubleAnimation Duration="0:0:0.5" To="0" Storyboard.TargetProperty="RenderTransform.Children[0].ScaleY"><DoubleAnimation.EasingFunction><CubicEase EasingMode="EaseOut"/></DoubleAnimation.EasingFunction></DoubleAnimation></Storyboard></BeginStoryboard></DataTrigger.ExitActions></DataTrigger></Style.Triggers></Style></Ellipse.Style></Ellipse>
- 切换前景色,这个就比较简单了,使用基础的更改资源字典即可。(当前使用的资源都需要是 DynamicResource)
private void ThemeToggle_Checked(object sender, RoutedEventArgs e){SwitchTheme(true);}private void ThemeToggle_Unchecked(object sender, RoutedEventArgs e){SwitchTheme(false);}
public void SwitchTheme(bool isDark){var res = Application.Current.Resources.MergedDictionaries;ResourceDictionary dictionary = new ResourceDictionary();dictionary.Source = new Uri(isDark ? "./Dark.xaml" : "./Light.xaml", UriKind.Relative);res[1] = dictionary;}
项目地址:github