WPF動畫


1、基本動畫。

WPF提供了一個更高級的模型,通過該模型可以只關注動畫的定義,而不考慮它們的渲染方式,這個模型基於依賴項屬性基礎架構,本質上,WPF動畫只不過是在一段時間間隔內修改依賴項屬性值的一種方式。不過還有另外一個限制,為了實現屬性的動態化,需要有支持相應數據類型的動畫類,例如Button.Width屬性使用雙精度數據類型,為實現屬性的動態化,需要使用DoubleAnimation類,但Button.Padding屬性使用的是Thickness結構,所以需要使用ThicknessAnimation類。為了為屬性應用動畫,可以針對相應的數據類型創建自己的動畫類,你將發現,System.Windows.Media.Animation名稱空間已經為希望使用的大多數數據類型提供了動畫類。

2、Animation類。

實際上有兩種類型的動畫,一種是在開始值和結束值之間以逐步增加的方式改變屬性的動畫(線性插值過程),另一種是從一個值突然變成另一值得動畫(關鍵幀動畫)。所有關鍵幀動畫都使用 "類型名 + AnimationUsingKeyFrames " 的形式進行命名,比如StringAnimationUsingKeyFrames和ObjectAnimationUsingKeyFrames。某些數據類型有關鍵幀動畫類,但沒有插值動畫類。例如,可使用關鍵幀為字符串應用動畫,不能使用插值為字符串應用動畫。然而,所有數據類型都支持關鍵幀動畫,除非他們根本不支持動畫。所有具有(使用插值)常規動畫類的數據類型,也都有相應的關鍵幀動畫的動畫類型,如線性插值的DoubleAnimation對應DoubleAnimationUsingKyyFrames。另外還有一種基於路徑的動畫。因此,WPF動畫使用三種方法:線性插值、關鍵幀和路徑。在System.Windows.Media.Animation名稱空間中將發現以下內容:

7個 "類型名+Animation類"  這些類使用插值動畫。

22個 "類型名+AnimationUsingKeyFrames" 這些類使用關鍵幀動畫。

3個 "類型名+AnimationUsingPath"類這類使用基於路徑的動畫。

3、使用代碼創建動畫。

wpf中,最常用的動畫技術是線性插值動畫,標准的幀速率是60秒/幀,使用動畫的最簡單方式是實例化在前面列出的其中一個動畫類,然后使用修改元素的BeginAnimation()方法,所有wpf元素,從UIElement基類開始,都繼承了BeginAnimation()方法,該方法是IAnimatable接口的一部分。

 xaml代碼: 

<Button Width="150" Height="60" Grid.Row="0" Click="Button_Click">點擊開始動畫</Button>
<Button Grid.Row="1" Name="btn1" Width="150" Height="60" Content="動畫按鈕"></Button>

 后台代碼:

private void Button_Click(object sender, RoutedEventArgs e) { //實例化一個DoubleAnimation類。
    DoubleAnimation doubleAnimation = new DoubleAnimation(); //設置From屬性。
    doubleAnimation.From = btn1.Width; //設置To屬性。
    doubleAnimation.To = 250; //設置Duration屬性。
    doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5)); //為元素設置BeginAnimation方法。
 btn1.BeginAnimation(Button.WidthProperty, doubleAnimation); }

 效果圖:

其中, From屬性是元素的開始值,To屬性是元素屬性的結束值,Duration是整個動畫執行的時間。即使不使用To屬性,也可以使用By屬性,By值被簡單地增加到From值上,使其達到To值。不過,對於非數值數據類型來說,By屬性是沒有意義的。

4、同時發生的動畫。

就是創建多個Animation動畫,然后為元素設置屬性。

后台代碼:

private void Button_Click(object sender, RoutedEventArgs e) { //實例化一個DoubleAnimation類。
    DoubleAnimation doubleAnimation = new DoubleAnimation(); //設置From屬性。
    doubleAnimation.From = btn1.Width; //設置To屬性。
    doubleAnimation.To = 250; //設置Duration屬性。
    doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5)); //為元素設置BeginAnimation方法。
 btn1.BeginAnimation(Button.WidthProperty, doubleAnimation); //實例化一個DoubleAnimation動畫,用於設置元素的高。
    DoubleAnimation doubleAnimationHeight = new DoubleAnimation(); //設置Form屬性。
    doubleAnimationHeight.From = btn1.Height; //設置To屬性的值。
    doubleAnimationHeight.By = 70; //設置時間。
    doubleAnimationHeight.Duration = new Duration(TimeSpan.FromSeconds(3)); //開始動畫。
 btn1.BeginAnimation(Button.HeightProperty, doubleAnimationHeight); }

 5、動畫的生命周期。

從技術的角度看,WPF動畫只是暫時的,這意味着它們不能真正改變基本屬性的值,當動畫處於活動狀態時,只是覆蓋了屬性的值。

單向動畫,在動畫運行結束后會保持處於活動狀態,這是因為動畫需要將按鈕的寬度保持為新值,這回導致如下常見問題,如果嘗試使用代碼在動畫完成后修改屬性值,代碼將不會起作用,因為代碼只是為屬性指定了一個新的本地值,但仍會先試用動畫之后的屬性值。

為了解決動畫完成后能修改屬性的值,有以下方法可解決。

a)、設置AutoReverse屬性,如果將該屬性設置為true,將會反向運動,返回原始的值(不適合動畫完成后,再為屬性設置最后的值,只是還原為動畫之前的值)。

b)、改變FillBehavior屬性。通常,FillBehavior屬性設置為HoldEnd,這意味着當當動畫結束時,會繼續為目標元素應用最后的值。如果將FillBehavior屬性改為Stop,只要動畫結束,屬性就會恢復為原來的值(適用於動畫結束后,再次為其設置新值,一般不與AutoReverse配合着使用,這兩個用其中一個就行了)。

6、動畫的Completed事件。

使用Completed事件時,要將事件設置BeginAnimation()方法之前,否則不起作用。在Completed中,可通過調用BeginAnimation()方法來渲染不活動的動畫,為此,只需要指定屬性,並為動畫對象傳遞null引用。

void doubleAnimationHeight_Completed(object sender, EventArgs e) { MessageBox.Show("動畫的高執行完畢了!!!"); //設置空引用。
    btn1.BeginAnimation(Button.HeightProperty, null); }

 7、TimeLine類。

TimeLine類的常用屬性。

TimeLine類的常用屬性
名稱 說明
BeginTime 設置將被添加到動畫開始之前的延時時間(TimeSpan類型),這一延時總被加載到總時間,具有5秒延時的5秒動畫,總時間是10秒。
Duration 動畫開始到結束的運行時間。
SpeedRatio 提高或減慢動畫速度。SpeedRatio屬性值是1,如果增加該屬性值為5,動畫的速度就會變成原來的5倍。

AcclerationRatio
DecelerationRatio

使動畫不是線性的,從而開始時較慢,或者開始時較快,這兩個屬性的值都在0~1之間,這兩個屬性值之和不能超過1。
AutoReverse 如果為true,當動畫完成時會自動反向播放,返回到原始值。
FillBehavior 決定當動畫結束時,如何操作。
RepeatBehavior 通過該屬性,可以使用指定的次數或時間間隔重復動畫,用於設置這個屬性的RepeatBehavior對象決定了確切的行為。

 

 

 

 

 

 

 

 

 

 

 

 

7.1)、AccelerationRatio和DeceleRation屬性。

可以通過AcclerationRation和DecelerationRation屬性壓縮部分時間軸,使動畫運行的更快,並將拉伸其他時間進行補償,使總時間保持不變這兩個屬性都表示百分比值,例如,將AcceleRation屬性設置為0.3,表示希望使用動畫持續時間中前30%的時間進行加速。例如在1個10秒的動畫中,前3秒會加速運行,而剩余的7秒會以恆定不變的速度運行,如果將DeceleRation屬性設置為0.3,那么最后3秒回減速運行。

