小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

【W(wǎng)PF學(xué)習(xí)】第五十一章 動(dòng)畫緩動(dòng)

 小仙女本仙人 2021-04-13

  線性動(dòng)畫的一個(gè)缺點(diǎn)是,它通常讓人覺(jué)得很機(jī)械且不能夠自然。相比而言,高級(jí)的用戶界面具有模擬真實(shí)世界系統(tǒng)的動(dòng)畫效果。例如,可能使用具有觸覺(jué)的下壓按鈕,當(dāng)單擊時(shí)按鈕快速?gòu)椈?,但是?dāng)沒(méi)有進(jìn)行操作時(shí)它們會(huì)慢慢地停下來(lái),創(chuàng)建真正移動(dòng)的錯(cuò)覺(jué)?;蛘?,可能使用類似Windows操作系統(tǒng)的最大化和最小化效果,當(dāng)窗口解決最終尺寸時(shí)窗口擴(kuò)展或收縮的速度會(huì)加速。這些細(xì)節(jié)十分細(xì)微,當(dāng)它們的實(shí)現(xiàn)比較完美時(shí)可能不會(huì)注意到它們。然而,幾乎總會(huì)注意到,粗糙的缺少這些更細(xì)微特征的動(dòng)畫會(huì)給人留下笨拙的印象。

  改進(jìn)動(dòng)畫并創(chuàng)建更趨自然的動(dòng)畫的秘訣是改變變化速率。不是創(chuàng)建以固定不變的速率改變的屬性的動(dòng)畫,而是需要設(shè)計(jì)根據(jù)某種方式加速或減速的動(dòng)畫。WPF提供了幾種選擇?;趲膭?dòng)畫和關(guān)鍵幀動(dòng)畫,這兩種技術(shù)都提供了更精細(xì)地控制動(dòng)畫的能力。但實(shí)現(xiàn)更趨自然的動(dòng)畫的最簡(jiǎn)單方法是使用預(yù)置的緩動(dòng)函數(shù)(easing function)。

  當(dāng)使用緩動(dòng)函數(shù)時(shí),仍可通過(guò)指定開(kāi)始和結(jié)束屬性值以常規(guī)的方式定義動(dòng)畫。但為了附加這些細(xì)節(jié),需要添加預(yù)先編寫好的修改動(dòng)畫過(guò)場(chǎng)的數(shù)學(xué)函數(shù),使動(dòng)畫在不同的點(diǎn)加速或減速。

一、使用緩動(dòng)函數(shù)

  動(dòng)畫緩動(dòng)的最大優(yōu)點(diǎn)是,相對(duì)于其他方法,如基于幀的動(dòng)畫和關(guān)鍵幀動(dòng)畫,這種方法需要的工作少很多。為使用動(dòng)畫緩動(dòng),使用某個(gè)緩動(dòng)函數(shù)類(繼承自EasingFunctionBase的類)的實(shí)例設(shè)置動(dòng)畫對(duì)象的EasingFunction屬性。通常需要設(shè)置緩動(dòng)函數(shù)的幾個(gè)屬性,并且為了得到所希望的效果,可能必須使用不同的設(shè)置,但不需要編寫代碼并且只需很少的XAML。

  例如,分析下面給出的兩個(gè)動(dòng)畫,這兩個(gè)動(dòng)畫用于按鈕。當(dāng)用戶將鼠標(biāo)移到按鈕上時(shí),使用一小段代碼調(diào)用growStoryboard動(dòng)畫,將按鈕拉伸到400單位。當(dāng)用戶移動(dòng)鼠標(biāo)使其離開(kāi)按鈕時(shí),按鈕收縮到其正常尺寸。

<Storyboard x:Name="growStoryboard">
   <DoubleAnimation Storyboard.TargetName="cmdGrow" Storyboard.TargetProperty="Width"
             To="400" Duration="0:0:1.5"></DoubleAnimation>
</Storyboard>
<Storyboard x:Name="revertStoryboard">
    <DoubleAnimation Storyboard.TargetName="cmdGrow" Storyboard.TargetProperty="Width"
            Duration="0:0:3"></DoubleAnimation>
