WPF 有趣的動畫效果

WPF 有趣的動畫效果

        這一次我要呈上一個簡單的文章,關於給你的WPF apps加入美麗的光線動畫,但是我對動畫這東西可能有點入迷了。

        實際上。我對動畫如此的入迷,以致於我最後作了以前從未打算作的東西,就是使用一些很實用的.NET代碼,漸變填充生成背景動畫。讓我先給你看一些終於效果吧。


WPF和元素定位
        然而。在咱們開始以前。咱們需要考慮一件事情。這件事讓我也有點原地轉圈的感受。

        彷佛當你使用WPF建立不論什麼閉環形狀時,你不能設置它的X和Y座標。好吧。至少你不能在通常的WPF窗口(像VS開箱即用的形狀)上。
        這一點上,我要謝謝個人好朋友(以及WPF各類大神)Gavin Lanata。他幫我解釋說,假設要在代碼中以我想要的方式定位。就不得不將窗體的根佈局從grid變爲canvas。

這是很是使人沮喪的。如此簡單的東西(並且是大多開發者會考慮尋找的東西)在WPF中卻不被以爲是繪製形狀的要求。canvas

我跑題了。現在咱們什麼也作不了。app

讓咱們開始吧
        打開Visual Studio,開始新的WPF應用程序項目。命名爲WpfAnimationTest。

你可以使用Blend。但是因爲咱們大多數要輸入代碼。Blend可能有點過分了。dom

        一旦你的模板載入完成,請改動你的「MainWindow.xaml」文件,看起來像這樣。
<Window x:Class="WpfAnimationTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="WPF Animation Testing" Height="600" Width="800"
         WindowStartupLocation="CenterScreen">
    <Canvas x:Name="Root" Background="Black">        
    </Canvas>
</Window>
        你會看到。除了將背景變爲黑色,咱們改變了默認的grid爲canvas。並且設置了窗口大小和標題。

改變的也很少。不像大多說WPF/XAML項目,這裏咱們畫的大部分用代碼實現。函數

        使用這個記錄。你可以輕易使用聲明的XAML,複製本文中的所有東西,但是會有大量反覆漸變、漸變點和其它需要資源的東西。經過使用這裏的代碼方法,咱們是用的不論什麼東西在超出範圍後都可以處理掉;而且更重要的是。它是可重用代碼。


首先是一點兒理論佈局

        假設你瞭解過XAML,你將可能知道WPF中所有東西都可以成爲動畫。顏色,位置,大小。填充這些可以使用時間線和故事板可以很是easy變成動畫。
        你使用不少可用動畫時間線類型中的一種建立你的動畫順序。一般新建對象。而後設置開始值、終止值,以及動畫執行時間長度。而後在將它們附加到故事板並啓動執行以前,附加這些動畫時間線到你想要它們控制的UI元素的屬性上。
        然而。有件事我沒有意識到,一個彩色漸變點位置也可以作成動畫。當你在WPF中建立顏色漸變時。你使用一系列對象「漸變點」建立了它們。
        假設你之前使用過PhotoShop之類的圖像處理軟件,並且使用小方形顏色標記器在顏色應該改變的地方標記填充位置,你已經使用了類似的概念。

好比,假設你想要在中間使用從紅到藍顏色漸變,而後變綠,你可能在0%處建立紅色點。在50%建立藍色,100%處建立綠色。動畫

WPF圖畫引擎而後在所有顏色間填充。這樣你就獲得從一個顏色到下一個的平滑過渡。ui

        在大多數WPF中大多數測量使用所謂的本地座標系統。這意味着你的窗口上,可能寬度有比方800像素,從0%到100%範圍使用0到1來表明。設置漸變時,這可能意味着0像素在0.0或0%,400像素在0.5或50%,800像素在1.0或100%,所有你的顏色點位置都是這樣指定的。
