Posted by: Zeeshan Amjad | May 26, 2010

Animating Brush with Code


We already saw the animation of dependency property here. In this example we change the font size property of text block. Data type of font size property is double and WPF already has DoubleAnimation class. We even did the same thing with color property here. But if we want to do the same thing with brush then WPF doesn’t provide any BrushAnimation class. In this case we have to create our own class inherited by animation timeline class. Here is a class diagram of Timeline animation class.

Animation_03

The most important thing while inherit class from animation time line class is to implement GetCurrentValue method and create two dependency properties “From” and “To”. We also override TargetPropertyType mthod of animation time line class. Here is a class diagram of animation time line class.

Animation_05

I found a simple implementation of Brush animation class here. This code is taken from the same source.

// get from http://stackoverflow.com/questions/1542274/how-do-i-combine-brushes-in-wpf
class BrushAnimation : AnimationTimeline
{
    protected override Freezable CreateInstanceCore()
    {
        return new BrushAnimation();
    }

    public override Type TargetPropertyType
    {
        get { return typeof(Brush); }
    }

    static BrushAnimation()
    {
        FromProperty = DependencyProperty.Register("From", typeof(Brush),
            typeof(BrushAnimation));

        ToProperty = DependencyProperty.Register("To", typeof(Brush),
            typeof(BrushAnimation));
    }

    public static readonly DependencyProperty FromProperty;
    public Brush From
    {
        get
        {
            return (Brush)GetValue(BrushAnimation.FromProperty);
        }
        set
        {
            SetValue(BrushAnimation.FromProperty, value);
        }
    }

    public static readonly DependencyProperty ToProperty;
    public Brush To
    {
        get
        {
            return (Brush)GetValue(BrushAnimation.ToProperty);
        }
        set
        {
            SetValue(BrushAnimation.ToProperty, value);
        }
    }

    public override object GetCurrentValue(object defaultOriginValue,
    object defaultDestinationValue, AnimationClock animationClock)
    {
        Brush fromVal = ((Brush)GetValue(BrushAnimation.FromProperty)).CloneCurrentValue();
        Brush toVal = ((Brush)GetValue(BrushAnimation.ToProperty)).CloneCurrentValue();

        if ((double)animationClock.CurrentProgress == 0.0)
            return fromVal; //Here it workes fine.

        if ((double)animationClock.CurrentProgress == 1.0)
            return toVal;   //It workes also here fine.

        toVal.Opacity = (double)animationClock.CurrentProgress;


        Border Bd = new Border();
        Border Bdr = new Border();

        Bd.Width = 1.0;
        Bd.Height = 1.0;

        Bd.Background = fromVal;
        Bdr.Background = toVal;

        Bd.Visibility = Visibility.Visible;
        Bdr.Visibility = Visibility.Visible;
        Bd.Child = Bdr;

        Brush VB = new VisualBrush(Bd);
        return VB; //But here it return's a transparent brush.

        //If I return the 'toVal' variable here it animates correctly the opacity.
    }
}

Now we can do rest of the stuff just like other animation examples.

// first linear gradient brush
LinearGradientBrush lgb1 = new LinearGradientBrush();
GradientStop gs1 = new GradientStop(Colors.Yellow, 0);
GradientStop gs2 = new GradientStop(Colors.Blue, 1);
lgb1.GradientStops.Add(gs1);
lgb1.GradientStops.Add(gs2);

rect.Fill = lgb1;

// second linear gradient brush
LinearGradientBrush lgb2 = new LinearGradientBrush();
GradientStop gs3 = new GradientStop(Colors.Red, 0);
GradientStop gs4 = new GradientStop(Colors.White, 1);
lgb2.GradientStops.Add(gs3);
lgb2.GradientStops.Add(gs4);

BrushAnimation ba = new BrushAnimation();
ba.From = lgb1;
ba.To = lgb2;
ba.AutoReverse = true;
ba.RepeatBehavior = RepeatBehavior.Forever;
ba.Duration = TimeSpan.FromSeconds(3);

