3

I need to scale an EllipseGeometry in C# with ScaleTransform, but it doesn't works. Here's the code:

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();

The storyboard_Completed event is triggered but there is no animation on the EllipseGeometry.

Where is the problem?

I can animate the EllipseGeometry only in this way:

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);

I need to put this DoubleAnimation in a Storyboard, but I don't know how.

Thanks.

Andrea
  • 125
  • 1
  • 1
  • 7

1 Answers1

2

It works if you use the Image control (instead of the Geometry) as target element:

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();

However, the most simply way may be to name the ScaleTransform

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

and run the animations like this:

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);

EDIT: In order to animate the RadiusX and RadiusY properties by means of a Storyboard, you could write this:

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
  • 123,504
  • 12
  • 155
  • 268
  • Thanks Clemens, it works using the image control as target. How can I change the render transform origin? I tried with `` but it doesn't works. So I changed the CenterX/Y ``, in this way the animation ends correctly (in the middle of the 400x300 image) but starts in the top left of the image (and not in the middle). How can I change the render transform origin (possibly using 0..1 values)? Thanks for your help. – Andrea Dec 16 '14 at 10:30
  • It's not clear what exactly you want to achieve. First you don't animate a RenderTransform, but the Transform of a Clip geometry. If you want to keep the Clip geometry's Center, you should not animate the geometry's Transform, but instead animate its RadiusX and RadiusY (as you already did). – Clemens Dec 16 '14 at 10:49
  • Yes, I want to keep clip geometry's center. With `rockClip.BeginAnimation(EllipseGeometry.RadiusXProperty, scale)` it works fine but I don't know how to put this animation inside a Storyboard. How can I achieve this? Thanks! – Andrea Dec 16 '14 at 11:02
  • I put the ScaleTransform in a TransformGroup: `` but I don't know how to set the target property. I tried this: `Storyboard.SetTargetProperty(scaleX, new PropertyPath("(Clip.Transform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"))` but it doesn't works. Where is the problem? – Andrea Dec 17 '14 at 08:47
  • Is it possible to animate the Clip opacity? I tried with `Storyboard.SetTarget(fade, target); Storyboard.SetTargetProperty(fade, new PropertyPath("Clip.Opacity"));` (where fade is the DoubleAnimation and target is the image) but it doesn't works. – Andrea Dec 18 '14 at 17:56
  • Clip is a Geometry, which has no Opacity property. Please stop asking questions in comments. Ask another regular question on StackOverflow. – Clemens Dec 18 '14 at 18:19