4

I want to apply a Blink animation to a Canvas so that all the objects I have drawn on it would blink with it.

I have been somewhat successful using the code below which changes the Opacity property of the Canvas rather fast to achieve this effect but I'm kinda not satisfied with it.

I would prefer a pure blink without any FadeOut/FadeIn as in my current code. How can I do it the right way?

var blinkAnimation = new DoubleAnimation
{
    From = 1,
    To = 0
};

var blinkStoryboard = new Storyboard
{
    Duration = TimeSpan.FromMilliseconds(500),
    RepeatBehavior = RepeatBehavior.Forever,
    AutoReverse = true
};

Storyboard.SetTarget(blinkAnimation, MyCanvas);
Storyboard.SetTargetProperty(blinkAnimation, new PropertyPath(OpacityProperty));

blinkStoryboard.Children.Add(blinkAnimation);
MyCanvas.BeginStoryboard(blinkStoryboard);

Maybe I can do that using the VisibilityProperty but I couldn't get it right.

Vahid
  • 5,144
  • 13
  • 70
  • 146
  • 1
    Maybe it's time to read the [Animation Overview](http://msdn.microsoft.com/en-us/library/ms752312.aspx) and [Animation Tips and Tricks](http://msdn.microsoft.com/en-us/library/bb613592.aspx) articles on MSDN. – Clemens May 11 '14 at 09:55
  • Thank you Clemens, I think it is. Actually since yesterday I only needed to get this effect I was being a little lazy to read lots of new stuff for this. But I'll definitely look at it now. – Vahid May 11 '14 at 09:57

2 Answers2

7

You might use a second animation with an appropriate BeginTime:

var switchOffAnimation = new DoubleAnimation
{
    To = 0,
    Duration = TimeSpan.Zero
};

var switchOnAnimation = new DoubleAnimation
{
    To = 1,
    Duration = TimeSpan.Zero,
    BeginTime = TimeSpan.FromSeconds(0.5)
};

var blinkStoryboard = new Storyboard
{
    Duration = TimeSpan.FromSeconds(1),
    RepeatBehavior = RepeatBehavior.Forever
};

Storyboard.SetTarget(switchOffAnimation, MyCanvas);
Storyboard.SetTargetProperty(switchOffAnimation, new PropertyPath(Canvas.OpacityProperty));
blinkStoryboard.Children.Add(switchOffAnimation);

Storyboard.SetTarget(switchOnAnimation, MyCanvas);
Storyboard.SetTargetProperty(switchOnAnimation, new PropertyPath(Canvas.OpacityProperty));
blinkStoryboard.Children.Add(switchOnAnimation);

MyCanvas.BeginStoryboard(blinkStoryboard);
Clemens
  • 123,504
  • 12
  • 155
  • 268
1

If you want on/off state for your animation you can change your animation to DoubleAnimationUsingKeyFrames

var blinkAnimation = new DoubleAnimationUsingKeyFrames();
blinkAnimation.KeyFrames.Add(new DiscreteDoubleKeyFrame(1, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(0))));
blinkAnimation.KeyFrames.Add(new DiscreteDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(250))));

var blinkStoryboard = new Storyboard
{
    Duration = TimeSpan.FromMilliseconds(500),
    RepeatBehavior = RepeatBehavior.Forever,
};

Storyboard.SetTarget(blinkAnimation, MyCanvas);
Storyboard.SetTargetProperty(blinkAnimation, new PropertyPath(OpacityProperty));

blinkStoryboard.Children.Add(blinkAnimation);
blinkStoryboard.Begin();
dkozl
  • 32,814
  • 8
  • 87
  • 89
  • I like this approach as well. But it behaves a little odd. It was a little fast at first. I played with the durations but I couldn't get the feel of `Blink` effect, Maybe I'm not entering the right values. – Vahid May 11 '14 at 10:03
  • 1
    Second `KeyFrame` time should be half of `Storyboard` duration. In this case 250/500 so if you want to make whole cycle take for example 1 sec then second `KeyFrame` should start at 500ms and `Storyboard` duration should be 1000ms – dkozl May 11 '14 at 10:21