获取双动画的当前值

时间:2011-06-05 17:41:01

标签: c# wpf animation

我有一个故事板,我正在制作一个矩形,像MPH汽车仪表中的针一样向上移动。所以,我让它从0变为60,我希望能够在变化时获得当前值,这样我就可以使用该值来制作数字仪表。

如何从双动画的开头到结尾获取当前值?我有这样的事情:

DoubleAnimation da = new DoubleAnimation();
da.Duration = new Duration(TimeSpan.FromSeconds(5));
da.From = 0;
da.To = 60;
RotateTransform rt = new RotateTransform();
rt.CenterX = 35;
rt.CenterY = 0;
rec3.RenderTransform = rt;
rt.BeginAnimation(RotateTransform.AngleProperty, da);

当它向上旋转矩形时,我试图获得该角度,但它只是返回零。

4 个答案:

答案 0 :(得分:3)

你必须做错事,考虑这个例子:

<Rectangle Width="100" Height="10" Fill="Red" HorizontalAlignment="Left" RenderTransformOrigin="1,0.5">
    <Rectangle.RenderTransform>
        <RotateTransform x:Name="rt" />
    </Rectangle.RenderTransform>
</Rectangle>
<TextBlock Text="{Binding ElementName=rt, Path=Angle}" />
rt.BeginAnimation(RotateTransform.AngleProperty, new DoubleAnimation(0, 60, TimeSpan.FromSeconds(1), FillBehavior.HoldEnd));

它显示的值很好。


如果您将rt.Angle分配给某个变量,该变量将在该时间点具有变换角度的值,那么它将与rt.Angle同时不会更改属性。

如果您不熟悉我在上述代码中使用的数据绑定,您可能需要查看overview

答案 1 :(得分:2)

不确定您面临的问题到底是什么,但我刚检查过,此代码会显示当前的角度:

RotateTransform rt = new RotateTransform();

private void button1_Click(object sender, RoutedEventArgs e)
{
    DoubleAnimation da = new DoubleAnimation();
    da.Duration = new Duration(TimeSpan.FromSeconds(10));
    da.From = 0;
    da.To = 60;
    rt.CenterX = 35;
    rt.CenterY = 0;
    rectangle1.RenderTransform = rt;
    rt.BeginAnimation(RotateTransform.AngleProperty, da);
}

private void button2_Click(object sender, RoutedEventArgs e)
{
    var x = rt.Angle; // x will have the value of current angle
}

[编辑]

如果您需要从另一个类访问私有rt.Angle,您可以通过以下属性公开它:

public Double CurrentAngle
{
    get { return rt.Angle; }
}

答案 2 :(得分:0)

晚上好。我有一个类似的问题,但在动画动画期间获取元素的位置。我用时间解决了这个问题。此方法基于知道动画开始后经过的时间。比方说,我们有这个元素的类代码:

Location = new Point(100, 100);

// set animations
var moveTime = 5000.0;
var function = new SineEase { EasingMode = EasingMode.EaseInOut };
var shift = new Point(1000, 700);
var locationAnimationX = new DoubleAnimation
{
    Duration = TimeSpan.FromMilliseconds(moveTime),
    To = shift .X,
    EasingFunction = function
};
var locationAnimationY = new DoubleAnimation
{
    Duration = TimeSpan.FromMilliseconds(moveTime),
    To = shift .Y,
    EasingFunction = function
};

// attach animations to this element and its properties
Storyboard.SetTarget(locationAnimationX, this);
Storyboard.SetTargetProperty(locationAnimationX, "(UIElement.RenderTransform).(CompositeTransform.TranslateX)");
Storyboard.SetTarget(locationAnimationY, this);
Storyboard.SetTargetProperty(locationAnimationY, "(UIElement.RenderTransform).(CompositeTransform.TranslateY)");

// create storyboard and start animation of move
var moveStory = new Storyboard();
moveStory.Children.Add(locationAnimationX);
moveStory.Children.Add(locationAnimationY);
moveStory.Begin();
var startTime = DateTime.Now;    

例如,我们必须在一段时间后知道当前位置。所以,让我们开始。

var elapsedTime = DateTime.Now.Subtract(startTime).TotalMilliseconds;  
var ratio = elapsedTime / moveTime;
var funcCurrentValue = function.Ease(ratio);
var currentShift = new Point(shift.X * funcCurrentValue, shift.Y * funcCurrentValue);

最后,当前位置由:

给出
var currentLocation = new Point(Location.X + currentShift.X, Location.Y + currentShift.Y);

答案 3 :(得分:0)

尽管这里有一些宣传海报,我还注意到在动画进行过程中很难访问动画属性的当前值。这是一个很好的解决方案,我已经习惯使用WPF动画在我的模型中随时间插值。

public class AnimatedDoubleValue : UIElement
{
    public event PropertyChangedEventHandler PropertyChanged;
    private void FirePropertyChanged(string name)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(name));
    }

    private double _value_cache; // this stores the current animated value!
    public double Value
    {
        get { return (double)GetValue(ValueProperty); }
        set
        {
            if (_value_cache == value)
                return;
            _value_cache = value;
            SetValue(ValueProperty, value);
            FirePropertyChanged("Value");
        }
    }

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(double), typeof(AnimatedDoubleValue), new UIPropertyMetadata(0.0, ValuePropertyChanged));

    private static void ValuePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        var self = (AnimatedDoubleValue)sender;
        var value = (double)e.NewValue;
        self.UpdateValue(value);
    }

    private void UpdateValue(double value)
    {
        _value_cache = value;
        FirePropertyChanged("Value");
    }
}

如果我理解正确,OP希望重复使用WPF动画工具进行模拟。这不是一个坏主意,因为根据经过的时间内插值并非完全无关紧要。

甚至不必将此AnimatedDoubleValue链接到WPF窗口小部件树。它可以用于获取动画值的更新。使用方式如下:

var doubleValue = new AnimatedDoubleValue();
var animation=new DoubleAnimation() { From=0, To=100, Duration=TimeSpan.FromSeconds(1) };
animation.SetValue(Storyboard.DesiredFrameRateProperty, 30);
doubleValue.BeginAnimation(AnimatedDoubleValue.ValueProperty, animation, HandoffBehavior.SnapshotAndReplace);

现在,您可以在doubleValue上收听PropertyChanged事件,也可以随时访问其Value属性。