咱們試一些代碼吧
        打開主要窗體XAML代碼。若是你已經如以前提到的改動了canvas,你應該加入例如如下代碼到MainWindow構造器中。
        public MainWindow()
        {
            InitializeComponent();
            Rectangle myRect = new Rectangle
            {
                Width = 300,
                Height = 100,
                Stroke = Brushes.White,
                StrokeThickness = 1
            };
            Root.Children.Add(myRect);
            Canvas.SetLeft(myRect, 100);
            Canvas.SetTop(myRect, 100);
        }
        當你按下F5,你應該能看到黑色背景上白色矩形,距離每個角都是100像素。大小300像素*100像素。需要Canvas SetLeft和SetTop調用,是因爲微軟決定贊成繪製閉環形狀的不論什麼人來決定形狀繪製的位置時沒實用處的。
        假設你也添加了填充參數:
        public MainWindow()
        {
            InitializeComponent();
            Rectangle myRect = new Rectangle
            {
                Width = 300,
                Height = 100,
                Stroke = Brushes.White,
                StrokeThickness = 1,
                Fill=Brushes.Red
            };
            Root.Children.Add(myRect);
            Canvas.SetLeft(myRect, 100);
            Canvas.SetTop(myRect, 100);
        }
        你也可以設置矩形全局的實心填充顏色。

然而。實心顏色有點無趣。this

咱們將改動成更加有趣的東西。spa

        首先,讓咱們經過將它在自身的函數中包裝起來,而後也建立數據對象傳送參數過去。咱們將加入所有需要的參數到數據對象,並且我將解釋咱們遇到的每個對象。
        加入新類到你的項目,命名爲BarDescription。

輸入例如如下代碼:code

namespace WpfAnimationTest
{
    public class BarDescriptor
    {
        public int RectangleX { get; set; }
        public int RectangleY { get; set; }
        public int RectangleWidth { get; set; }
        public int RectangleHeight { get; set; }
        public int AnimationTimeInSeconds { get; set; }
        // 0.0 to 1.0
        public float BarBaseRedLevel { get; set; }
        public float BarBaseGreenLevel { get; set; }
        public float BarBaseBlueLevel { get; set; }
        public float GradientStartX { get; set; }
        public float GradientStartY { get; set; }
        public float GradientEndX { get; set; }
        public float GradientEndY { get; set; }
    }
}
        確保依照你的需要改動了命名空間。

        而後,打開MainWindow.xaml.cs(或者你隨意命名的主窗體後臺代碼)。而後確保輸入一下代碼:
using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
 
namespace WpfAnimationTest
{
   public partial class MainWindow
   {
      private Rectangle _testRect;
 
      public MainWindow()
      {
         InitializeComponent();
         Loaded += MainWindowLoaded;
      }
 
      private void MainWindowLoaded(object sender,
         RoutedEventArgs e)
      {
         BarDescriptor barOne = new BarDescriptor
         {
            RectangleX = 100,
            RectangleY = 100,
            RectangleWidth = 200,
            RectangleHeight = 200,
            AnimationTimeInSeconds = 0,
            BarBaseRedLevel = 0,
            BarBaseGreenLevel = 0,
            BarBaseBlueLevel = 0,
            GradientStartX = 0,
            GradientStartY = 0,
            GradientEndX = 0,
            GradientEndY = 0
         };
 
         CreateRectangleAnimatedRectangle(barOne);
      }
 