</Storyboard>

  現(xiàn)在,動(dòng)畫使用線性插值,這意味著按鈕以恒定的機(jī)械性的速度增長(zhǎng)和收縮。為得到更趨自然的效果,可使用緩動(dòng)函數(shù)。下面的示例添加了名為ElasticEase的緩動(dòng)函數(shù)。最終效果是按鈕彈跳出其完整寬度,然后迅速?gòu)椈匾稽c(diǎn),接著在此擺動(dòng)超出其完整尺寸(但比上一次稍少一點(diǎn)),再以稍小的幅度迅速?gòu)椈?,等等,隨著運(yùn)動(dòng)的減弱不斷地重復(fù)這一跳動(dòng)模式。之后逐漸進(jìn)入緩和的10此振蕩。Oscillations屬性控制最終跳動(dòng)的次數(shù)。ElasticEase類提供了另一個(gè)在該例中沒(méi)有使用的屬性:Springiness。該屬性的值越大,后續(xù)的每個(gè)振蕩?kù)o止得越快(默認(rèn)值是3)。

<Storyboard x:Name="growStoryboard">
    <DoubleAnimation Storyboard.TargetName="cmdGrow" Storyboard.TargetProperty="Width"
                                     To="400" Duration="0:0:1.5">
           <DoubleAnimation.EasingFunction>
                  <ElasticEase Oscillations="10" EasingMode="EaseOut"></ElasticEase>
            </DoubleAnimation.EasingFunction>
      </DoubleAnimation>
</Storyboard>

  為真正理解該標(biāo)記和前面緩動(dòng)函數(shù)的示例之間的區(qū)別,需要試一下該動(dòng)畫。變化是顯著的。僅時(shí)候用一行XAML,就將一個(gè)簡(jiǎn)單的動(dòng)畫從業(yè)務(wù)的效果修改為精致美觀的效果,在專業(yè)的應(yīng)用程序中會(huì)感覺(jué)到這種精致效果。

二、在動(dòng)畫開(kāi)始時(shí)應(yīng)用緩動(dòng)與動(dòng)畫結(jié)束時(shí)應(yīng)用緩動(dòng)

  在繼續(xù)分析不同的緩動(dòng)函數(shù)前,理解緩動(dòng)函數(shù)的應(yīng)用時(shí)機(jī)很很重要的。所有緩動(dòng)函數(shù)類都繼承自EasingFunctionBase類,并且繼承了EasingMode屬性。該屬性具有三個(gè)可能值:EaseIn(該值意味著在動(dòng)畫開(kāi)始時(shí)應(yīng)用緩動(dòng)效果)、EaseOut(該值意味著在動(dòng)畫結(jié)束時(shí)應(yīng)用緩動(dòng)效果)、EaseInOut(該值意味著在動(dòng)畫開(kāi)始和結(jié)束時(shí)應(yīng)用緩動(dòng)效果——將EaseIn用于動(dòng)畫的前半部分,將EaseOut用于動(dòng)畫的后半部分)。

  在上面的示例中,growStoryboard中的動(dòng)畫使用EaseOut模式。因此,逐漸減弱的跳動(dòng)序列發(fā)生于動(dòng)畫的末尾。

  如果將ElasticEase函數(shù)的緩動(dòng)模式切換為EaseIn,跳動(dòng)將在動(dòng)畫的開(kāi)始部分發(fā)生。按鈕手勢(shì)使其寬度比開(kāi)始值更小一點(diǎn),然后擴(kuò)展寬度使其超過(guò)開(kāi)始值,繼而再稍多地收縮回一點(diǎn),持續(xù)這種模式以逐漸地增加振蕩直到自由振蕩并擴(kuò)展剩余的部分(使用ElasticEase.Osicillations屬性控制振蕩次數(shù))。

  最后,EaseInOut模式創(chuàng)建更新穎的效果,在動(dòng)畫的前半部分是振蕩動(dòng)畫的開(kāi)始,接下來(lái)在動(dòng)畫的后半部分是振蕩動(dòng)畫的結(jié)束。