private void Button_Click(object sender, RoutedEventArgs e) { //實例化一個DoubleAnimation類。
    DoubleAnimation doubleAnimation = new DoubleAnimation(); //設置From屬性。
    doubleAnimation.From = btn1.Width; //前5秒加速度運行。
    doubleAnimation.AccelerationRatio = 0.5; //后2秒減速運行
    doubleAnimation.DecelerationRatio = 0.2; //設置To屬性。
    doubleAnimation.To = 1000; //設置Duration屬性。
    doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(10)); //為元素設置BeginAnimation方法。
 btn1.BeginAnimation(Button.WidthProperty, doubleAnimation); }

 7.2)、RepeatBehavior屬性。

使用RepeataBehavior屬性可以控制如何重復運行動畫,如果希望重復固定次數,應為RepeatBehavior構造函數傳遞合適的次數。

還可設置RepeatBehavior為永久重復。 

//設置重復次數為3次。
doubleAnimation.RepeatBehavior = new RepeatBehavior(3); //設置永久重復動畫。
doubleAnimation.RepeatBehavior = RepeatBehavior.Forever;

 8、故事版。

WPF動畫通過一組動畫類表示,使用少數幾個屬性設置相關信息,如開始值、結束值以及持續時間。這顯然使他們非常適合於XAMl,不是很清晰的是,如何為特定的事件和屬性關聯動畫,以及如何在正確的時間觸發動畫。

故事板:故事板是BeginAnimation()方法的XAML等價物,通過故事板將動畫指定到合適的元素和屬性。

事件觸發器:事件觸發器響應屬性變化或事件(如按鈕的Click事件),並控制故事板。

故事板:

故事板是增強的時間線,可用來分組多個動畫,而且具有控制動畫播放的能力---暫停、停止以及播放位置。然而Storyboard類提供的最基本功能是,能夠使用TargetProperty和TargetName屬性指向某個特定屬性和特定元素,換句話說,故事板在動畫和希望應用動畫的屬性之間架起了一座橋梁。其中TargetProperty屬性和TargetName屬性都是附加屬性。 

<!--創建一個故事板-->
<Storyboard Storyboard.TargetProperty="Width">
    <!--創建一個DoubleAnimation類。-->
    <DoubleAnimation To="350" RepeatBehavior="Forever" Duration="0:0:3"></DoubleAnimation>
</Storyboard>

<!--由於Storyboard.TargetProperty屬性是附加屬性,因此還可以寫出-->
<Storyboard >
    <!--創建一個DoubleAnimation類。-->
    <DoubleAnimation Storyboard.TargetProperty = "Width" To="350" RepeatBehavior="Forever" Duration="0:0:3"></DoubleAnimation>
</Storyboard>

 事件觸發器:

可以在以下4個位置定義事件觸發器。

a)、在樣式中(Style.Triggers集合)。

b)、在數據模板中(DataTemplate.Triggers集合)。

c)、在控件模板中(ControlTemplate.Triggers集合)。

d)、直接在元素中定義事件觸發器(FrameworkElement.Triggers集合)。

當創建事件觸發器時,需要指定開始觸發器的路由事件和觸發器執行的一個或多個動作。對於動畫,最常用的動作是BeginStoryboard,該動作相當於調用BeginAnimation()方法。所有事件觸發器都可以啟動動作,所有動作都由繼承自System.Windows.TriggerAction的類表示

xaml代碼:

<Button Width="200" Height="80" Content="事件觸發器" FontSize="20">
    <!--元素觸發器-->
    <Button.Triggers>
        <!--定義事件觸發器-->
        <EventTrigger RoutedEvent="Button.Click">
            <!--執行一個動作-->
            <EventTrigger.Actions>
                <!--開始故事板-->
                <BeginStoryboard>
                    <!--創建一個故事板-->
                    <Storyboard >
                        <!--創建一個DoubleAnimation類。-->
                        <DoubleAnimation Storyboard.TargetProperty = "Width" To="350" RepeatBehavior="Forever" Duration="0:0:3"></DoubleAnimation>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger.Actions>
        </EventTrigger>
    </Button.Triggers>
</Button>

 效果圖:

9、使用樣式關聯觸發器。

有三種基本類型的WPF觸發器:屬性觸發器、數據觸發器以及事件觸發器。使用觸發器是關聯動畫的最常用方式,但並不是唯一的選擇。

xaml代碼: 

<Window.Resources>
    <Style TargetType="Button">
        <Setter Property="FontSize" Value="20"></Setter>            
        <Style.Triggers>
            <!--使用屬性觸發器-->
            <Trigger Property="IsPressed" Value="True">
                <!--在這里使用的是EnterActions-->
                <Trigger.EnterActions>
                    <BeginStoryboard>
                        <Storyboard Storyboard.TargetProperty="Width">
                            <DoubleAnimation To="300" RepeatBehavior="Forever" Duration="0:0:3"></DoubleAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </Trigger.EnterActions>
            </Trigger>
    </Style>
</Window.Resources>

<Grid>
    <Button Width="200" Height="80" Content="使用樣式關聯觸發器"></Button>
</Grid>        

效果圖:

 10、同步的動畫。

StoryBoard類間接地繼承自TimeLineGroup類,所以StoryBoard類能包含多個動畫,這些動畫可以作為一組進行管理,這意味着它們可以在同一時間開始。

<Window.Resources>
    <Style TargetType="Button">            
        <Setter Property="FontSize" Value="20"></Setter>            
        <Style.Triggers>
            <Trigger Property="IsPressed" Value="True">
                <Trigger.EnterActions>
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetProperty="Width" To="300" Duration="0:0:3"></DoubleAnimation>
                            <DoubleAnimation Storyboard.TargetProperty="Height" To="100" Duration="0:0:3"></DoubleAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </Trigger.EnterActions>
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>
    
<Grid>
    <Button Width="150" Height="70" Content="同步動畫"></Button>
</Grid>

效果圖:

 11、控制播放。

到目前為止,已經在事件觸發器中使用了一個動作,加載動畫的BeginStoryboard動作,然而,一旦創建故事版,就可以使用其他動作控制故事板,這些動作類都繼承自ControllableStoryboardAction類,控制故事版的主要類如下:

控制故事板的動作類
名稱 說明
PauseStoryboard 停止播放動畫並且保持當前位置
ResumeStoryboard 恢復播放暫停的動畫。
StopStoryboard 停止播放動畫,並將動畫時鍾重新設置到開始位置。
SeekStoryboard

跳到動畫時間線中的特定位置,如果當前動畫正在播放,就繼續從新位置播放。如果當前動畫
是暫停的,就繼續保持暫停。

SetStoryboardSpeedRatio 改變整個故事板的SpeedRatio屬性值。
SkipStoryboardToFill 將故事板移動到時間線的終點。FillBehavior屬性設置為HoldEnd,動畫繼續保持最后的值。
RemoveStoryboard 移除故事板,停止所有正在運行的動畫,並將屬性返回為原來的、最后一次設置的數值。

 

 

 

 

 

 

 

 

 

 

 

 

 

為成功地執行這些動作,必須在同一個Triggers集合中定義所有的觸發器,如果將BeginStoryboard動作的觸發器和PauseStoryboard動作的觸發器放置到不同的集合中,PauseStoryboard動作就無法工作。

xaml代碼: 

