An alternative to DoubleAnimationUsingPath
would be a custom animation that provides sinus values. It has an Amplitude
property that controls the amplitude and by its sign also the direction of the sinus animation. There is also a StartAngle
property that controls at which angle the animation starts.
public class SinusAnimation : DoubleAnimationBase
{
public static readonly DependencyProperty AmplitudeProperty =
DependencyProperty.Register(
"Amplitude", typeof(double), typeof(SinusAnimation));
public static readonly DependencyProperty StartAngleProperty =
DependencyProperty.Register(
"StartAngle", typeof(double), typeof(SinusAnimation));
public double Amplitude
{
get { return (double)GetValue(AmplitudeProperty); }
set { SetValue(AmplitudeProperty, value); }
}
public double StartAngle
{
get { return (double)GetValue(StartAngleProperty); }
set { SetValue(StartAngleProperty, value); }
}
protected override double GetCurrentValueCore(double defaultOriginValue,
double defaultDestinationValue, AnimationClock animationClock)
{
var result = defaultOriginValue;
var p = animationClock.CurrentProgress;
if (p.HasValue)
{
result = Amplitude * Math.Sin(
p.Value * Math.PI * 2d + StartAngle * Math.PI / 180d);
}
return result;
}
protected override Freezable CreateInstanceCore()
{
return new SinusAnimation();
}
}
This is some simple XAML that creates circular motion of a small blue circle. By different Amplitudes it might as well create elliptical trajectories, and by different StartAngles also all kinds of Lissajous figures.
<Canvas Margin="200">
<Path Fill="Blue">
<Path.Data>
<EllipseGeometry RadiusX="10" RadiusY="10"/>
</Path.Data>
<Path.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard Duration="0:0:2" RepeatBehavior="Forever">
<local:SinusAnimation
Storyboard.TargetProperty="(Canvas.Left)"
Amplitude="100"
Duration="0:0:2" RepeatBehavior="Forever"/>
<local:SinusAnimation
Storyboard.TargetProperty="(Canvas.Top)"
Amplitude="100" StartAngle="90"
Duration="0:0:2" RepeatBehavior="Forever"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Path.Triggers>
</Path>
</Canvas>
Edit: In order to reverse a DoubleAnmationUsingPath
you can simply set the Transform property of the used PathGeometry to an appropriate ScaleTransform:
<PathGeometry x:Key="path">
<PathGeometry.Transform>
<ScaleTransform ScaleX="-1"/>
</PathGeometry.Transform>
...
</PathGeometry>