How to rotate animation my button when click in c# wpf - c#

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

Related

How to move a picture to where a cursor clicked on the canvas

I have an image of a character and I want to be able to move it to the position of where my/the user's cursor is clicking on my canvas. for example-if the user clicked on the middle of the screen, I want his animal to walk there gradually, (at a certain speed). Does anyone know how I can achieve that?
How to move a picture to where a cursor clicked on the canvas
For your requirement, you could create DoubleAnimation for image. You could get your cursor clicked position with PointerPressed event then pass the position X,Y value to DoubleAnimation ToProperty. I created the sample you could refer.
Code behind
public MainPage()
{
this.InitializeComponent();
RootCanvasLayout.PointerPressed += new PointerEventHandler(Pointer_Pressed);
}
private void Pointer_Pressed(object sender, PointerRoutedEventArgs e)
{
Windows.UI.Input.PointerPoint currentPoint = e.GetCurrentPoint(RootCanvasLayout);
CreateAnimation(currentPoint);
}
void CreateAnimation(PointerPoint point)
{ var duration = new Duration(TimeSpan.FromMilliseconds(1000));
DoubleAnimation doubleAnimationX = new DoubleAnimation();
DoubleAnimation doubleAnimationY = new DoubleAnimation();
doubleAnimationX.To = point.Position.X-Pic.ActualWidth/2;
doubleAnimationX.Duration = duration;
doubleAnimationY.To = point.Position.Y-Pic.ActualHeight/2;
doubleAnimationY.Duration = duration;
var conStoryboard = new Storyboard();
conStoryboard.Children.Add(doubleAnimationX);
conStoryboard.Children.Add(doubleAnimationY);
Storyboard.SetTarget(doubleAnimationX, Pic);
Storyboard.SetTarget(doubleAnimationY, Pic);
Storyboard.SetTargetProperty(doubleAnimationX, "(Canvas.Left)");
Storyboard.SetTargetProperty(doubleAnimationY, "(Canvas.Top)");
conStoryboard.Begin();
}
Xaml
<Canvas Name="RootCanvasLayout" Background="Ivory">
<Image Name="Pic" Width="100" Height="100"
Source="Assets/hello.png"
Canvas.Left="0"
Canvas.Top = "0"/>
</Canvas>

WPF RotateTransform not working

I found below code to let my image(indicator1) rotation.
But it's nothing happened when I click the button.
Anyone know how to solve it?
private void Button_Click(object sender, RoutedEventArgs e)
{
RotateTransform rotateTransform = indicator1.RenderTransform as RotateTransform;
DoubleAnimation doubleAnimation = new DoubleAnimation();
doubleAnimation.From = 0;
doubleAnimation.To = 360;
doubleAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(10000));
Storyboard.SetTarget(doubleAnimation, rotateTransform);
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath(RotateTransform.AngleProperty));
Storyboard storyboard = new Storyboard();
storyboard.RepeatBehavior = RepeatBehavior.Forever;
storyboard.Children.Add(doubleAnimation);
storyboard.Begin(this);
}
You don't need the Storyboard. Using a Storyboard from code behind requires a workaround to get the target name lookup to to work. I haven't researched the exact cause of this, or whether or not it's always an issue. The code below works.
Note that you'll be setting RepeatBehavior on the DoubleAnimation now.
private void Button_Click(object sender, RoutedEventArgs e)
{
RotateTransform rotateTransform = indicator1.RenderTransform as RotateTransform;
DoubleAnimation doubleAnimation = new DoubleAnimation();
doubleAnimation.From = 0;
doubleAnimation.To = 360;
doubleAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(10000));
doubleAnimation.RepeatBehavior = RepeatBehavior.Forever;
rotateTransform.BeginAnimation(RotateTransform.AngleProperty, doubleAnimation);
}

How to remove Storyboard after begin it in UWP?

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

Shifting a Button Animation using System.Windows.Media.Animation

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

Resizing animation on SizeChanged event doesn't work as it should

I want a resizing animation when stackpanel visibility is set to visible state, but instead of that, I'm getting neverending flickering of border containing stackpanel.I don't think I'm doing it wrong.
Stack panel contains an instance of TextBlock.
private void MyBorder_SizeChanged_1(object sender, SizeChangedEventArgs e)
{
if (!first)
{
DoubleAnimation anim = new DoubleAnimation();
anim.From = e.PreviousSize.Height;
anim.To = e.NewSize.Height;
anim.Duration = new Duration(TimeSpan.FromSeconds(1));
Storyboard.SetTarget(anim, MyBorder);
Storyboard.SetTargetProperty(anim, new PropertyPath(Border.HeightProperty));
Storyboard st = new Storyboard();
st.Children.Add(anim);
st.Begin();
}
first = false;
}
private void MyBorder_Tap_1(object sender, GestureEventArgs e)
{
if (MyPanel.Visibility == Visibility.Collapsed)
MyPanel.Visibility = Visibility.Visible;
else
MyPanel.Visibility = Visibility.Collapsed;
}
The problem is that when you animate the height of the border it will trigger the SizeChanged event so you have a loop: size changed event>animate height>size changed event> ..
Also when the sized changed event is fired, the size change has already taken placed so even if that was working you will get a little flicking when it go back to do the animation.
Finally using HEight in an animation force a rendering update so that is not hardware accelerated.
Probably the best would be to either do a Translate Transform or a Scale Transform.
For exemple you could do a scale transform between 0 and 1 directly on MyPanel in the tap event.
This might help you to. It is a work around
private void MyBorder_SizeChanged_1(object sender, SizeChangedEventArgs e)
{
if (!first)
{
DoubleAnimation anim = new DoubleAnimation();
anim.From = e.PreviousSize.Height;
anim.To = e.NewSize.Height;
anim.Duration = new Duration(TimeSpan.FromSeconds(1));
Storyboard.SetTarget(anim, MyBorder);
Storyboard.SetTargetProperty(anim, new PropertyPath(Border.HeightProperty));
Storyboard st = new Storyboard();
st.Children.Add(anim);
st.Completed += st_Completed;
MyBorder.SizeChanged -= MyBorder_SizeChanged_1;
st.Begin();
}
first = false;
}
void st_Completed(object sender, EventArgs e)
{
MyBorder.SizeChanged += MyBorder_SizeChanged_1;
}
private void MyBorder_Tap_1(object sender, GestureEventArgs e)
{
if (MyPanel.Visibility == Visibility.Collapsed)
MyPanel.Visibility = Visibility.Visible;
else
MyPanel.Visibility = Visibility.Collapsed;
}
With reference to the fact that border is getting resized even in the storyboard its better to remove the event of size changed. Try animating the parent container on chld size changed some thing kind of this
I've solved this problem. Silly my, I thought that Measure method of StackPanel is private, and didn't bother to make sure about it, here's solution code for expanding StackPanel on Click.
private void MyBorder_Tap_1(object sender, GestureEventArgs e)
{
if (MyPanel.Visibility == Visibility.Collapsed)
{
MyPanel.Visibility = Visibility.Visible;
MyPanel.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
DoubleAnimation anim = new DoubleAnimation();
anim.From = MyBorder.ActualHeight;
anim.To = MyBorder.ActualHeight + MyPanel.DesiredSize.Height;
anim.Duration = new Duration(TimeSpan.FromSeconds(0.25));
Storyboard.SetTarget(anim, MyBorder);
Storyboard.SetTargetProperty(anim, new PropertyPath(Border.HeightProperty));
Storyboard st = new Storyboard();
st.Children.Add(anim);
st.Begin();
}
else
{
MyPanel.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
DoubleAnimation anim = new DoubleAnimation();
anim.From = MyBorder.ActualHeight;
anim.To = MyBorder.ActualHeight - MyPanel.DesiredSize.Height;
anim.Duration = new Duration(TimeSpan.FromSeconds(0.25));
Storyboard.SetTarget(anim, MyBorder);
Storyboard.SetTargetProperty(anim, new PropertyPath(Border.HeightProperty));
Storyboard st = new Storyboard();
st.Children.Add(anim);
st.Completed += (a,b) => { MyPanel.Visibility = Visibility.Collapsed; };
st.Begin();
}
}

Categories