[WPF] 实现两个任天堂 Switch 的加载动画


写了两个 Switch 的加载动画,第一个是 Swtich 最常见那个 Loading 动画:

其中拆分文字用到了 之前一篇文章 里提到的用 ItemsControl 拆分的方案,文字逐个反转的动画也用了那篇文章里提到的 TimeSpanIncreaser 来控制 BeginTime:

<Storyboard BeginTime="{Binding Next, Source={StaticResource TimeSpanIncreaser}}" RepeatBehavior="Forever">
    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="TextElement"
                                   Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)"
                                   Duration="0:0:4">
        <LinearDoubleKeyFrame KeyTime="0:0:0.4" Value="-1" />
        <LinearDoubleKeyFrame KeyTime="0:0:0.6" Value="1" />
        <LinearDoubleKeyFrame KeyTime="0:0:0.8" Value="-1" />
    </DoubleAnimationUsingKeyFrames>
</Storyboard>

另一个是 eShop 的加载动画,看起来简单,实现过程反而更有趣。

要实现这个动画,第一步要先把每行都拆分成一个独立的部分,然后还是使用 TimeSpanIncreaser 控制每个部分的开始动画的时间:

<local:NintendoEShopLoadingRow Delay="{Binding Next, Source={StaticResource TimeSpanIncreaser}}" />
<local:NintendoEShopLoadingRow Grid.Row="1" Delay="{Binding Next, Source={StaticResource TimeSpanIncreaser}}" />
<local:NintendoEShopLoadingRow Grid.Row="2" Delay="{Binding Next, Source={StaticResource TimeSpanIncreaser}}" />
<local:NintendoEShopLoadingRow Grid.Row="3" Delay="{Binding Next, Source={StaticResource TimeSpanIncreaser}}" />
<local:NintendoEShopLoadingRow Grid.Row="4" Delay="{Binding Next, Source={StaticResource TimeSpanIncreaser}}" />
<local:NintendoEShopLoadingRow Grid.Row="5" Delay="{Binding Next, Source={StaticResource TimeSpanIncreaser}}" />

然后实现 NintendoEShopLoadingRow ,先在里面放上四个颜色由浅到深的 Grid。为了不写死颜色,我做了个 LightenConverter,具体用法如下:

<Grid Background="{Binding Foreground, ElementName=Row, Converter={StaticResource LightenConverter}, ConverterParameter=.8}" />
<Grid Background="{Binding Foreground, ElementName=Row, Converter={StaticResource LightenConverter}, ConverterParameter=.6}" />
<Grid Background="{Binding Foreground, ElementName=Row, Converter={StaticResource LightenConverter}, ConverterParameter=.4}" />
<Grid Background="{Binding Foreground, ElementName=Row}" />

LightenConverter 的代码如下,先实现一个 HslColor 类,HSL即色相、饱和度、亮度(英语:Hue, Saturation, Lightness)。LightenConverter 将原本的 SolidColorBrush 中的 Color 转换成 HslColor,然后修改亮度后再转换回来:

public class LightenConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var brush = value as SolidColorBrush;
        if (brush == null)
            return value;

        var amount =System.Convert.ToDouble(parameter);

        return new SolidColorBrush(new HslColor(brush.Color).Lighten(amount).ToRgb());
    }

    public HslColor Lighten(HslColor source, double amount)
    {
        return new HslColor(source.h, source.s, source.l + (1 - source.l) * amount, source.a);
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new NotImplementedException();
}

这样就实现了 4 个 Grid 使用同一个颜色,但亮度不同。

最后要让这四个 Grid 动起来(其实只是动前面三个)。虽然说”动起来“,但并不是做移动的动画,而是用 ScaleTransform 做拉伸,同样是做 ScaleX 从 1 到 0 的动画,如果 RenderTransformOrigin="0,0.5" 就是以左边界为中心,即从右往左缩小;反之 RenderTransformOrigin="1,0.5" 就是从左往右缩小。通过设置 RenderTransformOrigin 实现了各层往不同的方向缩小,实现了左右往返的动画:

<DoubleAnimationUsingKeyFrames Storyboard.TargetName="L1" Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)">
    <LinearDoubleKeyFrame KeyTime="00:00:1" Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="L2" Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)">
    <LinearDoubleKeyFrame KeyTime="00:00:1" Value="1" />
    <LinearDoubleKeyFrame KeyTime="00:00:2" Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="L3" Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)">
    <LinearDoubleKeyFrame KeyTime="00:00:2" Value="1" />
    <LinearDoubleKeyFrame KeyTime="00:00:3" Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="L1" Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)">
    <LinearDoubleKeyFrame KeyTime="00:00:3" Value="0" />
    <LinearDoubleKeyFrame KeyTime="00:00:4" Value="1" />
</DoubleAnimationUsingKeyFrames>

可惜的是,这个动画对 WPF 来说有些勉强,偶尔会有卡顿的现象。反正只是玩玩,正式产品不要在这么大的元素上做动画。

源码:https://github.com/DinoChan/wpf_design_and_animation_lab

文章来源:https://www.cnblogs.com/dino623/p/two-nintendo-switch-loadings-in-wpf.html

版权声明:本文为YES开发框架网发布内容,转载请附上原文出处连接
管理员
上一篇:记一次 .NET 某妇产医院 WPF内存溢出分析
下一篇:WPF 布局 在有限空间内让两个元素尽可能撑开的例子
评论列表

发表评论

评论内容
昵称:
关联文章

[WPF] 实现天堂 Switch 动画
[WPF] 用 OpacityMask 模仿 UWP Text Shimmer 动画
WPF 布局 在有限空间内让元素尽可能撑开例子
WPF 组织机构摄像机树 全量 大数据量 分页摄像机节点
[WPF] 实现 WPF Inner Shadow
[WPF] 抄一个 CSS3 实现按钮
[WPF] 用 Effect 实现线条光影效果
C# 解析读取XML文件正确姿势
从数据库或者其他位置ASP.NET MVC Views 视图 数据库中加 cshtml
使用 WPF PowerPoint 系列 基于 OpenXML 解析实现 PPT 文本描边效果
[WPF] 使用 Shazzam Shader Editor 编写一个 Lighten Effect
winform自定义控件(UserControl)研究
[WPF] 实现一个很久以前流行按钮样式
MEF会缺少一些dll,
System.BadImageFormatException:“未能文件或程序集 或它某一个依赖项。试图格式不正确程序
.net中使用Linq 判断集合是否有交集集合类
JS合并数组3种方法详解
算法:计算大量数据数组交集,差集,并集,(数据差异)
使用 WPF PowerPoint 系列 文本 BodyProperties FontScale 与文本字号缩放
未能文件或程序集“CefSharp.Core.dll”或它某一个依赖项。

联系我们
联系电话:15090125178(微信同号)
电子邮箱:garson_zhang@163.com
站长微信二维码
微信二维码