<Window x:Class="控制播放.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525">
    <Window.Triggers>
        <!--開始事件-->
        <EventTrigger RoutedEvent="Button.Click" SourceName="btn_start">
            <BeginStoryboard Name="beginstoryboard1">
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="img" Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:6"></DoubleAnimation>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>

        <!--停止動畫-->
        <EventTrigger RoutedEvent="Button.Click" SourceName="btn_pause">
            <PauseStoryboard BeginStoryboardName="beginstoryboard1"></PauseStoryboard>
        </EventTrigger> 
        
        <!--恢復動畫-->
        <EventTrigger RoutedEvent="Button.Click" SourceName="btn_resume">
            <ResumeStoryboard BeginStoryboardName="beginstoryboard1"></ResumeStoryboard>
        </EventTrigger>
        
        <!--停止動畫-->
        <EventTrigger RoutedEvent="Button.Click" SourceName="btn_stop">
            <StopStoryboard BeginStoryboardName="beginstoryboard1"></StopStoryboard>
        </EventTrigger>

        <!--移除動畫-->
        <EventTrigger RoutedEvent="Button.Click" SourceName="btn_remove">
            <RemoveStoryboard BeginStoryboardName="beginstoryboard1"></RemoveStoryboard>
        </EventTrigger>        
    </Window.Triggers>
    
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="3*"></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>   
        
        <Image Name="img" Source="1.jpg"></Image>
        
        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <Button Name="btn_start" Content="開始" Margin="10" FontSize="20" Grid.Column="0"></Button>
            <Button Name="btn_pause" Content="暫停" Margin="10" FontSize="20" Grid.Column="1"></Button>
            <Button Name="btn_resume" Content="恢復" Margin="10" FontSize="20" Grid.Column="2"></Button>
            <Button Name="btn_stop" Content="停止" Margin="10" FontSize="20" Grid.Column="3"></Button>
            <Button Name="btn_remove" Content="移除" Margin="10" FontSize="20" Grid.Column="4"></Button>
        </Grid>
    </Grid>
</Window>

效果圖:

 分析:在包含元素的Triggers集合中(在這里是Window.Triggers集合),使用EventTrigger.SourceName屬性關聯這些事件觸發器,只要SourceName屬性和為按鈕設置的Name屬性相匹配,觸發器就會用到恰當的按鈕上。還必須要問BeginStoryboard動作指定名稱,這樣其他觸發器BeginStoryboardName屬性指定這個名稱,連接到相同的故事板,然后進行控制。

12、故事板事件。

故事板事件
Completed 動畫已經到達終點
CurrentGlobalSpeedInvalidated 速度發生了變化,或者動畫被暫停、重新開始、停止或移到某個新的位置。
CurrentStateInvalidated 動畫已經開始或結束。
CurrentTimeInvalidated 動畫時鍾已經向前移動了一個步長,正在更改動畫。當動畫開始、停止或結束時也會引發該事件。
RemoveRequested 動畫正在被移除。

 

 

 

 

 

 

 

 

監視動畫進度:

如果要監視動畫,要用到Storyboard的一些事件。在這里使用的是CurrentTimeInvalidated事件,每次向前移動動畫時鍾都會引發該事件。當引發CurrentTimeInvalidated事件時,發送者是Clock對象(Color類位於System.Windows.Media.Animation名稱空間中),可通過Clock對象檢索當前時間。當前時間使用TimeSpan對象表示,並且可檢索當前進度,當前進度使用0~1之間的數值表示。

后台代碼:

就是在上面的例子中為故事板加一個CurrentTimeInvalidated事件,然后再界面中放一個label控件(用於顯示時間)和ProgressBar(用於顯示進度,最大值為1,最小值為0)控件。 

private void Storyboard_CurrentTimeInvalidated(object sender, EventArgs e)
{
    Clock storyboardClock = (Clock)sender;
    if (storyboardClock.CurrentProgress == null)
    {
        lblTime.Content = "";
        progressBar1.Value = 0;
    }
    else
    {
        lblTime.Content = storyboardClock.CurrentTime.ToString();
        progressBar1.Value = (double)storyboardClock.CurrentProgress;
    }
}

效果圖:

13、動畫緩動。

線性動畫有一個缺點,通常讓人覺得機械和不夠自然。改進動畫並創建更趨自然的動畫的秘訣是改變變化速率。不是創建以固定不變的速率改變屬性的動畫,而是需要設計根據某種方式加速或減速的動畫,實現更趨自然的動畫的最簡單方法是使用預置的緩動函數(EasingFunction)。EasyingFunction屬性只能接受單個緩動函數對象,所以不能為同一個動畫結合不同的緩動函數。

xaml代碼:

