Вместо создания нового ScaleTransform для каждого изменения, используйте тот же и продолжайте применять новые анимации. Если вы не укажете свойство From
для анимации, оно начнется с текущего значения и выполнит плавную анимацию.
Чтобы избежать пропуска местоположения, запомните положение мыши внутри эллипса, а не всегда центрируйте его. Таким образом, вам не нужно беспокоиться о повторном центрировании. (Вы можете вызвать BeginAnimation с нулевой шкалой времени, чтобы остановить текущую анимацию, но тогда вы просто получите прыжок при первом MouseMove.)
В XAML:
<Ellipse Name="ellipse" Width="100" Height="100"
Stroke="Black" StrokeThickness="3" Fill="GreenYellow">
<Ellipse.RenderTransform>
<ScaleTransform x:Name="scale" CenterX="50" CenterY="50"/>
</Ellipse.RenderTransform>
</Ellipse>
В коде:
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);
}
как мне вернуть Canvas.SetLeft
в
нормальная работа после того, как
анимация на Canvas.LeftProperty
?
Один из способов - установить FillBehavior на Stop:
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);
Это приведет к тому, что свойство вернется к своему неанимированному значению после окончания анимации. Если вы установите значение после запуска анимации, то неанимированное значение будет просто конечным значением.
Другой способ - очистить анимацию, когда вы закончите:
ellipse.BeginAnimation(Canvas.LeftProperty, null);
Любой из них все равно заставит его прыгать при перетаскивании. Вы можете каждый раз запускать анимацию с помощью перетаскивания, но при этом перетаскивание будет казаться очень медленным. Может быть, вы хотите обрабатывать перетаскивание с помощью Canvas.Left, но обрабатывать плавное центрирование с помощью анимированного TranslateTransform?
XAML:
<Ellipse.RenderTransform>
<TransformGroup>
<ScaleTransform x:Name="scale" CenterX="50" CenterY="50"/>
<TranslateTransform x:Name="translate"/>
</TransformGroup>
</Ellipse.RenderTransform>
код:
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);
}