Translate and scale animation - wpf

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.

Related

How to fix VisualBrush lost line?

In WPF ,we can use VisualBrush do some thing like ppt's left side.
But I see the VisualBrush may lost the line in Rectangle when I zoom the VisualBrush to a small size.Like the image:
You can see VisualBrush lost the Bottom line.
But what I want is like the below image:
When I try use the BitmapImage that use RenderTargetBitmap to get a image and use linear interpolation algorithm to zoom will get a clearness image.
Can I change VisualBrush's algorithm I think it may use neighborhood-pixels algorithm.
Are there any printscreen algorithm that have a good performance like VisualBrush.
When I change my search key to ViewBox ,I can find the same question as this one :how to avoid a single pixel line disappear in wpf?
There is a class named TransformedBitmap which can scale your RenderTargetBitmap with default scaling algorithm.
Use the code below:
public static BitmapSource ToBitmapSource(this Visual visual, Size size)
{
var bounds = VisualTreeHelper.GetDescendantBounds(visual);
var width = (int) Math.Round(bounds.Width);
var height = (int) Math.Round(bounds.Height);
var bitmap = new RenderTargetBitmap(width, height, 96.0, 96.0, PixelFormats.Pbgra32);
bitmap.Render(visual);
return new TransformedBitmap(bitmap, new ScaleTransform(size.Width / width, size.Height / height));
}
I've tried this method in my demo and got the result below. You may noticed that the small rectangle in the left-top corner lost nothing.

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

How to accelerate WPF fade in/out animation

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.

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.

Image Flipping in WPF

How do you get an image to be reflected in wpf without using the xaml? I have a rectangle with a BitmapImageBrush as its fill. I want to be able to regularly flip this image (X-axis) back and forth at will in C#. I've read about using the ScaleTransform property but this only seems to work in the xaml and that's not what I want.
This is how the image is created:
ImageBrush l = new ImageBrush(new BitmapImage(new Uri(uriPath, UriKind.Relative)));
_animation.Add(l);
_visual = new Rectangle();
_visual.Fill = _animation[0];
_visual.Width = width;
_visual.Height = height;
_visual.Visibility = Visibility.Visible;
_window.GameCanvas.Children.Add(_visual);
_animation is a list of ImageBrushes.
This is really simple, yet I can't seem to figure out how to do it. Please help.
You can still add a scale transform programmatically, rather than using xaml.
For instance, in this article.
To do the flip, set your scale transform to be negative in the direction you want to flip (ie, if horizontal, set x to -1, or -desiredScale if you also want to resize).

Resources