WPF / SL动画时间缩放

时间:2012-06-04 23:21:08

标签: wpf silverlight animation

我寻找这个特别的东西,因为我认为这是非常重要和令人费解的事情,但我没有找到任何关于此事的东西。我正在考虑的是WPF和Silverlight动画中的时间缩放。

假设我们有一个持续时间为4s的DoubleAnimation并且动画从0到100的属性。它是自动反转的,或者有一个可以反转其效果的补充动画,这并不重要。假设触发此动画的事件是一个简单的MouseOver。

问题在于:我将光标悬停在元素上。该属性在4秒内从0到100。我将光标移开1秒,属性从100移动到75,然后我将鼠标移开。现在,该属性在4s内形成75到100的形式。对用户来说显而易见的是,动画运行速度慢了4倍。有没有办法缩放动画的时间?如果我希望这个动画在1秒内从75到100运行,我该怎么做?我自己想的可能是一个转换器,它将采用四个参数(绝对开始和结束,实际开始和整个时间间隔的时间跨度),然后吐出适当的时间。还有更优雅的方式吗?

我注意到动画很快时通常不会出现问题。当动画在0.2秒或0.1秒内运行时,人类并没有真正观察到速度上的差异,并且可能所有动画应尽可能快地不会使体验恶化。但请从理论上处理这个问题(因此没有代码样本)。我很好奇是否有适当的方法来缩放动画时间。

如果网上某处有我的问题的答案,请直接指示我。

帕维尔

P.S。不介意我的英语,我不是母语;)

3 个答案:

答案 0 :(得分:0)

我知道这不是您确切问题的答案,但解决此问题的一种方法是捕获MouseEnterMouseLeave,检查当前动画状态并暂停或恢复它:

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="AnimationTest.MainPage"
    Width="640" Height="480">
    <UserControl.Resources>
        <Storyboard x:Name="Rotate" AutoReverse="True">
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.Rotation)" Storyboard.TargetName="textBlock">
                <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:4" Value="100"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot" Background="White">
        <TextBlock x:Name="textBlock" Margin="197,216,200,215" TextWrapping="Wrap" Text="My Funky Text" FontSize="32" RenderTransformOrigin="0.5,0.5" MouseEnter="textBlock_MouseEnter" MouseLeave="textBlock_MouseLeave">
            <TextBlock.RenderTransform>
                <CompositeTransform/>
            </TextBlock.RenderTransform>
        </TextBlock>
    </Grid>
</UserControl>

代码:

private void textBlock_MouseEnter(object sender, MouseEventArgs e)
{
    var state = Rotate.GetCurrentState();
    if (state == ClockState.Stopped || state == ClockState.Filling) { Rotate.Begin(); } else Rotate.Resume();
}

private void textBlock_MouseLeave(object sender, MouseEventArgs e)
{
    Rotate.Pause();
}

答案 1 :(得分:0)

我做了更多的研究。似乎缩放动画时间的唯一好方法是使用MultiConverter,它接收边界值(例如前一个示例中的0和100),动画属性的当前值以及完整动画的运行时间(例如我的例子中的4s)。那么它应该计算动画的百分比(如果当前值是75,并且整个范围是0-100,则剩下动画的25%),并且返回值应该是前面提到的percantage of原始时间跨度(4s的25%是1s)。也许这不是实现目标的最优雅方式,但它似乎应该有效。

答案 2 :(得分:0)

我有同样的问题,让动画以你描述的方式线性地表现。我无法在XAML中找到使用WPF触发器的解决方案,而无需编写代码隐藏。

然后我开始使用 VisualStateManager 而不是触发器(WPF 4和Silverlight支持)。所有的动画都表现得像你期望的那样完美!

我建议使用Expression Blend 4来使用VisualStateManager,因为使用UI配置对象的各种状态只需几秒钟。