为什么我不能使用 DoubleAnimation Using Path 来为 TranslateForm.X 属性设置动画?
Why I can't use DoubleAnimationUsingPath to animate the TranslateForm.X propertry?
我在 wpf 中创建了一个自定义 Panel
,其中 children 需要在渲染后进行动画处理。我想要的每个 child 的动画是使用 bezier 曲线 平移(移动)。
我遵循 Microsoft's example 并创建了 AddAnimation
方法,我在其中添加了 Path
我希望面板的每个项目都具有动画效果。
不幸的是我得到了以下异常:
Cannot animate the 'X' property on a
'System.Windows.Media.TranslateTransform' using a
'System.Windows.Media.Animation.DoubleAnimationUsingPath'
但是我应该如何在没有 DoubleAnimationUsingPath
的情况下为 X 属性 设置动画?
方法如下:
private void AddAnimation(FrameworkElement child, Point childLocation)
{
var middlePoint = GetMiddlePoint();
var finalPoint = GetFinalPoint();
var animatedTranslateTransform = new TranslateTransform();
child.RenderTransform = animatedTranslateTransform;
child.RenderTransformOrigin = new Point(0.5, 0.5);
// Create the animation path.
PathGeometry animationPath = new PathGeometry();
PathFigure pFigure = new PathFigure();
pFigure.StartPoint = childLocation;
PolyBezierSegment pBezierSegment = new PolyBezierSegment();
pBezierSegment.Points.Add(middlePoint);
pBezierSegment.Points.Add(finalPoint);
pFigure.Segments.Add(pBezierSegment);
animationPath.Figures.Add(pFigure);
// Freeze the PathGeometry for performance benefits.
animationPath.Freeze();
// Create a DoubleAnimationUsingPath to move the
// rectangle horizontally along the path by animating
// its TranslateTransform.
DoubleAnimationUsingPath translateXAnimation =
new DoubleAnimationUsingPath();
translateXAnimation.PathGeometry = animationPath;
translateXAnimation.Duration = TimeSpan.FromSeconds(5);
// Set the Source property to X. This makes
// the animation generate horizontal offset values from
// the path information.
translateXAnimation.Source = PathAnimationSource.X;
// Set the animation to target the X property
Storyboard.SetTarget(translateXAnimation, child);
Storyboard.SetTargetProperty(translateXAnimation,
new PropertyPath("(FrameworkElement.RenderTransform).(TranslateTransform.X)"));
// Create a DoubleAnimationUsingPath to move the
// rectangle vertically along the path by animating
// its TranslateTransform.
DoubleAnimationUsingPath translateYAnimation =
new DoubleAnimationUsingPath();
translateYAnimation.PathGeometry = animationPath;
translateYAnimation.Duration = TimeSpan.FromSeconds(5);
// Set the Source property to Y. This makes
// the animation generate vertical offset values from
// the path information.
translateYAnimation.Source = PathAnimationSource.Y;
// Set the animation to target the Y property
// of the TranslateTransform named "AnimatedTranslateTransform".
Storyboard.SetTarget(translateYAnimation, child);
Storyboard.SetTargetProperty(translateYAnimation,
new PropertyPath("(FrameworkElement.RenderTransform).(TranslateTransform.Y)"));
// Create a Storyboard to contain and apply the animations.
Storyboard pathAnimationStoryboard = new Storyboard();
pathAnimationStoryboard.RepeatBehavior = RepeatBehavior.Forever;
pathAnimationStoryboard.Children.Add(translateXAnimation);
pathAnimationStoryboard.Children.Add(translateYAnimation);
// Start the animations when the rectangle is loaded.
child.Loaded += (sender, args) =>
{
Debug.WriteLine($"Child {child} loaded.");
pathAnimationStoryboard.Begin(child);
};
}
看看AnimationException的InnerException
属性。
异常的原因是两个点对于PolyBezierSegment
是不够的,因为它需要两个控制点和一个终点,因此每条曲线三个点。
改用PolyQuadraticBezierSegment
:
var pBezierSegment = new PolyQuadraticBezierSegment();
pBezierSegment.Points.Add(middlePoint);
pBezierSegment.Points.Add(finalPoint);
或者只是一个 QuadraticBezierSegment
:
var bezierSegment = new QuadraticBezierSegment();
bezierSegment.Point1 = middlePoint;
bezierSegment.Point2 = finalPoint;
对于它应该做的事情来说,代码似乎也太复杂了。您可以将 Storyboard 替换为两个 DoubleAnimationUsingPath
子级,其中一个 MatrixAnimationUsingPath
为 MatrixTransform
:
的 Matrix
属性 设置动画
var animation = new MatrixAnimationUsingPath
{
PathGeometry = animationPath,
Duration = TimeSpan.FromSeconds(5)
};
var transform = new MatrixTransform();
child.RenderTransform = transform;
child.Loaded += (s, e) =>
transform.BeginAnimation(MatrixTransform.MatrixProperty, animation);
我在 wpf 中创建了一个自定义 Panel
,其中 children 需要在渲染后进行动画处理。我想要的每个 child 的动画是使用 bezier 曲线 平移(移动)。
我遵循 Microsoft's example 并创建了 AddAnimation
方法,我在其中添加了 Path
我希望面板的每个项目都具有动画效果。
不幸的是我得到了以下异常:
Cannot animate the 'X' property on a 'System.Windows.Media.TranslateTransform' using a 'System.Windows.Media.Animation.DoubleAnimationUsingPath'
但是我应该如何在没有 DoubleAnimationUsingPath
的情况下为 X 属性 设置动画?
方法如下:
private void AddAnimation(FrameworkElement child, Point childLocation)
{
var middlePoint = GetMiddlePoint();
var finalPoint = GetFinalPoint();
var animatedTranslateTransform = new TranslateTransform();
child.RenderTransform = animatedTranslateTransform;
child.RenderTransformOrigin = new Point(0.5, 0.5);
// Create the animation path.
PathGeometry animationPath = new PathGeometry();
PathFigure pFigure = new PathFigure();
pFigure.StartPoint = childLocation;
PolyBezierSegment pBezierSegment = new PolyBezierSegment();
pBezierSegment.Points.Add(middlePoint);
pBezierSegment.Points.Add(finalPoint);
pFigure.Segments.Add(pBezierSegment);
animationPath.Figures.Add(pFigure);
// Freeze the PathGeometry for performance benefits.
animationPath.Freeze();
// Create a DoubleAnimationUsingPath to move the
// rectangle horizontally along the path by animating
// its TranslateTransform.
DoubleAnimationUsingPath translateXAnimation =
new DoubleAnimationUsingPath();
translateXAnimation.PathGeometry = animationPath;
translateXAnimation.Duration = TimeSpan.FromSeconds(5);
// Set the Source property to X. This makes
// the animation generate horizontal offset values from
// the path information.
translateXAnimation.Source = PathAnimationSource.X;
// Set the animation to target the X property
Storyboard.SetTarget(translateXAnimation, child);
Storyboard.SetTargetProperty(translateXAnimation,
new PropertyPath("(FrameworkElement.RenderTransform).(TranslateTransform.X)"));
// Create a DoubleAnimationUsingPath to move the
// rectangle vertically along the path by animating
// its TranslateTransform.
DoubleAnimationUsingPath translateYAnimation =
new DoubleAnimationUsingPath();
translateYAnimation.PathGeometry = animationPath;
translateYAnimation.Duration = TimeSpan.FromSeconds(5);
// Set the Source property to Y. This makes
// the animation generate vertical offset values from
// the path information.
translateYAnimation.Source = PathAnimationSource.Y;
// Set the animation to target the Y property
// of the TranslateTransform named "AnimatedTranslateTransform".
Storyboard.SetTarget(translateYAnimation, child);
Storyboard.SetTargetProperty(translateYAnimation,
new PropertyPath("(FrameworkElement.RenderTransform).(TranslateTransform.Y)"));
// Create a Storyboard to contain and apply the animations.
Storyboard pathAnimationStoryboard = new Storyboard();
pathAnimationStoryboard.RepeatBehavior = RepeatBehavior.Forever;
pathAnimationStoryboard.Children.Add(translateXAnimation);
pathAnimationStoryboard.Children.Add(translateYAnimation);
// Start the animations when the rectangle is loaded.
child.Loaded += (sender, args) =>
{
Debug.WriteLine($"Child {child} loaded.");
pathAnimationStoryboard.Begin(child);
};
}
看看AnimationException的InnerException
属性。
异常的原因是两个点对于PolyBezierSegment
是不够的,因为它需要两个控制点和一个终点,因此每条曲线三个点。
改用PolyQuadraticBezierSegment
:
var pBezierSegment = new PolyQuadraticBezierSegment();
pBezierSegment.Points.Add(middlePoint);
pBezierSegment.Points.Add(finalPoint);
或者只是一个 QuadraticBezierSegment
:
var bezierSegment = new QuadraticBezierSegment();
bezierSegment.Point1 = middlePoint;
bezierSegment.Point2 = finalPoint;
对于它应该做的事情来说,代码似乎也太复杂了。您可以将 Storyboard 替换为两个 DoubleAnimationUsingPath
子级,其中一个 MatrixAnimationUsingPath
为 MatrixTransform
:
Matrix
属性 设置动画
var animation = new MatrixAnimationUsingPath
{
PathGeometry = animationPath,
Duration = TimeSpan.FromSeconds(5)
};
var transform = new MatrixTransform();
child.RenderTransform = transform;
child.Loaded += (s, e) =>
transform.BeginAnimation(MatrixTransform.MatrixProperty, animation);