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