<Window.Resources>
    <Style TargetType="Button">
        <Style.Triggers>
            <EventTrigger RoutedEvent="Click">
                <EventTrigger.Actions>
                    <BeginStoryboard>
                        <Storyboard Storyboard.TargetProperty="Width">
                            <DoubleAnimation To="300" Duration="0:0:5">
                                <!--使用緩動函數-->
                                <DoubleAnimation.EasingFunction>
                                    <!--設置緩動模式和振盪次數-->
                                    <ElasticEase EasingMode="EaseOut" Oscillations="5"></ElasticEase>
                                </DoubleAnimation.EasingFunction>
                            </DoubleAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger.Actions>
            </EventTrigger>
        </Style.Triggers>
    </Style>
</Window.Resources>   
<Grid>
     <Button Width="150" Height="50" Content="緩動動畫" FontSize="20"></Button>
</Grid>    

效果圖:

14、緩動函數類。

在繼續分析不同的緩動類之前,理解緩動函數的應用時機是很重要的。所有的緩動函數類都繼承自EasingFunctionBase類,並且繼承了EasingMode屬性,EasingMode有三種值,分別是:EasyIn(在動畫開始時應用緩動效果)、EasyOut(動畫結束時應用緩動效果)和EasyInOut(在開始和結束時應用緩動動畫)。當應用緩動函數時不會改變動畫的持續時間。

緩動函數常用類
名稱 說明 屬性
BackEase

當使用EaseIn模式應用該緩動函數時,在動畫開始之前拉回動畫,當使用EaseOut模式應用該緩動函數時,允許動畫稍微超越,然后拉回。

Amplitude屬性決定了拉回和超越的量。默認值是1,可減小該屬性值(大於0的任何值)以縮減效果,或增加該屬性值放大效果。
ElasticEase 當使用EaseOut模式應用該緩動函數時,使動畫超越其最大值並前后擺動,逐漸減慢。當時用EaseIn模式應用該緩動函數時,動畫在其開始值周圍前后擺動,逐漸增加。 Oscillations屬性控制動畫前后擺動的次數。
BounceEase 執行與Elastic緩東函數類似的效果,只是彈跳永遠不會超越初始值或最終值。 Bounce屬性控制動畫回調的次數(默認是2)
CircleEase 使用圓函數加速(使用EaseIn模式),或減速(使用EaseOut模式)
CublicEase 使用基於時間立方的函數加速,其效果與Circle類似,但是加速效果更緩和。
QuadraticEase 使用基於時間平方的函數加速,效果與CublicEase類似,但加速過程更明顯。
QuarticEase  
QuinticEase  
SinEase  
PowerEase   Power
ExponentialEase   Exponent

 15、自定義緩動函數。

創建自定義緩動函數一般需要以下幾個步驟:

a)、新建一個類,讓其繼承自EasingFunctionBase類。

b)、重寫EaseInCore()方法和CreateInstanceCore()方法。

c)、定義依賴屬性。

d)、引用。

 后台代碼(自定義類): 

public class RandomJitterEase : EasingFunctionBase { //聲明一個Random類,用於聲明隨機數。
    Random rand = new Random(); /// <summary>
    /// 重寫EaseCore方法。 /// </summary>
    /// <param name="normalizedTime"></param>
    /// <returns></returns>
    protected override double EaseInCore(double normalizedTime) { //幾乎所有邏輯代碼都在EaseInCore方法中運行。該方法接受一個規范化的時間值,本質上是表示動畫進度從 //0到1之間的值,當動畫開始時,規范化的時間值是0,它從該點開始增加,直到在動畫結束點達到1. //在動畫運行期間,每次更新動畫的值時,WPF都會調用EaseInCore方法,確切的調用頻率取決於動畫的幀率。
        if (normalizedTime == 1) { return 1; } else { return Math.Abs(normalizedTime - (double)rand.Next(0, 10) / (2010 - Jitter)); } } protected override System.Windows.Freezable CreateInstanceCore() { return new RandomJitterEase(); } //定義一個依賴屬性。
    public static readonly DependencyProperty JitterProperty; //在靜態方法中注冊依賴屬性。
    static RandomJitterEase() { JitterProperty = DependencyProperty.Register("Jitter", typeof(int), typeof(RandomJitterEase), new UIPropertyMetadata(1000), new ValidateValueCallback(ValidateJitter)); } public int Jitter { get { return (int)GetValue(JitterProperty); } set { SetValue(JitterProperty, value); } } //此方法用於判斷值。
    private static bool ValidateJitter(object value) { int jitterValue = (int)value; if (jitterValue <= 2000 && jitterValue >= 0) { return true; } else { return false; } } }

 xaml代碼:

<Window x:Class="自定義緩動函數.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:自定義緩動函數" Title="MainWindow" Height="350" Width="525">
    
    <Window.Triggers>
        <!--事件觸發器,窗體加載的Loaded事件。-->
        <EventTrigger RoutedEvent="Window.Loaded">
            <EventTrigger.Actions>
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetName="ellipse1" Storyboard.TargetProperty="(Canvas.Left)" From="0" To="480" Duration="0:0:5"></DoubleAnimation>
                        <DoubleAnimation Storyboard.TargetName="ellipse2" Storyboard.TargetProperty="(Canvas.Left)" From="0" To="480" Duration="0:0:5">
                            <DoubleAnimation.EasingFunction>
                                <!--調用自定義緩動函數類-->
                                <local:RandomJitterEase EasingMode="EaseIn" Jitter="1500"></local:RandomJitterEase>
                            </DoubleAnimation.EasingFunction>
                        </DoubleAnimation>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger.Actions>
        </EventTrigger>
    </Window.Triggers>        
        
    <Canvas ClipToBounds="True">
        <Ellipse Name="ellipse1" Width="25" Height="25" Fill="Red"></Ellipse>
        <Ellipse Margin="0,70,0,0" Name="ellipse2" Width="25" Height="25" Fill="Green"></Ellipse>
    </Canvas>    
</Window>

效果圖:

16、WPF動畫性能和幀率。

通常,為用戶界面應用動畫,只不過是創建並配置正確的動畫和故事版對象。但在其他情況下,特別是同時發生多個動畫時,可能更加需要關注性能。WPF試圖保持以60幀/秒的速度進行動畫,可以確保從開始到結束得到平滑流暢的動畫。幀速率越低,會發生抖動現象。幀速率越高,占用的CPU也就越高。通過TimeLine.DesiredFrameRate屬性進行調整。

xaml代碼:

 

<Window x:Class="動畫性能之幀率.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:動畫性能之幀率" Title="MainWindow" Height="500" Width="525">    
    <Window.Triggers>
        <!--定義一個事件觸發器,通過SourceName屬性關聯button-->
        <EventTrigger RoutedEvent="Button.Click" SourceName="btn_start">
            <EventTrigger.Actions>
                <BeginStoryboard>
                    <!--通過Timeline.DesiredFrameRate屬性設置幀速率-->
                    <Storyboard Storyboard.TargetName="ellipse" Timeline.DesiredFrameRate="{Binding ElementName=txtBox1, Path=Text}">
                        <DoubleAnimation Storyboard.TargetProperty="(Canvas.Top)" From="0" To="300" Duration="0:0:10"></DoubleAnimation>
                        <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="0" To="250" Duration="0:0:10"></DoubleAnimation>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger.Actions>
        </EventTrigger>
    </Window.Triggers>    
    
    <Grid ShowGridLines="False">
        <Grid.RowDefinitions>
            <RowDefinition Height="5*"></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>            
        </Grid.RowDefinitions>
        
        <Grid.ColumnDefinitions >
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>  
        
        <Canvas ClipToBounds="True" Grid.Row="0" Grid.ColumnSpan="2" Height="320" Background="Beige">
            <Ellipse Name="ellipse" Fill="Red" Width="10" Height="10"></Ellipse>
        </Canvas>
<Label Grid.Row="1" Content="幀速率:" FontSize="20" HorizontalAlignment="Right" VerticalAlignment="Center"></Label> <TextBox Name="txtBox1" Text="1" Width="60" Height="30" FontSize="20" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center"></TextBox> <Button Name="btn_start" Grid.Row="2" Grid.ColumnSpan="2" Width="200" Height="60" Content="點擊動畫" FontSize="20"></Button> </Grid> </Window>

 

效果圖:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM