一般,爲用戶界面應用動畫只不過是建立並配置正確的動畫和故事板對象。但在其餘狀況下,特別是同時發生多個動畫時,可能須要更加關注性能。特定的效果更可能致使這些問題——例如,那些涉及視頻、大位圖以及多層透明等的效果一般須要佔用更多CPU開銷。若是不謹慎實現這類效果,運行它們使可能形成明顯抖動,或者會從其餘同時運行的應用程序搶佔CPU時間。緩存
幸運的是,WPF提供了幾個可提供幫助的技巧。接下來的幾節將學習下降最大幀率以及緩存計算機顯卡中的位圖,這兩種技術能夠減輕CPU的負擔。安全
1、指望的幀率佈局
正如前面所學習的,WPF試圖保持以60幀/秒的速度運動動畫。這樣可確保從開始到結束獲得平滑流暢的動畫。固然,WPF可能達不到這個目標。若是同時運行多個複雜的動畫,而且CPU或顯卡不能承受的話,整個幀率可能會降低(最好的情形),甚至可能會跳躍以進行補償(最壞的情形)。性能
儘管不多提升幀率,但可能會選擇下降幀率,這多是由於如下兩個緣由之一:學習
調整幀率很容易。只須要爲包含動畫的故事板使用Timeline.DesiredFrameRate附加屬性。下面的示例將幀率減半:測試
<Storyboard Timeline.DesiredFrameRate="30">
下圖顯示了一個簡單的測試程序,該程序爲一個小球應用動畫,使其在Canvas控件上沿一條曲線運動。動畫
這個應用程序開始在Canvas上繪製Ellipse對象。Canvas.ClipToBounds屬性被設置爲true,因此圓的邊緣不會超出Canvas控件的邊緣而進入窗口的其餘部分。spa
<Canvas ClipToBounds="True"> <Ellipse Name="ellipse" Fill="Red" Width="10" Height="10"></Ellipse> </Canvas>
爲在Canvas控件上移動圓,須要同時進行兩個動畫——一個動畫用於更新Canva.Left屬性(從左向右移動圓),另外一個動畫用於改變Canvas.Top屬性(使圓上升,而後降低)。Canvas.Top動畫是可反轉的——一旦圓達到最高點,就會降低。Canvas.Left動畫不是可反轉的,但持續時間是Canvas.Top動畫的兩倍,從而使得這兩個動畫能夠同時移動圓。最後的技巧是爲Canvas.Top動畫使用DeceleartionRatio屬性。這樣,當圓達到最高點是上升的速度會更慢,這會建立更逼真的效果。3d
下面是動畫的完整標記:code
<Window.Resources> <BeginStoryboard x:Key="beginStoryboard"> <Storyboard Timeline.DesiredFrameRate="{Binding ElementName=txtFrameRate,Path=Text}"> <DoubleAnimation Storyboard.TargetName="ellipse" Storyboard.TargetProperty="(Canvas.Left)" From="0" To="300" Duration="0:0:5"> </DoubleAnimation> <DoubleAnimation Storyboard.TargetName="ellipse" Storyboard.TargetProperty="(Canvas.Top)" From="300" To="0" AutoReverse="True" Duration="0:0:2.5" DecelerationRatio="1"> </DoubleAnimation> </Storyboard> </BeginStoryboard> </Window.Resources>
這個示例的真正目的是嘗試不一樣的幀率。爲查看某個特定幀率的效果,只須要在文本框中輸入合適的數值,而後單擊Repeat按鈕便可。而後動畫就會使用新的幀率(經過數據綁定表達式獲取新的幀率)觸發,從而能夠觀察動畫的效果。在更低的幀率下,橢圓不會均勻移動——而會在Cavans控件中的跳躍。
也可以使用代碼調整Timeline.DesiredFrame屬性。例如,可能但願讀取靜態屬性RenderCapability.Tier以肯定顯卡支持的渲染級別。
2、位圖緩存
位圖緩存通知WPF獲取內容的當前位圖圖像,並將其複製到顯卡的內存中。這時,顯卡能夠控制位圖的操做和顯示的刷新。這個處理過程比讓WPF完成全部工做要快不少,而且和顯卡不斷通訊。
若是運用得當,位圖緩存能夠改善應用程序的繪圖性能。但若是運用不當,就會浪費顯存而且實際上會下降性能。因此,在使用位圖緩存以前,須要確保真正合適。下面列出一些指導原則:
爲更好地理解位圖緩存,使用一個簡單示例是有幫助的,下圖例舉一個示例,一個動畫推進一個簡單的圖像——正方形——在Canvas面板上移動,Canvas面板包含一條具備複雜集合圖形的路徑。但正方形在Canvas面板表面上移動時,強制WPF從新計算路徑並填充丟失的部分。這會帶來極大的CPU負擔,而且動畫甚至可能開始變得斷斷續續。
可採用幾種方法解決該問題。一種選擇是使用一幅位圖替換背景,WPF可以更高效地管理位圖。更靈活的選擇是使用位圖緩存,這種方法可繼續將存活的、可交互的元素做爲背景。
爲啓用位圖緩存功能,將相應元素的CacheMode屬性設置爲BitmapCache。每一個元素都提供了CacheMode屬性,這意味着能夠精確選擇爲哪一個元素使用這一特徵。
<Path CacheMode="BitmapCache" ...></Path>
經過這個簡單修改,可當即看到區別。首先,窗口顯示的事件要稍長一些。但動畫的運行將更平滑,而且CPU的負擔將顯著下降。可經過Windows任務管理器進行檢查——常常能夠看到CPU的負擔從接近100%減小到20%一下。
一般,當啓用位圖緩存時,WPF採用元素當前尺寸的快照並將其位圖複製到顯卡中。若是以後使用ScaleTransform放大元素,這會變成一個問題。在這種狀況下,將放大緩存的位圖,而不是實際的元素,當放大元素時這會致使模糊放大以及色塊。
例如,設想一個修訂過的示例。在這個示例中,第二個同步動畫擴展Path使其爲原始尺寸的10倍,而後縮回原始尺寸。爲確保具備良好的顯示質量,可以使用5倍於Path原始尺寸的尺寸緩存其位圖:
<Path ...> <Path.CacheMode> <BitmapCache RenderAtScale="5"></BitmapCache> </Path.CacheMode> </Path>
這樣可解決像素化問題。雖然緩存的位圖仍比Path的最大動畫尺寸(最大尺寸達10倍於其原始尺寸)小,但顯卡能使位圖的尺寸加倍,從5倍到10倍,而不會有任何明顯的縮放問題。更重要的是,這可以使應用避免過多地使用顯存。