1. 程式人生 > 其它 >[WPF] 實現兩個任天堂 Switch 的載入動畫

[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


作者:dino.c
出處:http://www.cnblogs.com/dino623/
說明:歡迎轉載並請標明來源和作者。如有錯漏請指出,謝謝。