      private void CreateRectangleAnimatedRectangle(BarDescriptor
         inputParameters)
      {
         _testRect = new Rectangle
         {
            Width = inputParameters.RectangleWidth,
            Height = inputParameters.RectangleHeight,
            Stroke = Brushes.White,
            StrokeThickness = 1,
         };
 
         Root.Children.Add(_testRect);
         Canvas.SetLeft(_testRect, inputParameters.RectangleX);
         Canvas.SetTop(_testRect, inputParameters.RectangleY);
 
      }
 
   }
}
        再一次。確保輸入正確的命名空間。正如以前的樣例,執行時你應該又看到白色矩形。但是現在你也應該能夠輕鬆加入新矩形。經過建立新的「BarDescriptor」對象,並設置對應參數。
        然而,現在若是你設置主窗體大小和個人一樣(800*600)。設置barOne屬性例如如下:
            BarDescriptor barOne = new BarDescriptor
            {
                RectangleX = 0,
                RectangleY = 0,
                RectangleWidth = 800,
                RectangleHeight = 600,
                AnimationTimeInSeconds = 0,
                BarBaseRedLevel = 0,
                BarBaseGreenLevel = 0,
                BarBaseBlueLevel = 0,
                GradientStartX = 0,
                GradientStartY = 0,
                GradientEndX = 0,
                GradientEndY = 0
            };
        這樣會建立和主窗體相同大小的矩形。
加入漸變
        爲了使用普通C#代碼建立一個漸變色,你需要使用一個「 LinearGradientBrush」對象和一個"GradientStopCollection"。漸變筆刷將被用來填充矩形背景,並且點集合將設置漸變過程的顏色。
        咱們的漸變中。也會使用透明度。透明度從0.0到1.0-0%到100%。設置爲0%意味着不一樣看透它;它沒有透明度,而100%(1)則全然透明,顯示了它背後的一切。

透明度的設置贊成你控制多少背景、多少顏色顯示出來。

        在建立矩形方法內部的前面,加入例如如下的代碼建立你的顏色點:
            GradientStopCollection gradientStops = new GradientStopCollection
            {
                new GradientStop(Color.FromScRgb(0.0f, 1, 1, 1), 0.0),
                new GradientStop(Color.FromScRgb(0.0f, 1, 1, 1), 0.01),
                new GradientStop(Color.FromScRgb(0.5f, 1, 1, 1), 0.02),
                new GradientStop(Color.FromScRgb(1.0f, 1, 1, 1), 0.03),
                new GradientStop(Color.FromScRgb(0.5f, 1, 1, 1), 0.04),
                new GradientStop(Color.FromScRgb(0.0f, 1, 1, 1), 0.05),
                new GradientStop(Color.FromScRgb(0.0f, 1, 1, 1), 1.0),
            };
        這一系列的漸變點建立了一系列七色點全白(R/G/B值都爲1),顏色點被設置沿着漸變填充長度  位置爲 0, 0.01, 0.02, 0.03, 0.04, 0.05,和1。並且有透明度0, 0, 0.5, 1, 0.5, 0 和0。這系列填充意味着咱們從第一個點到第二個點透明,而後忽然從全然透明升級爲實心白色,緊接着忽然降回透明;最後,從點6和點7(矩形的剩餘部分)是100%透明。
        你定義了這些顏色點後,加入例如如下代碼:
 LinearGradientBrush gradientBrush = new LinearGradientBrush(gradientStops, new Point(0, 0.5), new Point(1, 0.5));
        這將使用點集建立實際的漸變。它將橫跨Y座標系,沿着X軸從0到100%(1)水平執行。

