这是我尝试的
我在画布上添加了一个形状,当您单击画布中的任意位置时,该形状将移向鼠标指针。您可以再次单击画布中的其他任何位置,形状将更改其路径以跟随新的指针位置。
xml
<Canvas x:Name="BackgroundCanvas"
Background="Transparent"
PreviewMouseDown="BackgroundCanvas_PreviewMouseDown">
<Ellipse Fill="Black"
Width="10"
Height="10"
x:Name="circ">
<Ellipse.RenderTransform>
<TranslateTransform X="-5"
Y="-5" />
</Ellipse.RenderTransform>
</Ellipse>
</Canvas>
BackgroundCanvas_PreviewMouseDown
private void BackgroundCanvas_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
double sx = (double)circ.GetValue(Canvas.LeftProperty);
double sy = (double)circ.GetValue(Canvas.TopProperty);
Point tp = e.GetPosition(BackgroundCanvas);
if (double.IsNaN(sx))
sx = 0;
if (double.IsNaN(sy))
sy = 0;
LineGeometry geom = new LineGeometry(new Point(sx, sy), tp);
Path p = new Path() { Data = geom, Stroke = Brushes.Black };
BackgroundCanvas.Children.Add(p);
var animation = new DoubleAnimationUsingPath
{
Duration = Duration.Automatic,
PathGeometry = PathGeometry.CreateFromGeometry(geom)
};
animation.Source = PathAnimationSource.X;
circ.BeginAnimation(Canvas.LeftProperty, animation);
animation.Source = PathAnimationSource.Y;
circ.BeginAnimation(Canvas.TopProperty, animation);
}
结果
我添加了显示结果的路径。试一试,看看它有多接近
编辑
我还尝试平滑动画路径,使其看起来不像直线
Point pp;
private void BackgroundCanvas_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
double sx = (double)circ.GetValue(Canvas.LeftProperty);
double sy = (double)circ.GetValue(Canvas.TopProperty);
Point tp = e.GetPosition(BackgroundCanvas);
if (double.IsNaN(sx))
sx = 0;
if (double.IsNaN(sy))
sy = 0;
Point sp = new Point(sx, sy);
StreamGeometry geom = new StreamGeometry();
using (StreamGeometryContext ctx = geom.Open())
{
ctx.BeginFigure(sp, false, false);
ctx.BezierTo(pp, tp, tp, true, false);
}
geom.Freeze();
pp = tp;
Path p = new Path() { Data = geom, Stroke = Brushes.Black };
BackgroundCanvas.Children.Add(p);
var animation = new DoubleAnimationUsingPath
{
Duration = Duration.Automatic,
PathGeometry = PathGeometry.CreateFromGeometry(geom)
};
animation.Source = PathAnimationSource.X;
circ.BeginAnimation(Canvas.LeftProperty, animation);
animation.Source = PathAnimationSource.Y;
circ.BeginAnimation(Canvas.TopProperty, animation);
}
结果
我希望这可以解决您修改正在运行的动画路径的问题(实际上不是修改,而是从触发点开始新动画),并具有融合外观的平滑度
编辑 2
我将我的方法与您的代码相结合,现在当窗口大小发生变化时,圆圈将沿着新路径到达第二个矩形。
private void Window_Loaded(object sender, RoutedEventArgs e)
{
Func<FrameworkElement, Point> centerOf = ele => ele.TransformToVisual(BackgroundCanvas).Transform(new Point(ele.Width / 2, ele.Height / 2));
Point start = centerOf(LeftRect);
Point end = centerOf(RightRect);
LineGeometry geom = new LineGeometry(start, end);
pp = end;
var animation = new DoubleAnimationUsingPath
{
Duration = TimeSpan.FromMilliseconds(totalDuration),
PathGeometry = PathGeometry.CreateFromGeometry(geom)
};
animation.Source = PathAnimationSource.X;
Circ.BeginAnimation(Canvas.LeftProperty, animation);
animation.Completed += delegate { Window_Loaded(null, null); };
animation.Source = PathAnimationSource.Y;
Circ.BeginAnimation(Canvas.TopProperty, animation);
startTime = DateTime.Now;
started = true;
}
Point pp;
DateTime startTime;
double totalDuration = 5000;
bool started;
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (!started)
return;
Func<FrameworkElement, Point> centerOf = ele => ele.TransformToVisual(BackgroundCanvas).Transform(new Point(ele.Width / 2, ele.Height / 2));
double sx = (double)Circ.GetValue(Canvas.LeftProperty);
double sy = (double)Circ.GetValue(Canvas.TopProperty);
Point tp = centerOf(RightRect);
double timeLeft = totalDuration - DateTime.Now.Subtract(startTime).TotalMilliseconds;
if (timeLeft < 1) return;
if (double.IsNaN(sx))
sx = 0;
if (double.IsNaN(sy))
sy = 0;
Point sp = new Point(sx, sy);
StreamGeometry geom = new StreamGeometry();
using (StreamGeometryContext ctx = geom.Open())
{
ctx.BeginFigure(sp, false, false);
ctx.BezierTo(pp, pp, tp, true, false);
}
geom.Freeze();
pp = tp;
var animation = new DoubleAnimationUsingPath
{
Duration = TimeSpan.FromMilliseconds(timeLeft),
PathGeometry = PathGeometry.CreateFromGeometry(geom)
};
animation.Source = PathAnimationSource.X;
Circ.BeginAnimation(Canvas.LeftProperty, animation);
animation.Completed += delegate { Window_Loaded(null, null); };
animation.Source = PathAnimationSource.Y;
Circ.BeginAnimation(Canvas.TopProperty, animation);
}
看看这是否是你要找的。当前圆形将使用其当前位置和第二个矩形来创建它的路径。如果您希望在调整窗口大小时移动圆圈,那么也许我们可能需要实现情节提要并使用 seek 方法来实现相同的目的。