How to accelerate WPF fade in/out animation - wpf

I implemented lightbox effect with window's opacity change whilst fading in/out. When I have my window maximized this effect has big delay or when I use duration property then opacity change is not smooth.
I manage this eg. with like here:
DoubleAnimation animate = new DoubleAnimation();
animate.From = 1.0;
animate.To = 0.5;
animate.Duration = new Duration(TimeSpan.FromSeconds(0));
this.BeginAnimation(Window.OpacityProperty, animate); // main window
Window1 win = new Window1(); // new window to get focus
win.ShowDialog();
Tell me please, if you know, does this effect works on GPU by default? If not, can I manage this somehow?

The maximization issue sounds like the computer might have performance issues, and the Duration issue exists because you set it to 0, a zero second animation is instant, of course it is not smooth.

Related

WPF Animation (changing multiple properties of single element at the same time)

I need to animate multiple properties of one ui element at the same time.
For example, decreasing width and height of windows synchronously.
Any idea?
DoubleAnimation widthAnimation = new DoubleAnimation
{
To = 0,
Duration = TimeSpan.FromSeconds(5)
};
DoubleAnimation heightAnimation = new DoubleAnimation
{
To = 0,
Duration = TimeSpan.FromSeconds(5)
};
Storyboard.SetTargetProperty(widthAnimation, new PropertyPath(Window.WidthProperty));
Storyboard.SetTarget(widthAnimation, this);
Storyboard.SetTargetProperty(heightAnimation, new PropertyPath(Window.HeightProperty));
Storyboard.SetTarget(heightAnimation, this);
Storyboard s = new Storyboard();
s.Completed += FadeOut_Completed;
s.Children.Add(widthAnimation);
s.Children.Add(heightAnimation);
this.BeginStoryboard(s, HandoffBehavior.SnapshotAndReplace, true);
It will do animations step by step; height will change after width changes are complete! :|
After looking at your code I understand that you are trying to animate the width and height of Window simultenousely
But I would regret to tell you that since window is not an actual wpf component but a platform component. however content of window is completely controllable as expected via your code, but window is not. any such changes are routed through Pinvoke. and the issue you are facing is a known issue and the work around are bit complex
one solution is here, this uses pinvoke to animate the window's height and width
Animating a WPF window width and height
here is a bug for similar issue created at microsoft, result is (Closed, as Won't Fix)
https://connect.microsoft.com/VisualStudio/feedback/details/715415/window-width-height-animation-in-wpf-got-broken-on-net-framework-4-0
Extra
below is a sample which is not actually solving your problem but will help you to reduce the number of lines you need to perform such animations for other elements. It is a rewrite of your code in less lines
DoubleAnimation anim = new DoubleAnimation
{
To = 0,
Duration = TimeSpan.FromSeconds(5)
};
border.BeginAnimation(Border.HeightProperty, anim);
border.BeginAnimation(Border.WidthProperty, anim);
try this code with any element except window, I used a border with some color filled
apologies for overlooking the Window in your code at first sight

Translate and scale animation

I have a wpf application and image inside a canvas. The image is placed in 0,0.
I need to animate the image moving from 0,0 to 500,200 and in the same time growing (I like to make an effect like coming from far to near).
If I do this:
TranslateTransform ttx = new TranslateTransform();
TranslateTransform tty = new TranslateTransform();
DoubleAnimationUsingKeyFrames dax = new DoubleAnimationUsingKeyFrames();
dax.KeyFrames.Add(new LinearDoubleKeyFrame(500, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1))));
DoubleAnimationUsingKeyFrames day = new DoubleAnimationUsingKeyFrames();
day.KeyFrames.Add(new LinearDoubleKeyFrame(200, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1))));
TransformGroup tg = new TransformGroup();
tg.Children.Add(ttx);
tg.Children.Add(tty);
krug.RenderTransform = tg;
ttx.BeginAnimation(TranslateTransform.XProperty, dax);
tty.BeginAnimation(TranslateTransform.YProperty, day);
And this works fine. It animates the translation of the image "krug" from 0,0 to 500,200.
But when I add logic for zooming the image while translating like this:
ScaleTransform zoom = new ScaleTransform();
DoubleAnimationUsingKeyFrames zoomTimeline = new DoubleAnimationUsingKeyFrames();
zoomTimeline.KeyFrames.Add(new LinearDoubleKeyFrame(2, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1))));
tg.Children.Add(zoom);
zoom.BeginAnimation(ScaleTransform.ScaleXProperty, zoomTimeline);
zoom.BeginAnimation(ScaleTransform.ScaleYProperty, zoomTimeline);
Then the image does not stop to 500, 200 but goes more far. If the zoom factor is bigger, the translation goes more future. How can I control the animation to stop at 500,200 ?
The problem you run into when combining scale and translate transforms is that it will scale the translate transform from the point of origin(ScaleTransform.CenterX, ScaleTransform.CenterY)
For example, if you want to slide it to the right by 50, and double it's scale, it will actually move a net distance of 100.
Try animating the ScaleTransform.CenterX and ScaleTransform.CenterY to match your translate transform. I believe that would let you scale on the fly like you want.
Put the animations in a single storyboard and set the duration of the storyboard to control the length of the animations.
Then start the storyboard.
I found a solution. I created separate user control that only does ScaleTransform. Then I apply TranslateTransform on the user control.