一旦你添加了漸變。改動了矩形建立參數來設置漸變,當你這樣作了。也會使得邊界消失:

            _testRect = new Rectangle
            {
                Width = inputParameters.RectangleWidth,
                Height = inputParameters.RectangleHeight,
                Stroke = Brushes.Transparent,
                StrokeThickness = 0,
                Fill = gradientBrush
            };
        這些都作好後,執行你的應用程序,你會獲得:

        你應該能夠直接看到不一樣透明度的影響。以及它致使填充圓柱形3D條外觀的效果。爲了實現動畫。咱們需要移動5個漸變點,組成漸變部分看起來像3D條。在上面的漸變點集中。這些值是5個值。位於兩個外部值之間,位置從0.01到0.05.
        咱們需要從左至右移動這些顏色點,並返回。這意味着咱們需要下述動做:
  • 點1從0.01到0.95並返回;
  • 點2從0.02到0.96並返回;
  • 點3從0.03到0.97並返回。
  • 點4從0.04到0.98並返回;
  • 點5從0.05到0.99並返回。

        咱們經過建立 5個 雙值動畫對象達成效果。每個分別匹配一個顏色點。加入下述代碼到矩形方法中。在建立漸變點以前:
            DoubleAnimation firstStopAnim =new DoubleAnimation(0.01, 0.95,new Duration(new TimeSpan(0, 0, 0, 5)));
            DoubleAnimation secondStopAnim = new DoubleAnimation(0.02, 0.96,new Duration(new TimeSpan(0, 0, 0, 5)));
            DoubleAnimation thirdStopAnim = new DoubleAnimation(0.03, 0.97,new Duration(new TimeSpan(0, 0, 0, 5)));
            DoubleAnimation fourthStopAnim = new DoubleAnimation(0.04, 0.98,new Duration(new TimeSpan(0, 0, 0, 5)));
            DoubleAnimation fifthStopAnim = new DoubleAnimation(0.05, 0.99,new Duration(new TimeSpan(0, 0, 0, 5)));

            firstStopAnim.AutoReverse = true;
            secondStopAnim.AutoReverse = true;
            thirdStopAnim.AutoReverse = true;
            fourthStopAnim.AutoReverse = true;
            fifthStopAnim.AutoReverse = true;

            firstStopAnim.BeginTime = new TimeSpan(0);
            secondStopAnim.BeginTime = new TimeSpan(0);
            thirdStopAnim.BeginTime = new TimeSpan(0);
            fourthStopAnim.BeginTime = new TimeSpan(0);
            fifthStopAnim.BeginTime = new TimeSpan(0);

            firstStopAnim.EasingFunction = new CubicEase();
            secondStopAnim.EasingFunction = new CubicEase();
            thirdStopAnim.EasingFunction = new CubicEase();
            fourthStopAnim.EasingFunction = new CubicEase();
            fifthStopAnim.EasingFunction = new CubicEase();
        這裏咱們加入5個點,而後設置默認屬性,以及範圍。默認屬性是本身主動返回相反方向,從0s開始,使用CubicEase動畫轉變。

一旦咱們建立動畫對象。咱們而後需要給內部5個漸變點以獨特的名稱,這樣咱們可以附加故事板對象控制他們的動畫。

        聲明漸變點集以後。建立線性漸變以前,加入例如如下代碼:
            String slotOneName = RandomName();
            String slotTwoName = RandomName();
            String slotThreeName = RandomName();
            String slotFourName = RandomName();
            String slotFiveName = RandomName();

            RegisterName(slotOneName, gradientStops[1]);
            RegisterName(slotTwoName, gradientStops[2]);
            RegisterName(slotThreeName, gradientStops[3]);
            RegisterName(slotFourName, gradientStops[4]);
            RegisterName(slotFiveName, gradientStops[5]);
        函數「RandomName」是用戶加入的函數,放在繪製矩形方法以後。

你需要給每個名稱一個隨機名,這樣你可以重用矩形繪製方法。假設你嘗試重用已經被分配給以前顏色點的名稱,矩形函數將終止,但是你不會獲得阻止應用程序的異常。而是獲得黑色窗體,沒有不論什麼動畫。所以確保你的點名稱惟一是很是重要的,但是沒有混亂到你給出不可用的屬性名。

我在這裏使用的函數使用了隨機和一個GUID結合的方式,沒有危急的字符。

爲了在你的代碼中定義它。在MainWindow類中,矩形函數以後加入例如如下代碼:

        private string RandomName()
        {
            const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            const int nameLen = 8;
            var random = new Random();
            string temp = Guid.NewGuid().ToString().
               Replace("-", String.Empty);
            temp = Regex.Replace(temp, @"[\d-]",
               string.Empty).ToUpper();
            return new string(Enumerable.Repeat(chars, nameLen).Select
               (s => s[random.Next(s.Length)]).ToArray()) + temp;
        }
        隨機名稱設置好之後,咱們而後開始在矩形函數中設置漸變更畫。

下一件事是映射咱們剛建立的隨機屬性名,附加漸變點到故事板。

咱們使用WPF故事板類的靜態屬性來匹配,而後建立故事板局部對象,加入每個動畫到子集合。

        將如下代碼放到線性漸變聲明以後,但是在你創建矩形以前:
            Storyboard.SetTargetName(firstStopAnim, slotOneName);
            Storyboard.SetTargetProperty(firstStopAnim,new PropertyPath(GradientStop.OffsetProperty));

            Storyboard.SetTargetName(secondStopAnim, slotTwoName);
            Storyboard.SetTargetProperty(secondStopAnim,new PropertyPath(GradientStop.OffsetProperty));

            Storyboard.SetTargetName(thirdStopAnim, slotThreeName);
            Storyboard.SetTargetProperty(thirdStopAnim,new PropertyPath(GradientStop.OffsetProperty));

            Storyboard.SetTargetName(fourthStopAnim, slotFourName);
            Storyboard.SetTargetProperty(fourthStopAnim,new PropertyPath(GradientStop.OffsetProperty));

            Storyboard.SetTargetName(fifthStopAnim, slotFiveName);
            Storyboard.SetTargetProperty(fifthStopAnim,new PropertyPath(GradientStop.OffsetProperty));

            Storyboard gradientAnimation = new Storyboard { RepeatBehavior = RepeatBehavior.Forever };

            gradientAnimation.Children.Add(firstStopAnim);
            gradientAnimation.Children.Add(secondStopAnim);
            gradientAnimation.Children.Add(thirdStopAnim);
            gradientAnimation.Children.Add(fourthStopAnim);
            gradientAnimation.Children.Add(fifthStopAnim);
        而後緊接着加入例如如下夢幻般的代碼,放置在矩形方法末尾,在設置矩形left和top以後:
gradientAnimation.Begin(this);
        假設一切正常進行。按下F5你會看到3D條左右來回移動。  

        以前,記得我簡要提到「BarDescriptor」對象的其它參數嗎?咱們將充分使用它。
        你已經知道。RectangleX, RectangleY, RegtangleWidth,和RectangleHeight指定位置和繪製矩形的大小。

 AnimationTimeInSeconds是你想讓故事板從矩形左側到右側執行的時間。這不包括返回時間。僅僅是動畫一圈的時間。 BarBaseRedLevel, BarBaseGreenLevel,和BarBaseBlueLevel被用來設置條的基色。設置這些可以用來改變條的整體顏色。

        最後,GradientStartX, GradientStartY, GradientEndX,和GradientEndY設置漸變將聽從的直線路徑。這些值從0.0到1.0,表明X和Y方向的0%到100%。好比,假設設置0,0到1,1,你的3D條將從左上角到右下角,沿着對角方向動畫。設置0,0.5和1,0.5將使動畫沿着普通的從左到右。

        改動barOne對象,讓它擁有下面值:
            BarDescriptor barOne = new BarDescriptor
            {
                RectangleX = 0,
                RectangleY = 0,
                RectangleWidth = 800,
                RectangleHeight = 600,
                AnimationTimeInSeconds = 5,
                BarBaseRedLevel = 0,
                BarBaseGreenLevel = 0.5f,
                BarBaseBlueLevel = 0,
                GradientStartX = 0,
                GradientStartY = 0.5f,
                GradientEndX = 1,
                GradientEndY = 0.5f
            };
        而後改動「CreateRectangle」方法使得參數被用在需要的地方。

