XAML Heartbeat Animation - How to ensure heart beats at least twice

删除回忆录丶 提交于 2019-12-09 23:58:13

问题


Greetings,

I would like to visually show when a background process is working. This process happens at a regular intervals (say every 30 seconds), and might take 10ms or 1000ms+ to complete. I'm using MVVM-Light framework so have created a data trigger wired up to a view model property on an image of a heart fading in and out.

My amateur animation technique is working when the process takes a second or more, but I would also like it to complete a full heartbeat (2 repeats) when the process takes a short period of time (<100ms), otherwise the animation is over too quickly and you can't (visually) tell that the process is working.

The problem is that the heart should remain beating for the duration of the process, so I can't just set the repeat behaviour to 2. A XAML solution is preferred, but I will not cringe if some code behind is needed :)

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

And if anyone has any tips on how to improve the heartbeat animation, I'm open to suggestions, thanks!


回答1:


I think you're gonna have to specify RepeatBehavior="2x" and subscribe to the Completed event for the StoryBoard and if IsHeartBeating is still true then you restart it.

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

Code behind event handler.
Update
Added boolean flag to only Stop the Storyboard when is has been re-started

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


来源:https://stackoverflow.com/questions/4434746/xaml-heartbeat-animation-how-to-ensure-heart-beats-at-least-twice

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!