XAML 心跳动画 - 如何确保心跳至少两次

si6*_*618 2 wpf xaml mvvm-light

问候,

我想直观地显示后台进程何时工作。此过程定期发生(例如每 30 秒),可能需要 10 毫秒或 1000 毫秒以上才能完成。我正在使用 MVVM-Light 框架,因此创建了一个数据触发器,连接到淡入和淡出的心脏图像上的视图模型属性。

当该过程需要一秒或更长的时间时,我的业余动画技术正在发挥作用,但我也希望它在该过程需要很短的时间(<100ms)时完成完整的心跳(2次重复),否则动画也会结束很快,您无法(从视觉上)看出该过程正在运行。

问题是心脏应该在整个过程中保持跳动,所以我不能只将重复行为设置为 2。XAML 解决方案是首选,但如果需要一些后面的代码,我不会畏缩:)

<Image 
    Height="60" Width="60" Margin="0,6,6,6"
    Name="Heartbeat" Source="/Resources/Heartbeat.png"
    VerticalAlignment="Bottom" HorizontalAlignment="Right" 
    Opacity=".05" Stretch="UniformToFill">
    <Image.Style>
        <Style>
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsHeartBeating}" Value="True">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard Name="HeartbeatStoryboard">
                            <Storyboard RepeatBehavior="Forever">
                                <DoubleAnimation
                                    Storyboard.TargetProperty="Opacity"
                                    From="0.05" To="0.8" Duration="0:0:0.100">
                                </DoubleAnimation>
                                <DoubleAnimation
                                    Storyboard.TargetProperty="Opacity"
                                    From="0.8" To="0.05" Duration="0:0:0.300">
                                    <DoubleAnimation.EasingFunction>
                                        <PowerEase EasingMode="EaseOut" Power="6" />
                                    </DoubleAnimation.EasingFunction>
                                </DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                    <DataTrigger.ExitActions>
                        <StopStoryboard BeginStoryboardName="HeartbeatStoryboard" />
                    </DataTrigger.ExitActions>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Image.Style>
</Image>
Run Code Online (Sandbox Code Playgroud)

如果有人对如何改进心跳动画有任何建议,我愿意接受建议,谢谢!

Fre*_*lad 5

我认为您必须指定 RepeatBehavior="2x" 并订阅 StoryBoard 的 Completed 事件,如果 IsHeartBeating 仍然为 true,则重新启动它。

<Image Height="60" Width="60" Margin="0,6,6,6"   
       Name="Heartbeat" Source="/Resources/Heartbeat.png"   
       VerticalAlignment="Bottom" HorizontalAlignment="Right"    
       Opacity=".05" Stretch="UniformToFill">
    <Image.Resources>
        <Storyboard x:Key="HeartbeatStoryboard2x"
                    RepeatBehavior="2x"
                    Completed="Storyboard_Completed">
            <DoubleAnimation Storyboard.TargetProperty="Opacity"
                             Storyboard.Target="{Binding ElementName=Heartbeat}"
                             From="0.05" To="0.8" Duration="0:0:0.500">
            </DoubleAnimation>
            <DoubleAnimation Storyboard.TargetProperty="Opacity"
                             Storyboard.Target="{Binding ElementName=Heartbeat}"
                             From="0.8" To="0.05" Duration="0:0:1.500">
                <DoubleAnimation.EasingFunction>
                    <PowerEase EasingMode="EaseOut" Power="6" />
                </DoubleAnimation.EasingFunction>
            </DoubleAnimation>
        </Storyboard>
    </Image.Resources>
    <Image.Style>
        <Style>
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsHeartBeating}" Value="True">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard Name="HeartbeatStoryboard">
                            <StaticResource ResourceKey="HeartbeatStoryboard2x"/>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Image.Style>
</Image>
Run Code Online (Sandbox Code Playgroud)

事件处理程序背后的代码。
更新
添加了布尔标志,仅在重新启动时停止情节提要

private bool m_restartedAnimation = false;
private void Storyboard_Completed(object sender, EventArgs e)
{
    ClockGroup clockGroup = sender as ClockGroup;
    Storyboard heartbeatStoryboard = clockGroup.Timeline as Storyboard;
    if (IsHeartBeating == true)
    {
        m_restartedAnimation = true;
        heartbeatStoryboard.Begin();
    }
    else
    {
        if (m_restartedAnimation == true)
        {
            heartbeatStoryboard.Stop();
        }
        m_restartedAnimation = false;
    }
}
Run Code Online (Sandbox Code Playgroud)