I want to move car to point 0, 0 with moving animations, but the problem is that I get an error then I use this function - https://gyazo.com/1f47e18f955c12dc1907fcf4d7b19d6a.
App look:
https://gyazo.com/10fb071534809229cb98955f9fb86231.
There is my code (I found this function in one article WPF. Easiest way to move Image to (X,Y) programmatically?):
public void Eiti(Image target, double newX, double newY)
{
var top = Canvas.GetTop(target);
var left = Canvas.GetLeft(target);
TranslateTransform trans = new TranslateTransform();
target.RenderTransform = trans;
DoubleAnimation anim1 = new DoubleAnimation(top, newY - top, TimeSpan.FromSeconds(10));
DoubleAnimation anim2 = new DoubleAnimation(left, newX - left, TimeSpan.FromSeconds(10));
trans.BeginAnimation(TranslateTransform.XProperty, anim1);
trans.BeginAnimation(TranslateTransform.YProperty, anim2);
}
and xaml:
<DockPanel Grid.Row="1" Background="#FF695887">
<Canvas>
<Image Name="car1" />
</Canvas>
</DockPanel>
How to solve it ?
public void Eiti(Image target, double newX, double newY)
{
var top = Canvas.GetTop(target);
var left = Canvas.GetLeft(target);
top = Double.IsNaN(top) ? 0 : top;
left = Double.IsNaN(left) ? 0 : left;
var storyboard = new Storyboard();
DoubleAnimation anim1 = new DoubleAnimation(top, newY, TimeSpan.FromSeconds(10));
Storyboard.SetTarget(anim1, target);
Storyboard.SetTargetProperty(anim1, new PropertyPath(Canvas.TopProperty));
storyboard.Children.Add(anim1);
DoubleAnimation anim2 = new DoubleAnimation(left, newX, TimeSpan.FromSeconds(10));
Storyboard.SetTarget(anim2, target);
Storyboard.SetTargetProperty(anim2, new PropertyPath(Canvas.LeftProperty));
storyboard.Children.Add(anim2);
storyboard.Begin();
}
Related
First of all I place here my situation sreenshot:
So I need to move these cars(cars are Images) where the arrow goes.
For driving straight I use this function:
private static void Eiti(Image target, double naujasX, double naujasY, double greitis, char kelias)
{
var top = Canvas.GetTop(target);
var left = Canvas.GetLeft(target);
top = Double.IsNaN(top) ? 0 : top;
left = Double.IsNaN(left) ? 0 : left;
naujasY = Paveikslas.canvasY(naujasY, kelias);
var storyboard = new Storyboard();
greitis = 100 / greitis; // apverciamas greitis, kad butu logiska
storyboard.Completed += Storyboard_Completed;
if (naujasY != -1) // isejimo simbolis (escape)
{
DoubleAnimation anim1 = new DoubleAnimation(top, naujasY, TimeSpan.FromSeconds(greitis));
Storyboard.SetTarget(anim1, target);
Storyboard.SetTargetProperty(anim1, new PropertyPath(Canvas.TopProperty));
storyboard.Children.Add(anim1);
DoubleAnimation anim2 = new DoubleAnimation(left, naujasX, TimeSpan.FromSeconds(greitis));
Storyboard.SetTarget(anim2, target);
Storyboard.SetTargetProperty(anim2, new PropertyPath(Canvas.LeftProperty));
storyboard.Children.Add(anim2);
}
storyboard.Begin();
}
and it's working good for me!
But now I have problem with rotating and driving car at the same time (for example like in my screenshot driving through green square).
Is there any function or other ways to solve this ?
the translate works fine, but there is no rotation, can you please help me?
TranslateTransform trans = new TranslateTransform();
Pointer.RenderTransform = trans;
DoubleAnimation animX = new DoubleAnimation(fromX, toX, TimeSpan.FromMilliseconds(325));
DoubleAnimation animY = new DoubleAnimation(fromY, toY, TimeSpan.FromMilliseconds(325));
DoubleAnimation rotateBy = new DoubleAnimation(0, 90, TimeSpan.FromMilliseconds(325));
animX.EasingFunction = new SineEase { EasingMode = EasingMode.EaseInOut };
animY.EasingFunction = new SineEase { EasingMode = EasingMode.EaseInOut };
animX.Completed += new EventHandler(myanim_Completed);
trans.BeginAnimation(TranslateTransform.XProperty, animX);
trans.BeginAnimation(TranslateTransform.YProperty, animY);
trans.BeginAnimation(RotateTransform.AngleProperty, rotateBy);
TranslateTransform doesn't have an Angle property. You should use a TransformGroup:
var group = new TransformGroup();
var trans = new TranslateTransform();
group.Children.Add(trans);
var rotate = new RotateTransform();
group.Children.Add(rotate);
Pointer.RenderTransform = group;
// the rest of the code is fine; only the last line needs fixing:
rotate.BeginAnimation(RotateTransform.AngleProperty, rotateBy);
You should also look into using Storyboard to group your animations.
I am able to animate the movement of a Border:
private void MoveTo(Border target, double newX, double newY)
{
Vector offset = VisualTreeHelper.GetOffset(target);
var top = offset.Y;
var left = offset.X;
TranslateTransform trans = new TranslateTransform();
target.RenderTransform = trans;
DoubleAnimation anim1 = new DoubleAnimation(0, newY - top, TimeSpan.FromMilliseconds(500));
DoubleAnimation anim2 = new DoubleAnimation(0, newX - left, TimeSpan.FromMilliseconds(500));
trans.BeginAnimation(TranslateTransform.YProperty, anim1);
trans.BeginAnimation(TranslateTransform.XProperty, anim2);
}
But I would like to be able to animate an increase in Height and Width as well as position to give the impression of enlarging an image(which is contained in a Border in my case and example above)).
Is this spossible with code behind?
OK, I tried the scale transform but it does not appear to do anything - do I need a storyboard?
private void Zoom(Border target)
{
TranslateTransform trans = new TranslateTransform();
target.RenderTransform = trans;
DoubleAnimation anim1 = new DoubleAnimation(1, 2, TimeSpan.FromMilliseconds(1000));
DoubleAnimation anim2 = new DoubleAnimation(1, 2, TimeSpan.FromMilliseconds(1000));
trans.BeginAnimation(ScaleTransform.ScaleXProperty, anim1);
trans.BeginAnimation(ScaleTransform.ScaleYProperty, anim2);
}
It is better to use scale transform for zooming, but if you insist on animating W/H you can do it, since these are normal DP you can animate them using standard DoubleAnimation/DoubleAnimationUsingKeyFrames
Something like
DoubleAnimation doubleAnimation = new DoubleAnimation(100, 200, new Duration(TimeSpan.FromMilliseconds(500)));
this.BeginAnimation(FrameworkElement.WidthProperty, doubleAnimation);
Use ScaleTransform, no need for Height & Width animations, the ScaleTransform will affect your Border's VisualTree so the inner image will be stretched as well.
private void Zoom(Border target)
{
ScaleTransform trans = new ScaleTransform();
target.RenderTransform = trans;
// if you use the same animation for X & Y you don't need anim1, anim2
DoubleAnimation anim = new DoubleAnimation(1, 2, TimeSpan.FromMilliseconds(1000));
trans.BeginAnimation(ScaleTransform.ScaleXProperty, anim);
trans.BeginAnimation(ScaleTransform.ScaleYProperty, anim);
}
I am trying to get these ellipses to grow but I cannot figure out how to start the animation. This is my first attempt at WPF animation and I don't quite understand how it all works.
private void drawEllipseAnimation(double x, double y)
{
StackPanel myPanel = new StackPanel();
myPanel.Margin = new Thickness(10);
Ellipse e = new Ellipse();
e.Fill = Brushes.Yellow;
e.Stroke = Brushes.Black;
e.Height = 0;
e.Width = 0;
e.Opacity = .8;
canvas2.Children.Add(e);
Canvas.SetLeft(e, x);
Canvas.SetTop(e, y);
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 0;
myDoubleAnimation.To = 10;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));
myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);
Storyboard.SetTargetName(myDoubleAnimation, e.Name);
Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Ellipse.HeightProperty));
Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Ellipse.WidthProperty));
}
You don't need a Storyboard here. Just do
e.BeginAnimation(Ellipse.WidthProperty, myDoubleAnimation);
e.BeginAnimation(Ellipse.HeightProperty, myDoubleAnimation);
If you really need to do it with a Storyboard, you will have to add separate animations, one per animated property, to the Storyboard. And you have to call SetTarget instead of SetTargetName when you don't apply a name. Finally you'll need to start the Storyboard by calling Begin:
DoubleAnimation widthAnimation = new DoubleAnimation
{
From = 0,
To = 10,
Duration = TimeSpan.FromSeconds(5)
};
DoubleAnimation heightAnimation = new DoubleAnimation
{
From = 0,
To = 10,
Duration = TimeSpan.FromSeconds(5)
};
Storyboard.SetTargetProperty(widthAnimation, new PropertyPath(Ellipse.WidthProperty));
Storyboard.SetTarget(widthAnimation, e);
Storyboard.SetTargetProperty(heightAnimation, new PropertyPath(Ellipse.HeightProperty));
Storyboard.SetTarget(heightAnimation, e);
Storyboard s = new Storyboard();
s.Children.Add(widthAnimation);
s.Children.Add(heightAnimation);
s.Begin();
I'm designing a game like this
class Anima
{
Storyboard story;
Random rand;
Canvas canvas;
Ellipse target;
public Anima() {
rand = new Random();
canvas = new Canvas();
target = new Ellipse();
target.Fill = Brushes.Red;
target.Width = 50;
target.Height = 50;
Canvas.SetLeft(target, rand.NextDouble() * 300);
Canvas.SetTop(target, rand.NextDouble() * 300);
canvas.Children.Add(target);
story = new Storyboard();
story.BeginTime = TimeSpan.FromMilliseconds(rand.Next(500, 5000));
DoubleAnimation a = new DoubleAnimation();
a.To = rand.NextDouble() * 300;
a.Duration = new Duration(TimeSpan.FromMilliseconds(50));
Storyboard.SetTarget(a, target);
Storyboard.SetTargetProperty(a, new PropertyPath(Canvas.LeftProperty));
story.Children.Add(a);
DoubleAnimation b = new DoubleAnimation();
b.To = rand.NextDouble() * 300;
b.Duration = new Duration(TimeSpan.FromMilliseconds(50));
Storyboard.SetTarget(b, target);
Storyboard.SetTargetProperty(b, new PropertyPath(Canvas.TopProperty));
story.Children.Add(b);
story.Completed += new EventHandler(story_Completed);
Window win = new Window();
win.Loaded += delegate(object sender, RoutedEventArgs e) {
story.Begin();
};
win.Content = canvas;
win.Show();
}
void story_Completed(object sender, EventArgs e) {
int next = rand.Next(500, 5000);
double left = rand.NextDouble() * 300;
double top = rand.NextDouble() * 300;
Console.WriteLine("position: ({0:G6}, {1:G6})", Canvas.GetLeft(target), Canvas.GetTop(target));
Console.WriteLine("state : wait for " + next + " ms");
Console.WriteLine("next : ({0:G6}, {1:G6})", left, top);
Console.WriteLine();
(story.Children[0] as DoubleAnimation).To = left;
(story.Children[1] as DoubleAnimation).To = top;
story.BeginTime = TimeSpan.FromMilliseconds(next);
story.Begin();
}
}
Everything is great, but I found that the ellipse didn't get the right position and make an error about 2% to 50%. It seems like the Storyboard.Completed event triggered before the end of animation.
What's wrong with it?
I would suggest that you use CompositionTarget.Rendering event or DispatcherTimer for controlling complex animations, especially if you are developing a game. The built-in animations are not precise enough and cannot be controlled easily.
Here are some links that will get you started on CompositionTarget
How to: Render on a Per Frame Interval Using CompositionTarget
Using the CompositionTarget
Fun with Animation Part 1
use Dispatcher.BeginInvoke(...), you can get the right value