【问题标题】:Get current value of a double animation获取双重动画的当前值
【发布时间】:2011-06-05 17:41:00
【问题描述】:

我有一个故事板,我在其中制作一个矩形,就像 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);

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

【问题讨论】:

  • 我认为这会有所帮助,如果你展示了你将如何准确地使用改变的角度值。 HB展示了如何将 UI 元素绑定到变化的角度,我展示了如何以编程方式随时获取角度。如果这些答案都不适合您,您需要为您的问题添加更多详细信息。

标签: c# wpf animation


【解决方案1】:

你一定是做错了什么,看看这个例子:

<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

【讨论】:

  • 有没有办法在不绑定的情况下在后面的代码中获取该值?听起来不像
  • 重点是什么?如果您有一段代码,您仍然只能访问该段代码执行时的当前值,您想做什么?当然,您可以创建一个专用属性并为其设置动画,然后将变换和数字显示绑定到该属性。
  • 我只是希望我能做像 7 段显示器这样的段。我想从模拟切换到数字
  • 好吧,我正在模拟汽车仪表。它有一个长方形的针,我正在根据故事板让它上升。它工作得很好。但是,我也希望能够切换到数字以像数字时钟一样以 7 段显示 RPM。所以我需要得到这个值,这样我就可以在它上面运行一个开关。
  • 那么您的模型中应该有一个速度属性,并且显示应该以不同的方式表示该值。
【解决方案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; }
}

【讨论】:

  • 如何在不点击按钮的情况下继续获取当前值?如果我添加 var x = rt.Angle;到动画的底部,它只返回零。
  • 我有复选框来模拟齿轮所以上面的代码是在一个私有的 void checkBox2_Checked(object sender, RoutedEventArgs e) 我怎样才能继续得到它的当前值,因为它只是返回零
  • @icelated - 不确定我是否理解。如果您需要使用新 Angle 不断更新文本框,请使用 H.B. 之类的绑定。显示。如果您需要以编程方式访问它,只需在需要时访问 Angle 属性即可。
  • 由于某种原因它仍然返回零
  • 完全是 hb - 那么我怎样才能得到当前值呢?如果可能的话,我需要在后面的代码中这样做
【解决方案3】:

尽管这里有一些海报声称不是这样,但我也注意到在动画进行时很难访问动画属性的当前值。这是一个很好的解决方案,我使用 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 属性。

【讨论】:

  • 不知道为什么这被否决了。经过 3 天的搜索,这是动画类获取动画值的一个很好的起点
  • 这是从计算的动画中捕获动画值的正确解决方案。通过使用OldValue 可以计算分数/功率。
【解决方案4】:

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

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

【讨论】:

  • 如果您有新问题,请点击 按钮提出问题。如果有助于提供上下文,请包含指向此问题的链接。
  • 我一开始没有写,但这当然是一个答案。感谢您的建议,很抱歉造成混乱。
猜你喜欢
  • 2019-09-02
  • 1970-01-01
  • 2012-12-06
  • 2021-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-30
相关资源
最近更新 更多