是否可以改变路径,例如动画已在进行中PathGeometry
的{{1}}属性?如果是这样,怎么样?
我的一些代码:
XAML:
DoubleAnimationUsingPath
代码隐藏:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Canvas x:Name="BackgroundCanvas"
Background="Transparent"
Grid.ColumnSpan="2">
<Ellipse Fill="Black" Width="10" Height="10" x:Name="Circ">
<Ellipse.RenderTransform>
<TranslateTransform X="-5" Y="-5" />
</Ellipse.RenderTransform>
</Ellipse>
</Canvas>
<Rectangle x:Name="LeftRect" Width="100" Height="100" Grid.Column="0" Fill="#80002EE2" />
<Rectangle x:Name="RightRect" Width="100" Height="100" Grid.Column="1" Fill="#8000B70A" />
</Grid>
</Window>
这应该在两个矩形的中心之间移动一个10x10的圆圈。我想更改动画,如果尚未完成并且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);
var animation = new DoubleAnimationUsingPath
{
Duration = Duration.Automatic,
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);
}
触发,那么当窗口例如是动画时动画实际上在矩形的中心结束。调整大小。
答案 0 :(得分:1)
这是我的尝试
我在画布上添加了一个形状,当您单击画布中的任何位置时,形状将朝向鼠标指针移动。您可以在画布中再次单击其他任何位置,并且形状将更改其路径以跟随新指针位置。
XAML
<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);
}
看看这是否是你要找的。当前圈子将使用其当前位置和第二个矩形来创建它的路径。如果您希望在窗口调整大小时移动圆圈,那么我们可能需要实现故事板并使用搜索方法来实现相同的目标。