Can't consistently maximize WPF window

I have a minimized WPF window. I click the item in the taskbar to maximize. It makes a little audio ding, then I try again, and again. Usually about the third try it will maximize. What could cause it to refuse my initial maximize attempt?
One possibility is that you have some code that's changing the value of the ResizeMode property to NoResize.
See this page for more: http://msdn.microsoft.com/en-us/library/ms748948.aspx
Second, you might be overriding OnStateChanged and not calling base.OnStateChanged() consistently.
Third, you may have something hogging the UI's thread during your first attempts. Once that task--whatever it is--stops blocking then WPF can repaint the window in restored/maximized state.
I had a similar problem when trying to manually maximize a custom window.
The solution was to put the next code in my maximize button...
this.SizeToContent = System.Windows.SizeToContent.Manual;
this.MaxWidth = double.PositiveInfinity;
this.MaxHeight = double.PositiveInfinity;
this.Width = double.NaN;
this.Height = double.NaN;
this.WindowState = WindowState.Maximized;
Where 'this' referes to the Window.

How to resize from the center of element?

I want to show new window with animation that enlarge the size from 0 to 300. In the Loaded event, I put this code:
DoubleAnimation heightAnim = new DoubleAnimation(0,300,TimeSpan.FromSeconds(1));
BeginAnimation(HeightProperty,heightAnim);
DoubleAnimation WidthAnim = new DoubleAnimation(0,300,TimeSpan.FromSeconds(1));
BeginAnimation(WidthProperty,WidthAnim);
This code work fine. But the construction starts on top - left corner of window and it expanded to right and down until it got 300 * 300 size.
I want it to start from the center and expand from there to all 4 sides.
How can I do it?
p.s. after trying Jogy answer, I realized that maybe better approach to get this effect is to apply animation on ScaleX and ScaleY instead of applying animation on the window size. Because when animation on window size , user will see only part of the content until it got to full size.
What do you think of ? What's better approach?
Thanks in advance!
In order to get this effect, I realized It's better use ScaleTransform. On Loaded event the code should be like this:
ScaleTransform scaleTransform = new ScaleTransform();
the 'grid' is element under Window and it's HorizontalElignment and VerticalElignment set to 'Center'
grid.LayoutTransform = scaleTransform;
DoubleAnimation heightAnim = new DoubleAnimation(0,1,TimeSpan.FromSeconds(1));
scaleTransform.BeginAnimation(ScaleTransform.ScaleYProperty,heightAnim);
DoubleAnimation WidthAnim = new DoubleAnimation(0,1,TimeSpan.FromSeconds(1));
scaleTransform.BeginAnimation((ScaleTransform.ScaleXProperty,WidthAnim);
Add two more animations, for the Top and Left properties, like this:
DoubleAnimation topAnim = new DoubleAnimation(this.Top, this.Top - 150, TimeSpan.FromSeconds(1));
BeginAnimation(TopProperty, topAnim);
DoubleAnimation leftAnim = new DoubleAnimation(this.Left, this.Left - 150, TimeSpan.FromSeconds(1));
BeginAnimation(LeftProperty, leftAnim);
You may also want to synchronize the animations, by putting them in a Storyboard.

In WPF, after DoubleAnimation UIElement property cannot be changed?

OK, I'm making a GUI for my MP3 player using WPF and I have a border that enlarges its width property for every second of the played track, thus making a "Progress Bar" for the currently played song. I named the border ProgressBarBorder. After the whole playlist is complete, I wanted to use a DoubleAnimation to fade out the border. Now, if I start the player again, the border reacts as it's supposed to (meaning the width starts from 0 and progresses to the end of the song), but the opacity property for some strange reason stays 0.0 (that is the value that DoubleAnimation sets). I have explicitly coded
ProgressBarBorder.Opacity = 1.0;
in the method that starts the playback. Nevertheless, it stays invisible. Now, if I don't use DoubleAnimation and just write
ProgressBarBorder.Opacity = 0.0;
when the playlist is complete, it does go back to 1.0 when I start the player again. This is the reason why I am positive that the animation is the one causing the problem. Also, isn't the property supposed to go back to it's original state after the animation is finished? If yes, my border should become visible automatically after the animation is complete.
Here's my partially pseudo-code:
if (TrackIsComplete)
{
DoubleAnimation Fading = new DoubleAnimation();
Fading.From = 1.0;
Fading.To = 0.0;
Fading.Duration = TimeSpan.FromSeconds(3);
ProgressBarBorder.BeginAnimation(Border.OpacityProperty, Fading);
}
and
private void PlayTrack()
{
ProgressBarBorder.Opacity = 1.0;
Play();
....
}
Could anyone help please? Thanks.
The animation is holding on to its target value. To free the dependency property of any animations, do a BeginAnimation with a null value:
private void PlayTrack()
{
ProgressBarBorder.BeginAnimation(Border.OpacityProperty, null);
ProgressBarBorder.Opacity = 1.0;
....
}
When an Animation ends, it continues holding the value. This is what is causing the behavior you noticed, where setting the property does not appear to update it. Here's some info on how to set a property after an animation has been applied to it.
Play around with the FillBevior of your animation timeline. This might help:
http://msdn.microsoft.com/en-us/library/system.windows.media.animation.fillbehavior.aspx

Resources