This is my control:
I am getting this to rotate, with this code:
Global variable, bool IsTriangleAnimRunning = false;
And the rest of the code:
public void AnimateTriangle()
{
var rotation = (int)((100 / 100d) * 45 * 1); // Max 45 degree rotation
var duration = (int)(750 * (100 / 100d)); // Max 750ms rotation
while (IsTriangleAnimRunning != false)
{
MyTriangle.Dispatcher.BeginInvoke(
(Action)(() =>
{
var anim = new DoubleAnimation
{
To = rotation,
Duration = new Duration(TimeSpan.FromMilliseconds(duration)),
AutoReverse = true
};
var rt = new RotateTransform();
MyTriangle.RenderTransform = rt;
rt.BeginAnimation(RotateTransform.AngleProperty, anim);
}), DispatcherPriority.ContextIdle);
Thread.Sleep(duration * 2);
}
}
The event handler for the button, that triggers the animation:
public void HandleTriangleEvents(object sender, RoutedEventArgs a)
{
Thread t_triagle = new Thread(new ThreadStart(this.AnimateTriangle));
Button btn = (Button)sender;
if (btn.Name == "btnStartTriangleAnim")
{
IsTriangleAnimRunning = true;
btnStartTriangleAnim.IsEnabled = false;
t_triagle.Start();
}
else
{
IsTriangleAnimRunning = false;
btnStartTriangleAnim.IsEnabled = true;
t_triagle.Abort();
}
}
It behaves in an unatural way, because, when I stop it, it resets to its regular position. I am assuming it, does this for some reason, that I cannot understand. Also, for some reason, this code does not get it to run constantly, but only once.
Desired functionality: If, I hit start button, run the thread and keep on rotating, while thread is running. If, I hit, stop, then stop in the current state of rotation. If I hit start, run the thread again and keep rotating back and forth.
--
Tested with Task Async, runs slower and doesn't repeat.
private async Task AnimateTriangle()
{
double rotation = 45d;
double duration = 100d;
var anim = new DoubleAnimation
{
To = rotation,
Duration = TimeSpan.FromMilliseconds(duration),
AutoReverse = true,
RepeatBehavior = RepeatBehavior.Forever
};
var transform = MyTriangle.RenderTransform as RotateTransform;
await Task.Factory.StartNew(() =>
{
while (IsTriangleAnimRunning != false)
{
MyTriangle.Dispatcher.Invoke(() =>
{
if (transform == null)
{
transform = new RotateTransform();
MyTriangle.RenderTransform = transform;
}
transform.BeginAnimation(RotateTransform.AngleProperty, anim);
}, DispatcherPriority.ContextIdle);
if (IsTriangleAnimRunning == false)
{
MyTriangle.Dispatcher.Invoke(() =>
{
if (MyTriangle.RenderTransform is RotateTransform)
{
var angle = transform.Angle; // current animated value
transform.Angle = angle;
transform.BeginAnimation(RotateTransform.AngleProperty, null);
}
}, DispatcherPriority.ContextIdle);
}
}
});
}
CodePudding user response:
You do not need to start a thread.
Start an animation that runs forever, until you reset it by setting a null
animation.
Before you reset it, explicitly set the value of the target property to the current animated value.
Reuse the existing RotateTransform instead of re-assigning one each time you start the animation.
private void StartButtonClick(object sender, RoutedEventArgs e)
{
double rotation = 45d;
double duration = 750d;
var anim = new DoubleAnimation
{
To = rotation,
Duration = TimeSpan.FromMilliseconds(duration),
AutoReverse = true,
RepeatBehavior = RepeatBehavior.Forever
};
var transform = MyTriangle.RenderTransform as RotateTransform;
if (transform == null)
{
transform = new RotateTransform();
MyTriangle.RenderTransform = transform;
}
transform.Angle = 0d;
transform.BeginAnimation(RotateTransform.AngleProperty, anim);
}
private void StopButtonClick(object sender, RoutedEventArgs e)
{
if (MyTriangle.RenderTransform is RotateTransform transform)
{
var angle = transform.Angle; // current animated value
transform.Angle = angle;
transform.BeginAnimation(RotateTransform.AngleProperty, null);
}
}