三、緩動(dòng)函數(shù)類

  WPF提供了11個(gè)緩動(dòng)函數(shù)類,所有這些類都位于熟悉的System.Windows.Media.Animation名稱控件中。下表描述了所有緩動(dòng)函數(shù)類,并列出了它們的重要屬性。請(qǐng)記住,每個(gè)緩動(dòng)函數(shù)類還提供了EasingMode屬性,用于控制是影響動(dòng)畫的開(kāi)始(EaseIn)、是影響動(dòng)畫的結(jié)束(EaseOut)還是同時(shí)影響動(dòng)畫的開(kāi)始和結(jié)束(EaseInOut)。

表 緩動(dòng)函數(shù)

 名    稱    說(shuō)     明    屬    性
BackEase 當(dāng)使用EaseIn模式應(yīng)用該緩動(dòng)函數(shù)時(shí),在動(dòng)畫開(kāi)始之前來(lái)回動(dòng)畫。當(dāng)使用EaseOut模式應(yīng)用該緩動(dòng)函數(shù)時(shí),允許動(dòng)畫稍微超越然后拉回 Amplitude屬性決定了拉回和超越的量。默認(rèn)值是1,可減少該屬性值(大于0的任何值)以縮減效果,或增加該屬性值以放大效果
ElasticEase 當(dāng)使用EaseOut模式應(yīng)用緩動(dòng)函數(shù)時(shí),使動(dòng)畫超越其最大值并前后擺動(dòng),逐漸減慢。當(dāng)使用EaseIn模式應(yīng)用該緩動(dòng)函數(shù)時(shí),動(dòng)畫在其開(kāi)始值周圍前后擺動(dòng),逐漸增加 Oscillations屬性控制動(dòng)畫前后擺動(dòng)的次數(shù)(默認(rèn)值是3),Springiness屬性控制振蕩增加或減弱的速度(默認(rèn)值是3)
BounceEase 執(zhí)行與ElasticEase緩動(dòng)函數(shù)類似的效果,只是彈跳永遠(yuǎn)不會(huì)超越初始值或最終值 Bounce屬性控制動(dòng)畫回跳的次數(shù)(默認(rèn)值是2),Bounciness屬性決定彈跳增加或減弱的速度(默認(rèn)值是2)
CircleEase 使用圓函數(shù)加速(使用EaseIn模式)或減速(使用EaseOut模式)動(dòng)畫 無(wú)
CubicEase 使用基于時(shí)間立方的函數(shù)加速(使用EaseIn模式)動(dòng)畫。其效果與CircleEase類似,但是加速過(guò)程更緩和 無(wú)
QuadraticEase 使用基于時(shí)間平分的函數(shù)加速(使用EaseIn模式)或減速(使用EaseOut模式)動(dòng)畫。效果與CubicEase類似,但加速過(guò)程更緩和 無(wú)
QuarticEase 使用基于時(shí)間4次方的函數(shù)加速(使用EaseIn模式)或減速(使用EaseOut模式)動(dòng)畫。效果和CubicEase以及QuadraticEase類似,但加速過(guò)程更明顯 無(wú)
QuinticEase 使用基于時(shí)間5次方的函數(shù)加速(使用EaseIn模式)或減速(使用EaseOut模式)動(dòng)畫。效果和CubicEase、QuadraticEase以及QuarticEase類似,但是加速過(guò)程更明顯 無(wú)
SineEase 使用包含正弦計(jì)算的函數(shù)加速(使用EaseIn模式)或減速(使用EaseOut模式)動(dòng)畫。加速非常緩和,并且相對(duì)于其他各種緩動(dòng)函數(shù)更接近線性插值 無(wú)
PowerEase 使用冪函數(shù)f(t)=t^p加速(使用EaseIn模式)或減速(使用EaseOut模式)動(dòng)畫。根據(jù)為指數(shù)p使用的值,可復(fù)制Cubic、QuadraticEase、QuarticEase以及QuinticEase Power屬性用于設(shè)置公式中的指數(shù)。將該屬性設(shè)置為2會(huì)復(fù)制QuadraticEase的效果,設(shè)置為3會(huì)復(fù)制CubicEase的效果。設(shè)置為4會(huì)復(fù)制QuarticEase的效果。設(shè)置為5會(huì)復(fù)制QuinticEase效果,或選擇其他不同值,默認(rèn)值是2
ExponentialEase 使用指數(shù)函數(shù)f(t)=(e(at)-1)/(e(a)-1)加速(使用EaseIn模式)或減速(使用EaseOut模式)動(dòng)畫 Exponent屬性用于設(shè)置指數(shù)(默認(rèn)值是2)

  許多緩動(dòng)函數(shù)提供了類似但隱約不同的效果。為成功地使用動(dòng)畫緩動(dòng),需要決定使用哪個(gè)緩動(dòng)函數(shù),以及如何進(jìn)行配置。通常,這個(gè)過(guò)程需要一點(diǎn)試錯(cuò)的體驗(yàn)。有兩個(gè)資源可提供幫助。

  首先,WPF文檔為每個(gè)緩動(dòng)函數(shù)的行為提供了插圖示例,顯示動(dòng)畫如何隨著時(shí)間修改屬性值。查看這些插圖是理解緩動(dòng)函數(shù)作用的好方法。

  其次,Microsoft提供了幾個(gè)范例程序,可使用這些范例播放不同的緩動(dòng)函數(shù),并嘗試不同的屬性值。最方便的范例之一是Silverlight應(yīng)用程序。

