【问题标题】:WPF - EllipseGeometry animation in C# using a StoryboardWPF - 使用情节提要的 C# 中的 EllipseGeometry 动画
【发布时间】:2015-02-14 13:22:10
【问题描述】:

我需要在 C# 中使用 ScaleTransform 缩放 EllipseGeometry,但它不起作用。 代码如下:

XAML:

<Image x:Name="rock" Stretch="None">
    <Image.Clip>
        <EllipseGeometry x:Name="rockClip" RadiusX="100" RadiusY="100" Center="200,150">
            <EllipseGeometry.Transform>
                    <ScaleTransform/>
            </EllipseGeometry.Transform>
        </EllipseGeometry>
    </Image.Clip>
</Image>

C#:

DoubleAnimation scaleX = new DoubleAnimation();
scaleX.BeginTime = TimeSpan.FromMilliseconds(fromMills);
scaleX.Duration = new Duration(TimeSpan.FromMilliseconds(2000));
scaleX.From = 0.0;
scaleX.To = 1.0;
scaleX.SetValue(Storyboard.TargetProperty, rockClip);
scaleX.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("(EllipseGeometry.Transform).(ScaleTransform.ScaleX)"));

DoubleAnimation scaleY = new DoubleAnimation();
scaleY.BeginTime = TimeSpan.FromMilliseconds(fromMills);
scaleY.Duration = new Duration(TimeSpan.FromMilliseconds(2000));
scaleY.From = 0.0;
scaleY.To = 1.0;
scaleY.SetValue(Storyboard.TargetProperty, rockClip);
scaleY.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("(EllipseGeometry.Transform).(ScaleTransform.ScaleY)"));

Storyboard storyboard = new Storyboard();
storyboard.Children.Add(scaleX);
storyboard.Children.Add(scaleY);
storyboard.Completed += storyboard_Completed;
animation.Begin();

storyboard_Completed 事件被触发,但 EllipseGeometry 上没有动画。

问题出在哪里?

我只能通过这种方式为 EllipseGeometry 设置动画:

DoubleAnimation scale = new DoubleAnimation();
scale.From = 0;
scale.To = 40;
scale.Duration = new Duration(TimeSpan.FromMilliseconds(5000));
rockClip.BeginAnimation(EllipseGeometry.RadiusXProperty, scale);
rockClip.BeginAnimation(EllipseGeometry.RadiusYProperty, scale);

我需要把这个 DoubleAnimation 放到 Storyboard 中,但我不知道怎么做。

谢谢。