改動漸變點集的建立,讓它看起來例如如下:

            GradientStopCollection gradientStops = new GradientStopCollection
            {
                new GradientStop(Color.FromScRgb(0.5f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 0.0),
                new GradientStop(Color.FromScRgb(0.0f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 0.01),
                new GradientStop(Color.FromScRgb(0.5f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 0.02),
                new GradientStop(Color.FromScRgb(1.0f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 0.03),
                new GradientStop(Color.FromScRgb(0.5f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 0.04),
                new GradientStop(Color.FromScRgb(0.0f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 0.05),
                new GradientStop(Color.FromScRgb(0.5f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 1.0),
            };
        而後。改動你建立線性漸變筆刷的行,看起來例如如下:
            LinearGradientBrush gradientBrush = new LinearGradientBrush(gradientStops,new Point(inputParameters.GradientStartX,
                inputParameters.GradientStartY),new Point(inputParameters.GradientEndX,inputParameters.GradientEndY));
        假設一切順利,你應該有一個綠色條左右移動,和以前相比有輕微漸變:

        假設你看到上圖,恭喜你。

現在需要作的就是把剩餘的條加入上去,建立不少其它「BarDescriptor」對象,將它們傳送到矩形建立方法例如如下:

BarDescriptor barOne = new BarDescriptor
{
   RectangleX = 0,
   RectangleY = 0,
   RectangleWidth = 800,
   RectangleHeight = 600,
   AnimationTimeInSeconds = 5,
   BarBaseRedLevel = 0,
   BarBaseGreenLevel = 0.5f,
   BarBaseBlueLevel = 0,
   GradientStartX = 0,
   GradientStartY = 0.5f,
   GradientEndX = 1,
   GradientEndY = 0.5f
};
 
BarDescriptor barTwo = new BarDescriptor
{
   RectangleX = 0,
   RectangleY = 0,
   RectangleWidth = 800,
   RectangleHeight = 600,
   AnimationTimeInSeconds = 4,
   BarBaseRedLevel = 0,
   BarBaseGreenLevel = 0.5f,
   BarBaseBlueLevel = 0,
   GradientStartX = 1,
   GradientStartY = 0,
   GradientEndX = 0,
   GradientEndY = 1
};
 
BarDescriptor barThree = new BarDescriptor
{
   RectangleX = 0,
   RectangleY = 0,
   RectangleWidth = 800,
   RectangleHeight = 600,
   AnimationTimeInSeconds = 3,
   BarBaseRedLevel = 0,
   BarBaseGreenLevel = 0.5f,
   BarBaseBlueLevel = 0,
   GradientStartX = 0,
   GradientStartY = 0,
   GradientEndX = 1,
   GradientEndY = 1
};
 
BarDescriptor barFour = new BarDescriptor
{
   RectangleX = 0,
   RectangleY = 0,
   RectangleWidth = 800,
   RectangleHeight = 600,
   AnimationTimeInSeconds = 6,
   BarBaseRedLevel = 0,
   BarBaseGreenLevel = 0.5f,
   BarBaseBlueLevel = 0,
   GradientStartX = 0.5f,
   GradientStartY = 0,
   GradientEndX = 0.5f,
   GradientEndY = 1
};
 
CreateRectangleAnimatedRectangle(barOne);
CreateRectangleAnimatedRectangle(barTwo);
CreateRectangleAnimatedRectangle(barThree);
CreateRectangleAnimatedRectangle(barFour);
        本文中開頭用的圖片就是四個條相互覆蓋的產品,贊成透明度相互結合。更改時間和更改速度有一樣效果。因此不一樣條移動速度不同。

        你能夠試玩顏色漸變和透明度映射,並建立各類有趣的效果。

僅僅是要記住,爲了能夠正常執行,你必須在中心有5個漸變,集合中有5個點。

        終於完整的後臺代碼是這種:
using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace WpfAnimationTest
{
    public partial class MainWindow
    {
        private Rectangle _testRect;

        public MainWindow()
        {
            InitializeComponent();
            Loaded += MainWindowLoaded;
        }

        private void MainWindowLoaded(object sender,
           RoutedEventArgs e)
        {
            BarDescriptor barOne = new BarDescriptor
            {
                RectangleX = 0,
                RectangleY = 0,
                RectangleWidth = 800,
                RectangleHeight = 600,
                AnimationTimeInSeconds = 5,
                BarBaseRedLevel = 0,
                BarBaseGreenLevel = 0.5f,
                BarBaseBlueLevel = 0,
                GradientStartX = 0,
                GradientStartY = 0.5f,
                GradientEndX = 1,
                GradientEndY = 0.5f
            };

            BarDescriptor barTwo = new BarDescriptor
            {
                RectangleX = 0,
                RectangleY = 0,
                RectangleWidth = 800,
                RectangleHeight = 600,
                AnimationTimeInSeconds = 4,
                BarBaseRedLevel = 0,
                BarBaseGreenLevel = 0.5f,
                BarBaseBlueLevel = 0,
                GradientStartX = 1,
                GradientStartY = 0,
                GradientEndX = 0,
                GradientEndY = 1
            };

            BarDescriptor barThree = new BarDescriptor
            {
                RectangleX = 0,
                RectangleY = 0,
                RectangleWidth = 800,
                RectangleHeight = 600,
                AnimationTimeInSeconds = 3,
                BarBaseRedLevel = 0,
                BarBaseGreenLevel = 0.5f,
                BarBaseBlueLevel = 0,
                GradientStartX = 0,
                GradientStartY = 0,
                GradientEndX = 1,
                GradientEndY = 1
            };

            BarDescriptor barFour = new BarDescriptor
            {
                RectangleX = 0,
                RectangleY = 0,
                RectangleWidth = 800,
                RectangleHeight = 600,
                AnimationTimeInSeconds = 6,
                BarBaseRedLevel = 0,
                BarBaseGreenLevel = 0.5f,
                BarBaseBlueLevel = 0,
                GradientStartX = 0.5f,
                GradientStartY = 0,
                GradientEndX = 0.5f,
                GradientEndY = 1
            };

            CreateRectangleAnimatedRectangle(barOne);
            CreateRectangleAnimatedRectangle(barTwo);
            CreateRectangleAnimatedRectangle(barThree);
            CreateRectangleAnimatedRectangle(barFour);
        }

        private void CreateRectangleAnimatedRectangle(BarDescriptor inputParameters)
        {
            DoubleAnimation firstStopAnim =new DoubleAnimation(0.01, 0.95,new Duration(new TimeSpan(0, 0, 0, 5)));
            DoubleAnimation secondStopAnim = new DoubleAnimation(0.02, 0.96,new Duration(new TimeSpan(0, 0, 0, 5)));
            DoubleAnimation thirdStopAnim = new DoubleAnimation(0.03, 0.97,new Duration(new TimeSpan(0, 0, 0, 5)));
            DoubleAnimation fourthStopAnim = new DoubleAnimation(0.04, 0.98,new Duration(new TimeSpan(0, 0, 0, 5)));
            DoubleAnimation fifthStopAnim = new DoubleAnimation(0.05, 0.99,new Duration(new TimeSpan(0, 0, 0, 5)));

            firstStopAnim.AutoReverse = true;
            secondStopAnim.AutoReverse = true;
            thirdStopAnim.AutoReverse = true;
            fourthStopAnim.AutoReverse = true;
            fifthStopAnim.AutoReverse = true;

            firstStopAnim.BeginTime = new TimeSpan(0);
            secondStopAnim.BeginTime = new TimeSpan(0);
            thirdStopAnim.BeginTime = new TimeSpan(0);
            fourthStopAnim.BeginTime = new TimeSpan(0);
            fifthStopAnim.BeginTime = new TimeSpan(0);

            firstStopAnim.EasingFunction = new CubicEase();
            secondStopAnim.EasingFunction = new CubicEase();
            thirdStopAnim.EasingFunction = new CubicEase();
            fourthStopAnim.EasingFunction = new CubicEase();
            fifthStopAnim.EasingFunction = new CubicEase();

            GradientStopCollection gradientStops = new GradientStopCollection
            {
                new GradientStop(Color.FromScRgb(0.5f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 0.0),
                new GradientStop(Color.FromScRgb(0.0f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 0.01),
                new GradientStop(Color.FromScRgb(0.5f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 0.02),
                new GradientStop(Color.FromScRgb(1.0f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 0.03),
                new GradientStop(Color.FromScRgb(0.5f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 0.04),
                new GradientStop(Color.FromScRgb(0.0f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 0.05),
                new GradientStop(Color.FromScRgb(0.5f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 1.0),
            };

            String slotOneName = RandomName();
            String slotTwoName = RandomName();
            String slotThreeName = RandomName();
            String slotFourName = RandomName();
            String slotFiveName = RandomName();

            RegisterName(slotOneName, gradientStops[1]);
            RegisterName(slotTwoName, gradientStops[2]);
            RegisterName(slotThreeName, gradientStops[3]);
            RegisterName(slotFourName, gradientStops[4]);
            RegisterName(slotFiveName, gradientStops[5]);

            LinearGradientBrush gradientBrush = new LinearGradientBrush(gradientStops,new Point(inputParameters.GradientStartX,
                inputParameters.GradientStartY),new Point(inputParameters.GradientEndX,inputParameters.GradientEndY));

            Storyboard.SetTargetName(firstStopAnim, slotOneName);
            Storyboard.SetTargetProperty(firstStopAnim,new PropertyPath(GradientStop.OffsetProperty));

            Storyboard.SetTargetName(secondStopAnim, slotTwoName);
            Storyboard.SetTargetProperty(secondStopAnim,new PropertyPath(GradientStop.OffsetProperty));

            Storyboard.SetTargetName(thirdStopAnim, slotThreeName);
            Storyboard.SetTargetProperty(thirdStopAnim,new PropertyPath(GradientStop.OffsetProperty));

            Storyboard.SetTargetName(fourthStopAnim, slotFourName);
            Storyboard.SetTargetProperty(fourthStopAnim,new PropertyPath(GradientStop.OffsetProperty));

            Storyboard.SetTargetName(fifthStopAnim, slotFiveName);
            Storyboard.SetTargetProperty(fifthStopAnim,new PropertyPath(GradientStop.OffsetProperty));

            Storyboard gradientAnimation = new Storyboard { RepeatBehavior = RepeatBehavior.Forever };

            gradientAnimation.Children.Add(firstStopAnim);
            gradientAnimation.Children.Add(secondStopAnim);
            gradientAnimation.Children.Add(thirdStopAnim);
            gradientAnimation.Children.Add(fourthStopAnim);
            gradientAnimation.Children.Add(fifthStopAnim);

            _testRect = new Rectangle
            {
                Width = inputParameters.RectangleWidth,
                Height = inputParameters.RectangleHeight,
                Stroke = Brushes.White,
                StrokeThickness = 1,
                Fill=gradientBrush
            };

            Root.Children.Add(_testRect);
            Canvas.SetLeft(_testRect, inputParameters.RectangleX);
            Canvas.SetTop(_testRect, inputParameters.RectangleY);

            gradientAnimation.Begin(this);
        }

        private string RandomName()
        {
            const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            const int nameLen = 8;
            var random = new Random();
            string temp = Guid.NewGuid().ToString().
               Replace("-", String.Empty);
            temp = Regex.Replace(temp, @"[\d-]",
               string.Empty).ToUpper();
            return new string(Enumerable.Repeat(chars, nameLen).Select
               (s => s[random.Next(s.Length)]).ToArray()) + temp;
        }
    }
}
相關文章
相關標籤/搜索