四、創(chuàng)建自定義緩動(dòng)函數(shù)

  通過(guò)從EasingFunctionBase繼承自己的類,并重載EaseInCore()和CreateInstanceCore()方法,可創(chuàng)建自定義緩動(dòng)效果。這是一個(gè)非常專業(yè)的技術(shù),因?yàn)榇蟛糠珠_(kāi)發(fā)人員能通過(guò)配置標(biāo)準(zhǔn)的緩動(dòng)函數(shù)來(lái)獲得所希望的效果。然而,如果確實(shí)決定創(chuàng)建自定義緩動(dòng)函數(shù),將發(fā)現(xiàn)該過(guò)出奇簡(jiǎn)單。

  需要編寫的幾乎所有邏輯都在EaseInCore()方法中運(yùn)行。該方法接受一個(gè)規(guī)范化的時(shí)間值——本質(zhì)上,是表示動(dòng)畫進(jìn)度的從0到1之間的值。當(dāng)動(dòng)畫開(kāi)始時(shí),規(guī)范化得時(shí)間值是0。它從該點(diǎn)開(kāi)始增加,直到在動(dòng)畫結(jié)束點(diǎn)達(dá)到1。

protected override double EaseInCore(double normalizedTime)
{...}

  在動(dòng)畫運(yùn)行期間,每次更新動(dòng)畫的值時(shí)WPF都會(huì)調(diào)用EaseInCore()方法。確切的調(diào)用頻率取決于動(dòng)畫的幀率,但可以預(yù)期每秒調(diào)用EaseInCore()方法的次數(shù)接近60。

  為執(zhí)行緩動(dòng),EaseInCore()方法采用規(guī)范化的時(shí)間值,并以某種方式對(duì)其進(jìn)行調(diào)整。EaseInCore()方法返回的調(diào)整后的值,隨后被用于調(diào)整動(dòng)畫的進(jìn)度。例如,如果EaseInCore()方法返回0,動(dòng)畫被返回到其開(kāi)始點(diǎn)。如果EaseInCore()方法返回1,動(dòng)畫跳到其結(jié)束點(diǎn)。然而,EaseInCore()方法的返回值并不局限于這一范圍——例如,可返回1.5以使動(dòng)畫過(guò)渡運(yùn)行自身50%。已經(jīng)看到過(guò)用于緩動(dòng)函數(shù)(如ElasticEase)的這類效果。

  下面給出的EaseInCore()方法版本根本不執(zhí)行任何工作。該版本返回規(guī)范化的時(shí)間值,意味著動(dòng)畫將均勻展開(kāi),就像是沒(méi)有緩動(dòng)。