【问题讨论】:

    标签: c# wpf storyboard scaletransform wpf-animation


    【解决方案1】:

    如果您使用 Image 控件(而不是 Geometry)作为目标元素,它会起作用:

    var scaleX = new DoubleAnimation();
    scaleX.BeginTime = TimeSpan.FromMilliseconds(fromMills);
    scaleX.Duration = TimeSpan.FromSeconds(2);
    scaleX.From = 0.0;
    scaleX.To = 1.0;
    Storyboard.SetTarget(scaleX, rock);
    Storyboard.SetTargetProperty(scaleX, new PropertyPath("Clip.Transform.ScaleX"));
    
    var scaleY = new DoubleAnimation();
    scaleY.BeginTime = TimeSpan.FromMilliseconds(fromMills);
    scaleY.Duration = TimeSpan.FromSeconds(2);
    scaleY.From = 0.0;
    scaleY.To = 1.0;
    Storyboard.SetTarget(scaleY, rock);
    Storyboard.SetTargetProperty(scaleY, new PropertyPath("Clip.Transform.ScaleY"));
    
    var storyboard = new Storyboard();
    storyboard.Children.Add(scaleX);
    storyboard.Children.Add(scaleY);
    storyboard.Begin();
    

    然而,最简单的方法可能是命名 ScaleTransform

    <EllipseGeometry.Transform>
        <ScaleTransform x:Name="scale"/>
    </EllipseGeometry.Transform>
    

    然后像这样运行动画:

    var scaleAnimation = new DoubleAnimation
    {
        BeginTime = TimeSpan.FromMilliseconds(fromMills),
        Duration = TimeSpan.FromSeconds(2),
        From = 0.0,
        To = 1.0
    };
    
    scale.BeginAnimation(ScaleTransform.ScaleXProperty, scaleAnimation);
    scale.BeginAnimation(ScaleTransform.ScaleYProperty, scaleAnimation);
    

    编辑:为了通过情节提要为 RadiusXRadiusY 属性设置动画,您可以这样写:

    var radiusXAnimation = new DoubleAnimation();
    radiusXAnimation.BeginTime = TimeSpan.FromMilliseconds(fromMills);
    radiusXAnimation.Duration = TimeSpan.FromSeconds(2);
    radiusXAnimation.From = 0;
    radiusXAnimation.To = 100;
    Storyboard.SetTarget(radiusXAnimation, rock);
    Storyboard.SetTargetProperty(radiusXAnimation, new PropertyPath("Clip.RadiusX"));
    
    var radiusYAnimation = new DoubleAnimation();
    radiusYAnimation.BeginTime = TimeSpan.FromMilliseconds(fromMills);
    radiusYAnimation.Duration = TimeSpan.FromSeconds(2);
    radiusYAnimation.From = 0;
    radiusYAnimation.To = 100;
    Storyboard.SetTarget(radiusYAnimation, rock);
    Storyboard.SetTargetProperty(radiusYAnimation, new PropertyPath("Clip.RadiusY"));
    
    var storyboard = new Storyboard();
    storyboard.Children.Add(radiusXAnimation);
    storyboard.Children.Add(radiusYAnimation);
    storyboard.Begin();
    

    【讨论】:

    • 感谢 Clemens,它使用图像控件作为目标。如何更改渲染变换原点?我尝试使用&lt;Image x:Name="rock" Stretch="None" RenderTransformOrigin="0.5, 0.5"&gt;,但它不起作用。所以我改变了CenterX/Y &lt;ScaleTransform CenterX="200" CenterY="150"/&gt;,这样动画正确结束(在400x300图像的中间)但从图像的左上角开始(而不是在中间)。如何更改渲染变换原点(可能使用 0..1 值)?感谢您的帮助。
    • 不清楚你到底想要达到什么。首先,您不是为 RenderTransform 设置动画,而是为 Clip 几何体的 Transform 设置动画。如果要保留 Clip 几何体的 Center,则不应为几何体的 Transform 设置动画,而是为其 RadiusX 和 RadiusY 设置动画(就像您已经做过的那样)。
    • 是的,我想保留剪辑几何的中心。使用rockClip.BeginAnimation(EllipseGeometry.RadiusXProperty, scale) 可以正常工作,但我不知道如何将此动画放入情节提要中。我怎样才能做到这一点?谢谢!
    • 我将 ScaleTransform 放在了 TransformGroup 中:&lt;EllipseGeometry.Transform&gt;&lt;TransformGroup&gt;&lt;ScaleTransform CenterX="200" CenterY="150"/&gt;&lt;/TransformGroup&gt;&lt;/EllipseGeometry.Transform&gt; 但我不知道如何设置目标属性。我试过这个:Storyboard.SetTargetProperty(scaleX, new PropertyPath("(Clip.Transform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)")) 但它不起作用。问题出在哪里?
    • 是否可以为剪辑不透明度设置动画?我试过Storyboard.SetTarget(fade, target); Storyboard.SetTargetProperty(fade, new PropertyPath("Clip.Opacity"));(其中fade是DoubleAnimation,目标是图像)但它不起作用。
    猜你喜欢
    • 1970-01-01
    • 2011-01-12
    • 1970-01-01
    • 2014-09-12
    • 2017-12-17
    • 1970-01-01
    • 2019-09-12
    • 2020-11-30
    相关资源
    最近更新 更多