rect.BeginAnimation(Rectangle.FillProperty, ba);

Here is complete C# code of the program.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

// get from http://stackoverflow.com/questions/1542274/how-do-i-combine-brushes-in-wpf
class BrushAnimation : AnimationTimeline
{
    protected override Freezable CreateInstanceCore()
    {
        return new BrushAnimation();
    }

    public override Type TargetPropertyType
    {
        get { return typeof(Brush); }
    }

    static BrushAnimation()
    {
        FromProperty = DependencyProperty.Register("From", typeof(Brush),
            typeof(BrushAnimation));

        ToProperty = DependencyProperty.Register("To", typeof(Brush),
            typeof(BrushAnimation));
    }

    public static readonly DependencyProperty FromProperty;
    public Brush From
    {
        get
        {
            return (Brush)GetValue(BrushAnimation.FromProperty);
        }
        set
        {
            SetValue(BrushAnimation.FromProperty, value);
        }
    }

    public static readonly DependencyProperty ToProperty;
    public Brush To
    {
        get
        {
            return (Brush)GetValue(BrushAnimation.ToProperty);
        }
        set
        {
            SetValue(BrushAnimation.ToProperty, value);
        }
    }

    public override object GetCurrentValue(object defaultOriginValue,
    object defaultDestinationValue, AnimationClock animationClock)
    {
        Brush fromVal = ((Brush)GetValue(BrushAnimation.FromProperty)).CloneCurrentValue();
        Brush toVal = ((Brush)GetValue(BrushAnimation.ToProperty)).CloneCurrentValue();

        if ((double)animationClock.CurrentProgress == 0.0)
            return fromVal; //Here it workes fine.

        if ((double)animationClock.CurrentProgress == 1.0)
            return toVal;   //It workes also here fine.

        toVal.Opacity = (double)animationClock.CurrentProgress;


        Border Bd = new Border();
        Border Bdr = new Border();

        Bd.Width = 1.0;
        Bd.Height = 1.0;

        Bd.Background = fromVal;
        Bdr.Background = toVal;

        Bd.Visibility = Visibility.Visible;
        Bdr.Visibility = Visibility.Visible;
        Bd.Child = Bdr;

        Brush VB = new VisualBrush(Bd);
        return VB; //But here it return's a transparent brush.

        //If I return the 'toVal' variable here it animates correctly the opacity.
    }
}

public class MyWindow : Window
{
    public MyWindow()
    {
        Title = "Animation with Code";
        Width = 400;
        Height = 300;


        Rectangle rect = new Rectangle();
        rect.Width = 400;
        rect.Height = 300;

        // first linear gradient brush
        LinearGradientBrush lgb1 = new LinearGradientBrush();
        GradientStop gs1 = new GradientStop(Colors.Yellow, 0);
        GradientStop gs2 = new GradientStop(Colors.Blue, 1);
        lgb1.GradientStops.Add(gs1);
        lgb1.GradientStops.Add(gs2);

        rect.Fill = lgb1;

        // second linear gradient brush
        LinearGradientBrush lgb2 = new LinearGradientBrush();
        GradientStop gs3 = new GradientStop(Colors.Red, 0);
        GradientStop gs4 = new GradientStop(Colors.White, 1);
        lgb2.GradientStops.Add(gs3);
        lgb2.GradientStops.Add(gs4);

        BrushAnimation ba = new BrushAnimation();
        ba.From = lgb1;
        ba.To = lgb2;
        ba.AutoReverse = true;
        ba.RepeatBehavior = RepeatBehavior.Forever;
        ba.Duration = TimeSpan.FromSeconds(3);

        rect.BeginAnimation(Rectangle.FillProperty, ba);

        Content = rect;
    }
}

public class AnimatinClass
{
    [STAThread]
    public static void Main()
    {
        MyWindow win = new MyWindow();

        Application app = new Application();
        app.Run(win);
    }
}

Here are few output of the program.

BrushAnimation_01

BrushAnimation_02

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: