Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Instead of creating a new ScaleTransform for each change, use the same one and keep applying new animations. If you don't specify a <code>From</code> property for the animation, it will start with the current value and do a smooth animation. </p> <p>To avoid the location skip, remember the position of the mouse within the ellipse instead of always centering it. That way you won't need to worry about recentering it. (You can call BeginAnimation with a null timeline to stop the current animation, but then you'll just get a jump on the first MouseMove.) </p> <p>In XAML: </p> <pre><code>&lt;Ellipse Name="ellipse" Width="100" Height="100" Stroke="Black" StrokeThickness="3" Fill="GreenYellow"&gt; &lt;Ellipse.RenderTransform&gt; &lt;ScaleTransform x:Name="scale" CenterX="50" CenterY="50"/&gt; &lt;/Ellipse.RenderTransform&gt; &lt;/Ellipse&gt; </code></pre> <p>In code: </p> <pre><code>private Point offsetInEllipse; void ellipse_MouseDown(object sender, MouseButtonEventArgs e) { if (e.LeftButton != MouseButtonState.Pressed) return; ellipse.CaptureMouse(); offsetInEllipse = e.GetPosition(ellipse); var scaleAnimate = new DoubleAnimation(1.25, new Duration(TimeSpan.FromSeconds(1))); scale.BeginAnimation(ScaleTransform.ScaleXProperty, scaleAnimate); scale.BeginAnimation(ScaleTransform.ScaleYProperty, scaleAnimate); } void ellipse_MouseMove(object sender, MouseEventArgs e) { if (e.LeftButton != MouseButtonState.Pressed || !ellipse.IsMouseCaptured) return; var pos = e.GetPosition(canvas); Canvas.SetLeft(ellipse, pos.X - offsetInEllipse.X); Canvas.SetTop(ellipse, pos.Y - offsetInEllipse.Y); } void ellipse_MouseUp(object sender, MouseButtonEventArgs e) { if (!ellipse.IsMouseCaptured) return; ellipse.ReleaseMouseCapture(); var scaleAnimate = new DoubleAnimation(1, new Duration(TimeSpan.FromSeconds(1))); scale.BeginAnimation(ScaleTransform.ScaleXProperty, scaleAnimate); scale.BeginAnimation(ScaleTransform.ScaleYProperty, scaleAnimate); } </code></pre> <hr> <blockquote> <p>how do I return <code>Canvas.SetLeft</code> to normal operation after having an animation on the <code>Canvas.LeftProperty</code>?</p> </blockquote> <p>One way is to set the <a href="http://msdn.microsoft.com/en-us/library/system.windows.media.animation.fillbehavior.aspx" rel="nofollow">FillBehavior</a> to Stop: </p> <pre><code>ellipse.BeginAnimation(Canvas.LeftProperty, new DoubleAnimation( pos.X - ellipse.Width * 0.5, new Duration(TimeSpan.FromSeconds(1)), FillBehavior.Stop)); Canvas.SetLeft(ellipse, pos.X - ellipse.Width * 0.5); </code></pre> <p>That will cause the property to go back to its un-animated value after the animation ends. If you set the value after you start the animation then the un-animated value will just be the final value. </p> <p>Another way is to clear the animation when you're done: </p> <pre><code>ellipse.BeginAnimation(Canvas.LeftProperty, null); </code></pre> <p>Either of those will still cause it to jump when you drag, though. You could have the drag start a new animation every time, but that will make the dragging feel very laggy. Maybe you want to handle the dragging using Canvas.Left, but handle the smooth centering using an animated TranslateTransform? </p> <p>XAML: </p> <pre><code>&lt;Ellipse.RenderTransform&gt; &lt;TransformGroup&gt; &lt;ScaleTransform x:Name="scale" CenterX="50" CenterY="50"/&gt; &lt;TranslateTransform x:Name="translate"/&gt; &lt;/TransformGroup&gt; &lt;/Ellipse.RenderTransform&gt; </code></pre> <p>Code: </p> <pre><code>void ellipse_MouseDown(object sender, MouseButtonEventArgs e) { if (e.LeftButton != MouseButtonState.Pressed) return; ellipse.CaptureMouse(); var scaleAnimate = new DoubleAnimation(1.25, new Duration(TimeSpan.FromSeconds(1))); scale.BeginAnimation(ScaleTransform.ScaleXProperty, scaleAnimate); scale.BeginAnimation(ScaleTransform.ScaleYProperty, scaleAnimate); // We are going to move the center of the ellipse to the mouse // location immediately, so start the animation with a shift to // get it back to the current center and end the animation at 0. var offsetInEllipse = e.GetPosition(ellipse); translate.BeginAnimation(TranslateTransform.XProperty, new DoubleAnimation(ellipse.Width / 2 - offsetInEllipse.X, 0, new Duration(TimeSpan.FromSeconds(1)))); translate.BeginAnimation(TranslateTransform.YProperty, new DoubleAnimation(ellipse.Height / 2 - offsetInEllipse.Y, 0, new Duration(TimeSpan.FromSeconds(1)))); MoveEllipse(e); } void ellipse_MouseMove(object sender, MouseEventArgs e) { if (e.LeftButton != MouseButtonState.Pressed || !ellipse.IsMouseCaptured) return; MoveEllipse(e); } private void MoveEllipse(MouseEventArgs e) { var pos = e.GetPosition(canvas); Canvas.SetLeft(ellipse, pos.X - ellipse.Width / 2); Canvas.SetTop(ellipse, pos.Y - ellipse.Height / 2); } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload