我想沿着正弦半径的圆制作一个对象的动画,其中幅度和频率可以改变。
我已经成功创建了正弦圆,以及一个遵循其初始路径的对象。此外,当我改变圆的振幅时,它会发生变化。但是,该对象的路径不会更新,我不确定如何使其更新。 XAML:
<Grid>
<Path HorizontalAlignment="Center"
VerticalAlignment="Center"
Stretch="Uniform" x:Name="MainPath" SizeChanged="MainPath_SizeChanged" Fill="Green" Stroke="Black">
<Path.Data>
<PathGeometry x:Name="ScaledAnimationPath">
<PathGeometry.Figures>
<PathFigure StartPoint="{Binding StartPoint}">
<PolyLineSegment Points="{Binding Points}"/>
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
<Ellipse Width="30" Height="30" Fill="Blue">
<Ellipse.RenderTransform>
<TranslateTransform x:Name="AnimatedTranslateTransform" />
</Ellipse.RenderTransform>
<Ellipse.Triggers>
<EventTrigger RoutedEvent="Path.Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<!-- Animates the rectangle horizotally along the path. -->
<DoubleAnimationUsingPath
Storyboard.TargetName="AnimatedTranslateTransform"
Storyboard.TargetProperty="X"
PathGeometry="{Binding ElementName=ScaledAnimationPath}"
Source="X"
Duration="0:0:3" />
<!-- Animates the rectangle vertically along the path. -->
<DoubleAnimationUsingPath
Storyboard.TargetName="AnimatedTranslateTransform"
Storyboard.TargetProperty="Y"
PathGeometry="{Binding ElementName=ScaledAnimationPath}"
Source="Y"
Duration="0:0:3" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Ellipse.Triggers>
</Ellipse>
(SizeChanged 事件调用 VM 中的一个方法 - 完成以根据元素的大小缩放 PolyLine 的点)
视图模型:
public class ParticlePathVM : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
PointCollection points;
public PointCollection Points { get => points; set { if (points != value) { points = value; RaisePropertyChanged(nameof(Points)); } } }
Point startPoint;
public Point StartPoint { get => startPoint; set { if (startPoint != value) { startPoint = value; RaisePropertyChanged(nameof(StartPoint)); } } }
double amplitude;
public double Amplitude { get => amplitude; set { if (amplitude != value) { amplitude = value; RaisePropertyChanged(nameof(Amplitude)); UpdatePoints(); } } }
public double AmplitudeMax { get; } = 10;
public double Radius;
public double Frequency;
System.Threading.SynchronizationContext _context;
public ParticlePathVM()
{
_context = System.Threading.SynchronizationContext.Current;
Radius = 266 - AmplitudeMax;
StartPoint = new Point(Radius, 0);
Amplitude = 5;
Frequency = 10;
UpdatePoints();
}
public void UpdateBounds(Size s)
{
if (s.Width > 1)
{
Radius = (s.Width / 2) - AmplitudeMax;
Debug.WriteLine(string.Format("{0} -> {1}", s, Radius));
StartPoint = new Point(Radius, 0);
UpdatePoints();
}
}
void UpdatePoints()
{
var points = new List<Point>();
for (float i = 0; i <= 360; i += 0.5F)
{
points.Add(GetCartesian(i));
}
_context.Post(o =>
{
Points = new PointCollection(points);
}, null);
}
public Point GetCartesian(double angle)
{
var rad = angle * (Math.PI / 180.0);
var r = Radius + Amplitude * Math.Sin(2 * Frequency * rad);
return new Point(r * Math.Cos(rad), r * Math.Sin(rad));
}
}
再次 - 当我从 VM 外部更改幅度时,圆的形状确实发生了变化,但移动物体不会改变其路径。看来我需要一种方法来更新故事板,但我不知道该怎么做。有什么建议吗?
由于我在后面的代码中定义了路径,因此我能够简单地将对象上 TranslateTransform 的位置绑定到 VM,并使用路径的代码表示来移动对象。