I have a Button in my Window, how do I use code behind in C# to go about animating it to shift to the left by lets say 100 pixels once I click on it.
private void myButton_Click(object sender, System.Windows.RoutedEventArgs e)
{
// TODO: Add event handler implementation here.
DoubleAnimation _DoubleAnimation = new DoubleAnimation();
_DoubleAnimation.From = 0;
_DoubleAnimation.To = 100;
_DoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
myButton.BeginAnimation(Button.RenderTransformOriginProperty, _DoubleAnimation);
}
If you want to change the size, in this case must be WidthProperty in Animation:
myButton.BeginAnimation(Button.WidthProperty, _DoubleAnimation);
To avoid sharp transition in the Animation, you must explicitly set the Width of the Button:
<Button Name="myButton"
Width="30"
Content="Test"
Click="myButton_Click" />
And in Animation specify only To value:
private void myButton_Click(object sender, System.Windows.RoutedEventArgs e)
{
DoubleAnimation _DoubleAnimation = new DoubleAnimation();
_DoubleAnimation.To = 100;
_DoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
myButton.BeginAnimation(Button.WidthProperty, _DoubleAnimation);
}
If you want to shift Button in Animation, you can use ThicknessAnimation:
Thanks for the remark to #Rohit Vats
private void myButton_Click(object sender, System.Windows.RoutedEventArgs e)
{
ThicknessAnimation animation = new ThicknessAnimation(new Thickness(0),
new Thickness(100, 0, 0, 0),
new Duration(new TimeSpan(0, 0, 1)),
FillBehavior.HoldEnd);
myButton.BeginAnimation(Button.MarginProperty, animation);
}
If you want to shift button to left by 100 pixels, you have to set margin to -100 of last value which obviously can't be achieved by DoubleAnimation since it can animate only double values whereas Margin is of type Thickness.
You can achieved that using Storyboard:
Storyboard myStoryboard = new Storyboard();
ObjectAnimationUsingKeyFrames animation = new ObjectAnimationUsingKeyFrames();
animation.BeginTime = TimeSpan.FromSeconds(0);
Storyboard.SetTarget(animation, myButton);
Storyboard.SetTargetProperty(animation, new PropertyPath("Margin"));
double left = myButton.Margin.Left - 100;
DiscreteObjectKeyFrame keyFrame = new DiscreteObjectKeyFrame(new Thickness(left,
0, 0, 0), TimeSpan.FromSeconds(1));
animation.KeyFrames.Add(keyFrame);
myStoryboard.Children.Add(animation);
myStoryboard.Begin();
For smooth transition what you can do is add multiple key frames and play them in interval of 0.1 secs. In case you need more smooth transition, break it down to further smaller intervals.
This is how you do it:
Storyboard myStoryboard = new Storyboard();
ObjectAnimationUsingKeyFrames animation = new ObjectAnimationUsingKeyFrames();
animation.BeginTime = TimeSpan.FromSeconds(0);
Storyboard.SetTarget(animation, myButton);
Storyboard.SetTargetProperty(animation, new PropertyPath("Margin"));
for (int count = 1; count < 21; count++)
{
double left = myButton.Margin.Left - (5 * count);
DiscreteObjectKeyFrame keyFrame = new DiscreteObjectKeyFrame(new
Thickness(left, 0, 0, 0), TimeSpan.FromSeconds(0.05 * count));
animation.KeyFrames.Add(keyFrame);
}
myStoryboard.Children.Add(animation);
myStoryboard.Begin();
It is depends how you have placed the Button on the page. If you want to layout elements by coordinates (not recommended) you can place the button on Canvas. Then you can use code like this:
<Canvas>
<Button Canvas.Left="100" Canvas.Top="100" Name="btnOk" HorizontalAlignment="Center" VerticalAlignment="Center" Width="50" Click="BtnOk_OnClick">Ok</Button>
</Canvas>
and code-behind:
var doubleAnimation = new DoubleAnimation();
double left = Canvas.GetLeft(btnOk);
doubleAnimation.From = left;
doubleAnimation.To = left - 100;
doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
btnOk.BeginAnimation(Canvas.LeftProperty, doubleAnimation);
Related
these are my declaration for my DoubleAnimation and storyboard
private Storyboard openmenurotateSB;
DoubleAnimation openMenuRotate = new DoubleAnimation();
openMenuRotate.From = 0;
openMenuRotate.To = 90;
openMenuRotate.Duration = new Duration(TimeSpan.FromMilliseconds(1000));
openMenuRotate.FillBehavior = FillBehavior.Stop;
openMenuRotate.AutoReverse = true;
openmenurotateSB = new Storyboard();
openmenurotateSB.Children.Add(openMenuRotate);
Storyboard.SetTargetName(openMenuRotate, OpenMenuButton.Name);
Storyboard.SetTargetProperty(openMenuRotate, new PropertyPath(RotateTransform.AngleProperty));
when click, begin rotate animation
private void OpenMenu_Click(object sender, RoutedEventArgs e)
{
openmenurotateSB.Begin(OpenMenuButton);
}
There is no any error or exception, it just does not work.
Thanks in advance.
Xing Yik
A RotateTransform should be assigned to either the RenderTransform or the LayoutTransform property of the Button.
<Button Content="Open Menu" Click="OpenMenu_Click"
RenderTransformOrigin="0.5,0.5">
<Button.RenderTransform>
<RotateTransform x:Name="rotateTransform"/>
</Button.RenderTransform>
</Button>
You do not need to use a Storyboard. Just directly animate the RotateTransform.
private void OpenMenu_Click(object sender, RoutedEventArgs e)
{
var animation = new DoubleAnimation
{
To = 90,
Duration = TimeSpan.FromSeconds(1),
FillBehavior = FillBehavior.Stop,
AutoReverse = true
};
rotateTransform.BeginAnimation(
RotateTransform.AngleProperty, animation);
}
or if you don't want to assign an x:Name to the RotateTransform or have assigned the RenderTransform property in code behind:
((UIElement)sender).RenderTransform.BeginAnimation(
RotateTransform.AngleProperty, animation);
I'm working on the UI animations with my UWP project. When I combined the Storyboard with translate transform based on user's manipulation in a control, it's seem like the tranlastion didn't work anymore after the Storyboard had begun its animation.
After researching, I thought this is the reason -
that I can't change the value of a property after it has been animated, and I have to remove the Storyboard,... Unfortunately this article is support for WPF so I can't apply to my UWP project. So does anyone know any solutions for this situation ?
XAML:
<Frame x:Name="StoreFrame"
Grid.Row="1"
Grid.RowSpan="1"
MaxWidth="400"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ManipulationDelta="StoreFrame_OnManipulationDelta"
ManipulationMode="TranslateY">
<Frame.RenderTransform>
<CompositeTransform x:Name="Transform" />
</Frame.RenderTransform>
</Frame>
Manipulation event handler:
private void StoreFrame_OnManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
Transform.TranslateY += e.Delta.Translation.Y;
}
My Storyboard animation:
private void ShowStoreFrameAnimation()
{
VerticalAnimatiton(StoreFrame, StoreFrame.ActualHeight, 0);
}
public void VerticalAnimatiton(DependencyObject controlObject,
double fromValue, double toValue, double durationTime = 1000)
{
//The animation things
var storyboard = new Storyboard();
var duration = new Duration(TimeSpan.FromMilliseconds(durationTime));
var ease = new CubicEase { EasingMode = EasingMode.EaseOut };
var animation = new DoubleAnimation
{
EasingFunction = ease,
Duration = duration
};
storyboard.Children.Add(animation);
animation.From = fromValue;
animation.To = toValue;
animation.EnableDependentAnimation = false;
Storyboard.SetTarget(animation, controlObject);
Storyboard.SetTargetProperty(animation, "(UIElement.RenderTransform).(CompositeTransform.TranslateY)");
storyboard.Begin();
}
How to remove Storyboard after begin it in UWP?
I can't change the value of a property after it has been animated, and I have to remove the Storyboard.
As you said that we can't change the value of a property after it has been animated. And there is no viable way to remove the storyboard. But you can add the new storyboard for same property that has been used. the following code is a workaround for your scenario.
Add the new storyboard to the StoreFrame_OnManipulationDelta event method.
private void StoreFrame_OnManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
Transform.TranslateY += e.Delta.Translation.Y;
var duration = new Duration(TimeSpan.FromMilliseconds(1000));
var ease = new CubicEase { EasingMode = EasingMode.EaseOut };
var animation = new DoubleAnimation
{
EasingFunction = ease,
Duration = duration
};
var conStoryboard = new Storyboard();
conStoryboard.Children.Add(animation);
animation.From = Transform.TranslateY;
animation.To = Transform.TranslateY += e.Delta.Translation.Y;
animation.EnableDependentAnimation = false;
Storyboard.SetTarget(animation, StoreFrame);
Storyboard.SetTargetProperty(animation, "(UIElement.RenderTransform).(CompositeTransform.TranslateY)");
conStoryboard.Begin();
}
Animation effect
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);
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);
}
Im attempting to create a storyboard in C# not XAML to control scaling of an image, so i can easily alter the ScaleTransform.ScaleX and ScaleTransform.ScaleY values in a DoubleAnimation.
So far I believe i have created the animations and added it to a new storyboard, and the appropriate values change in the C# when i check with breakpoints, but it's not actually working.
My C# looks like this:
public void SetStatistics(double[] value)
{
Storyboard sb = new Storyboard();
sb.Duration = new Duration(TimeSpan.FromSeconds(1));
//Wedge Animation X-Axis
DoubleAnimation wax = new DoubleAnimation();
//Wedge Animation Y-Axis
DoubleAnimation way = new DoubleAnimation();
ScaleTransform st = ((ScaleTransform)FindName("wedge1scale"));
wax = new DoubleAnimation();
way = new DoubleAnimation();
wax.Duration = sb.Duration;
way.Duration = sb.Duration;
sb.Children.Add(wax);
sb.Children.Add(way);
Storyboard.SetTargetProperty(wax, new PropertyPath("(ScaleTransform.ScaleX)"));
//End scale from calculation with an Enum value
wax.To = StatMin + (StatPercent * value[1]);
//Start scale from current value
wax.From = st.ScaleX;
Storyboard.SetTargetProperty(way, new PropertyPath("(ScaleTransform.ScaleY)"));
//End scale from calculation with an Enum value
way.To = StatMin + (StatPercent * value[1]);
//Start scale from current value
way.From = st.ScaleY;
Storyboard.SetTarget(wax, Wedge1);
Storyboard.SetTarget(way, Wedge1);
Main.Resources.Add("animation", sb);
sb.Begin();
}
My XAML Image is like this:
<Image x:Name="Wedge1" Source="Images/Wedge.png" RenderTransformOrigin="-0.008,1.027" Height="682" Width="263" Canvas.Left="869.04" Canvas.Top="-158.251" >
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform x:Name="wedge1scale" ScaleX="0.555" ScaleY="0.555"/>
<TranslateTransform X="88.102" Y="-4.381"/>
</TransformGroup>
</Image.RenderTransform>
</Image>
Thanks in advance for any info :)
The problem is your PropertyPath. You would have to write RenderTransform.Children[0].ScaleX and RenderTransform.Children[0].ScaleY in order to animate the ScaleX and ScaleY properties of the first child of the TransformGroup in the Image's RenderTransform.
var wax = new DoubleAnimation { Duration = TimeSpan.FromSeconds(1) };
var way = new DoubleAnimation { Duration = TimeSpan.FromSeconds(1) };
wax.To = ...
way.To = ...
Storyboard.SetTargetProperty(
wax, new PropertyPath("RenderTransform.Children[0].ScaleX"));
Storyboard.SetTargetProperty(
way, new PropertyPath("RenderTransform.Children[0].ScaleY"));
Storyboard.SetTarget(wax, Wedge1);
Storyboard.SetTarget(way, Wedge1);
var sb = new Storyboard();
sb.Children.Add(wax);
sb.Children.Add(way);
sb.Begin();
And it would be less code without the Storyboard:
var wax = new DoubleAnimation { Duration = TimeSpan.FromSeconds(1) };
var way = new DoubleAnimation { Duration = TimeSpan.FromSeconds(1) };
wax.To = ...
way.To = ...
wedge1scale.BeginAnimation(ScaleTransform.ScaleXProperty, wax);
wedge1scale.BeginAnimation(ScaleTransform.ScaleYProperty, way);
And I guess in your case it isn't necessary to set the From property, as the animations start from the current property values by default.