Animate window width right to left - c#

I am making a sidebar-style app which is located on the left of right side of the screen.
I am trying to make it look like it's sliding in and out of the screen, but when it's on the right, it slides in from the left still.
I can't find any right to left options regarding window width, so I was hoping to find the answer here.
Here is my current working animation code for left to right:
public static void AnimateSize(this Window target, double newWidth, EventHandler completed)
{
var length = new TimeSpan(0, 0, 0, 0, Settings.Default.AnimationTime);
var sb = new Storyboard {Duration = new Duration(length)};
var aniWidth = new DoubleAnimationUsingKeyFrames();
aniWidth.Duration = new Duration(length);
aniWidth.KeyFrames.Add(new EasingDoubleKeyFrame(target.ActualWidth,
KeyTime.FromTimeSpan(new TimeSpan(0, 0, 0, 0, 00))));
aniWidth.KeyFrames.Add(new EasingDoubleKeyFrame(newWidth, KeyTime.FromTimeSpan(length)));
Storyboard.SetTarget(aniWidth, target);
Storyboard.SetTargetProperty(aniWidth, new PropertyPath(FrameworkElement.WidthProperty));
sb.Children.Add(aniWidth);
sb.Completed += completed;
sb.Begin();
}
called like this:
_window.AnimateSize(0, delegate { _window.Hide(); });
and this:
_window.Width = 0;
_window.Show();
_window.AnimateSize(Settings.Default.Width, delegate { });
Thanks.

private void Animate(double beginfrom, double to, DependencyProperty dp)
{
var da = new DoubleAnimation {
From = beginfrom,
To = to,
FillBehavior = FillBehavior.Stop,
Duration = new Duration(TimeSpan.FromSeconds(0.3)),
AccelerationRatio = 0.1
};
var storyBoard = new Storyboard();
storyBoard.Children.Add(da);
Storyboard.SetTarget(da, this); //this = your control object
Storyboard.SetTargetProperty(da, new PropertyPath(dp));
storyBoard.Begin();
}
Simple usage: Animate(0, 250, WidthProperty);

I had similar task to accomplish. I used to animate the left property of my window and make it appear as though it slides from the outside and disappears in the same fashion. but when a colleague who uses two screens used it , the window would slide onto the other screen.
The work around used was to simultaneously animate the width and left properties. this gives the effect of the window appearing at the desired location and unfurling towards the left.
DoubleAnimation daLeftAppear = new DoubleAnimation(popupWidthDetails.workAreaWidth, (<workAreaWidth> - <windowWidth> - 5), new Duration(TimeSpan.FromSeconds(1)));
daLeftAppear.EasingFunction = new QuarticEase();
Storyboard.SetTargetName(daLeftAppear, this.Name);
Storyboard.SetTargetProperty(daLeftAppear, new PropertyPath(LeftProperty));
DoubleAnimation daWidthAppear = new DoubleAnimation(0, 100, new Duration(TimeSpan.FromSeconds(1)));
daWidthAppear.EasingFunction = new QuarticEase();
Storyboard.SetTargetName(daWidthAppear, this.Name);
Storyboard.SetTargetProperty(daWidthAppear, new PropertyPath(WidthProperty));
sbAppear = new Storyboard();
sbAppear.Children.Add(daLeftAppear);
sbAppear.Children.Add(daWidthAppear);

Related

Apply transformation on an image on C# for a Windows Phone application

I'm working on a mini-game where I need to make images go from their initial position to another using a translation transformation.
The problem is: I don't know how to proceed to apply the translation.
So here's the code used to generate my images.
Image myImage1 = new Image();
myImage1.Source = new BitmapImage(new Uri("/Images/image1.png", UriKind.Relative));
myImage1.Name = "image" + index++.ToString();
myImage1.Tap += myImage_Tap;
Canvas.SetLeft(image, 200);
Canvas.SetTop(image, 600);
gameArea.Children.Add(image);
Thanks for your time.
You have two choices to move your image around. The first is using a Canvas like your code shows, but you have to make sure your element is actually within a Canvas. Is your "gameArea" a Canvas? If it's not, your code won't work. The other option is to use Transforms.
var myImage1 = new Image
{
Source = new BitmapImage(new Uri("/Images/image1.png", UriKind.Relative)),
Name = "image" + index++.ToString(),
Tap += myImage_Tap,
RenderTransform = new TranslateTransform
{
X = 200,
Y = 600
}
};
gameArea.Children.Add(image);
Now gameArea can be any type of Panel and it will work.
Note that when using a Canvas, your Top and Left will be from the upper left corner of the Canvas. When using a Transform, your X and Y will be relative to where the element would have originally be drawn.
UPDATE -- Helper class to do simple animations using a Canvas
public sealed class ElementAnimator
{
private readonly UIElement _element;
public ElementAnimator(UIElement element)
{
if (null == element)
{
throw new ArgumentNullException("element", "Element can't be null.");
}
_element = element;
}
public void AnimateToPoint(Point point, int durationInMilliseconds = 300)
{
var duration = new Duration(TimeSpan.FromMilliseconds(durationInMilliseconds));
var easing = new BackEase
{
Amplitude = .3
};
var sb = new Storyboard
{
Duration = duration
};
var animateLeft = new DoubleAnimation
{
From = Canvas.GetLeft(_element),
To = point.X,
Duration = duration,
EasingFunction = easing,
};
var animateTop = new DoubleAnimation
{
From = Canvas.GetTop(_element),
To = point.Y,
Duration = duration,
EasingFunction = easing,
};
Storyboard.SetTargetProperty(animateLeft, "(Canvas.Left)");
Storyboard.SetTarget(animateLeft, _element);
Storyboard.SetTargetProperty(animateTop, "(Canvas.Top)");
Storyboard.SetTarget(animateTop, _element);
sb.Children.Add(animateLeft);
sb.Children.Add(animateTop);
sb.Begin();
}
}
So here's what I did with your code, I took just this part and made it a function:
public void AnimateToPoint(UIElement image, Point point, int durationInMilliseconds = 300)
{
var duration = new Duration(TimeSpan.FromMilliseconds(durationInMilliseconds));
var sb = new Storyboard
{
Duration = duration
};
var animateTop = new DoubleAnimation
{
From = Canvas.GetTop(image),
To = point.Y,
Duration = duration
};
Storyboard.SetTargetProperty(animateTop, new PropertyPath("Canvas.Top")); // You can see that I made some change here because I had an error with what you gave me
Storyboard.SetTarget(animateTop, image);
sb.Children.Add(animateTop);
sb.Begin();
}
And then I made the call with:
Point myPoint = new Point(leftpos, 300); // leftpos is a variable generated randomly
AnimateToPoint(myImage, myPoint);
So now there is still a single error, and it's in the instruction "sb.Begin;".
And it says: Cannot resolve TargetProperty Canvas.Top on specified object.
I reaylly don't know how to proceed.
Thanks for your previous answer!

Create a Blink animation in WPF in code behind

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.
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);
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();

Cannot set width or height of animated control in WPF programmatically (not even through Snoop)

This may be animation related. I have a WPF control whose width and height I'm animating through several different storyboards. I create the storyboards and then call Begin() on them. I've provided code for how the storyboards look below.
I want to re-evaluate the control size on some event (e.g. window resize) so that it is different from the value that was animated. I attempt to handle this on SizeChanged manually (after the animation has run) by setting the Width and Height properties of my control. The debugger shows that those values are not set (the original values remain).
When I inspect the WPF through Snoop, the Width and Height rows are highlighted in a peach/orange color and trying to set the values through it again does not persist it (the original value is shown when I focus away. My guess is that my animation is somehow overriding manual changes to the property but I'm not sure if this is true or how to solve it.
Storyboard Class
public class MyAnimationClass
{
private Storyboard _myStoryboard;
private DoubleAnimation _animation1;
private DoubleAnimation _animation2;
private DoubleAnimation _animation3;
private void InitializeStoryboard()
{
_myStoryboard = CreateMyStoryboard(out _animation1, out _animation2, out _animation3);
}
private Storyboard CreateMyStoryboard(out DoubleAnimation animation1, out DoubleAnimation animation2, out DoubleAnimation animation3)
{
var myStoryboard = new Storyboard();
// create animations
animation1 = new DoubleAnimation { Duration = new TimeSpan(0, 0, 0, 0, 250), From = 0, To = 0 };
animation2 = new DoubleAnimation { BeginTime = new TimeSpan(), Duration = new TimeSpan(0, 0, 0, 0, 250), From = 35, To = 35 };
animation3 = new DoubleAnimation { BeginTime = new TimeSpan(0, 0, 0, 0, 250), Duration = new TimeSpan(0, 0, 0, 0, 250), From = 35, To = 0 };
Storyboard.SetTargetProperty(animation1, new PropertyPath(FrameworkElement.WidthProperty));
Storyboard.SetTargetProperty(animation2, new PropertyPath(FrameworkElement.HeightProperty));
Storyboard.SetTargetProperty(animation3, new PropertyPath(FrameworkElement.HeightProperty));
myStoryboard.Children.Add(animation1);
myStoryboard.Children.Add(animation2);
myStoryboard.Children.Add(animation3);
return myStoryboard;
}
public void Animate(Control controlToAnimate)
{
// ....
var finalWidth = CalculateFinalWidth();
var finalHeight = CalculateFinalHeight();
_animation1.To = finalWidth;
_animation3.To = finalHeight;
_myStoryboard.Begin(controlToAnimate);
}
}
When I want to animate something, I call Animate() on the instance of my MyAnimationClass class.
Thoughts?
This ended up being a pretty simple fix. The value wasn't changing because of FillBehavior controlling the property value. However, simply changing it to FillBehavior.Stop didn't solve my problem because when my non-animation code set width/height, the next time my animation ran it would animate to the width/height I wanted and then default back to the set height. This was solved by setting the width/height of the control after calculation and before animation:
public void Animate(Control controlToAnimate)
{
// ....
var finalWidth = CalculateFinalWidth();
var finalHeight = CalculateFinalHeight();
// set values here so after animation they stay
controlToAnimate.Width = finalWidth;
controlToAnimate.Height = finalHeight;
_animation1.To = finalWidth;
_animation3.To = finalHeight;
_myStoryboard.Begin(controlToAnimate);
}

Dependency property's set doesn't update its value

I have popup and i have a animation using its horizontal and vertical offsets. This Animation takes these offsets as values and have a simple storyboard. For the 1st time it works fine and the second time, the Horizontal offset was not updating the value. I dono why its like this. I have checked the Dp with the property changed handlers, its not get changed. Retains its old value. There is no binding at all, value is set directly.
What might be the reason for this. Any idea on this??
var duration = new TimeSpan(0, 0, 0, 0, 200);
horizontalDoubleAnimation = new EasingDoubleKeyFrame();
verticalDoubleAnimation = new EasingDoubleKeyFrame();
horizontalDoubleAnimation.KeyTime = KeyTime.FromTimeSpan(duration);
verticalDoubleAnimation.KeyTime = KeyTime.FromTimeSpan(duration);
horizontalDoubleAnimation.EasingFunction = new CircleEase();
verticalDoubleAnimation.EasingFunction = new CircleEase();
DoubleAnimationUsingKeyFrames horizontalAnimationUsingKeyFrames = new DoubleAnimationUsingKeyFrames();
DoubleAnimationUsingKeyFrames verticalAnimationUsingKeyFrames = new DoubleAnimationUsingKeyFrames();
horizontalAnimationUsingKeyFrames.KeyFrames.Add(horizontalDoubleAnimation);
verticalAnimationUsingKeyFrames.KeyFrames.Add(verticalDoubleAnimation);
reverseAnimationStoryboard = new Storyboard { Duration = duration };
reverseAnimationStoryboard.Children.Add(horizontalAnimationUsingKeyFrames);
reverseAnimationStoryboard.Children.Add(verticalAnimationUsingKeyFrames);
Storyboard.SetTarget(horizontalAnimationUsingKeyFrames, this.DraggablePopup);
Storyboard.SetTarget(verticalAnimationUsingKeyFrames, this.DraggablePopup);
Storyboard.SetTargetProperty(horizontalAnimationUsingKeyFrames, new PropertyPath("HorizontalOffset"));
Storyboard.SetTargetProperty(verticalAnimationUsingKeyFrames, new PropertyPath("VerticalOffset"));
this.DraggablePopup.Resources.Add("storyboard", reverseAnimationStoryboard);

WPF Can the animation reverse be invoked explicitly?

Animations in WPF provide the boolean parameter AutoReverse. Is it possible to make a call to the functionality implemented by AutoReverse = "true"?
My goal is to spare some troublesome reverse animation and especially spare alot of code. The reverse must not happen directly after the animation ended.
Example of using AutoReverse and True to animate only the reverse animation, but this does not work as required - it still animates the actual animation and the reverse animation.
TranslateTransform transform = new TranslateTransform(0.0, 0.0);
myBox.RenderTransform = transform;
sb = new Storyboard();
Duration dur = new Duration(TimeSpan.FromSeconds(0.5));
DoubleAnimation shiftAnimation = new DoubleAnimation(100.0, dur);
shiftAnimation.AutoReverse = true;
sb.Children.Add(shiftAnimation);
Storyboard.SetTarget(shiftAnimation, myBox);
Storyboard.SetTargetProperty(shiftAnimation, new PropertyPath("RenderTransform.X"));
sb.Seek(TimeSpan.FromSeconds(0.5));
sb.Begin();
you could set the timeclock to 100% of the animationduration so when the animation starts, it will skip the non-reversed part!
Edit:
if Duration is set to 0:0:1.5 you apply a new timeline to your animation set to 0:0:1.5. Autoreverse has to be set to on and then you yust have to start the animation.
Edit 2:
TranslateTransform transform = new TranslateTransform(0.0, 0.0);
myBox.RenderTransform = transform;
sb = new Storyboard();
Duration dur = new Duration(TimeSpan.FromSeconds(0.5));
DoubleAnimation shiftAnimation = new DoubleAnimation(100.0, dur);
shiftAnimation.AutoReverse = true;
sb.Children.Add(shiftAnimation);
Storyboard.SetTarget(shiftAnimation, myBox);
Storyboard.SetTargetProperty(shiftAnimation, new PropertyPath("RenderTransform.X"));
sb.Begin();
sb.Pause();
sb.Seek(sb.Duration.TimeSpan);
sb.Resume();
I have found that the following code works nicely:
private bool reverse=false;
TimeSpan animationDuration = TimeSpan.FromMilliseconds(500);
Storyboard storyboard1 = new Storyboard();
private void prepareStoryBoard(Button btn)
{
btn.RenderTransform = new CompositeTransform();
DoubleAnimation animationShrink = new DoubleAnimation() { To = 0,
Duration =animationDuration , FillBehavior = FillBehavior.HoldEnd };
storyboard1.Children.Add(animationShrink);
Storyboard.SetTarget(animationShrink, btn);
Storyboard.SetTargetProperty(animationShrink,
"(Button.RenderTransform).(CompositeTransform.ScaleX)");
}
private void toggleAnimate()
{
if(reverse==false)
{
storyboard1.AutoReverse = false;
storyboard1.Begin();
reverse=true;
}
else
{
storyboard1.AutoReverse = true;
storyboard1.Seek(animationDuration);
storyboard1.Resume();
reverse = false;
}
}
The first time toggleAnimate() is called, the animation is executed in the normal direction, the second time toggleAnimate() is invoked the animation is reversed.

Categories