protected override double EaseInCore(double normalizedTime)
{
   return normalizedTime;     
}

  下面的EaseInCore()方法版本通過(guò)計(jì)算規(guī)范化時(shí)間值得立方,復(fù)制CubicEase函數(shù)的效果。因?yàn)橐?guī)范化的時(shí)間值是小數(shù),其立方值是更小的小數(shù);所以該方法的效果是最初減慢動(dòng)作動(dòng)畫,并當(dāng)規(guī)范化的時(shí)間值(及其立方值)解決與1時(shí)導(dǎo)致動(dòng)畫加速。

protected override double EaseInCore(double normalizedTime)
        {
            return Math.Pow(normalizedTime, 3);
        }

  最后,下面是一個(gè)執(zhí)行更有趣內(nèi)容的自定義緩動(dòng)函數(shù)——以一定的隨機(jī)量便宜規(guī)范化的時(shí)間值,導(dǎo)致分散的抖動(dòng)效果??墒褂锰峁┑腏itter依賴性屬性(在一個(gè)較小的范圍內(nèi))調(diào)整抖動(dòng)的幅度,該屬性接受從0到2000之間的數(shù)值。

public class RandomJitterEase : EasingFunctionBase
    {

        // Store a random number generator.
        private Random rand = new Random();

        protected override double EaseInCore(double normalizedTime)
        {
            //To see the values add code like this:
            //System.Diagnostics.Debug.WriteLine(...);

            // Make sure there's no jitter in the final value.
            if (normalizedTime == 1) return 1;

            // Offset the value by a random amount.
            return Math.Abs(normalizedTime - (double)rand.Next(0, 10) / (2010 - Jitter));
        }

        public int Jitter
        {
            get { return (int)GetValue(JitterProperty); }
            set { SetValue(JitterProperty, value); }
        }

        public static readonly DependencyProperty JitterProperty =
            DependencyProperty.Register("Jitter", typeof(int), typeof(RandomJitterEase),
            new UIPropertyMetadata(1000), new ValidateValueCallback(ValidateJitter));

        private static bool ValidateJitter(object value)
        {
            int jitterValue = (int)value;
            return ((jitterValue <= 2000) && (jitterValue >= 0));
        }

        // This required override simply provides a live instance of your easing function.
        protected override Freezable CreateInstanceCore()
        {
            return new RandomJitterEase();
        }
    }

下面是緩動(dòng)函數(shù)在XAML中使用的示例:

<Window x:Class="Animation.CustomEasingFunction"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:Animation"
        Title="CustomEasingFunction" Height="300" Width="600">
    <Window.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">
            <EventTrigger.Actions>
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation
            Storyboard.TargetName="ellipse1" Storyboard.TargetProperty="(Canvas.Left)"
            To="500" Duration="0:0:10">
                        </DoubleAnimation>
                        <DoubleAnimation
            Storyboard.TargetName="ellipse2" Storyboard.TargetProperty="(Canvas.Left)"
            To="500" Duration="0:0:10">
                            <DoubleAnimation.EasingFunction>
                                <local:RandomJitterEase EasingMode="EaseIn" Jitter="1000"></local:RandomJitterEase>
                            </DoubleAnimation.EasingFunction>
                        </DoubleAnimation>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger.Actions>
        </EventTrigger>
    </Window.Triggers>
    <Canvas Margin="10">
        <Ellipse Name="ellipse1" Canvas.Left="0" Fill="Red" Width="20" Height="20"></Ellipse>

        <Ellipse Name="ellipse2" Canvas.Top="100" Canvas.Left="0" Fill="Red" Width="20" Height="20"></Ellipse>
    </Canvas>
</Window>

  效果圖如下所示,可以看到上面的圓圈平滑向右移動(dòng),下面的圓圈來(lái)回緩動(dòng)向右移動(dòng):

 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多