Stop storyboard at exact keyFrame - wpf

I made a die for some game I'm making (in c#), it's a usercontrol which uses a storyboard to show several images after each other (like a slideshow) so it looks like a rolling 3D die. The problem is starting and stopping it at a specific keyFrame. It's seems logical to use Pause() and Resume() for this, but I can't figure out how to Pause at an exact keyFrame.
Some people use a seperate dispatcherTimer to do this, but this isn't precise enough to stop it at that exact keyframe. (for example, if you throw 4 it must stop on the 4 image).
So, it would be great if there was some method like this:
TimeSpan keyTime = new TimeSpan(0,0,0,0,750); // 750 miliseconds
myStoryBoard.ResumeTo(keyTime); // <- doesn't exist as far as I know
Here is a snippet from my storyboard in XAML:
<Storyboard x:Key="DieStoryBoard" RepeatBehavior="Forever">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="image1">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:0.05">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="image2">
<DiscreteObjectKeyFrame KeyTime="0:0:0.05">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:0.10">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="image3">
<DiscreteObjectKeyFrame KeyTime="0:0:0.10">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:0.15">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
.....
And some images to make things clearer:

try this...
my example is a rotating arrow,and I can stop it at a specified angle.
<Window.Resources>
<Storyboard x:Key="Storyboard1">
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="(UIElement.RenderTransform).
(TransformGroup.Children)[2].(RotateTransform.Angle)"
Storyboard.TargetName="RightPanelButton1">
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="0.0"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:1" Value="45.0"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:2" Value="90.0"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:3" Value="135.0"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:4" Value="180.0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
Storyboard st = ((Storyboard)this.Resources["Storyboard1"]);
st.Begin();
st.Seek(new TimeSpan(0,0,2));
st.Pause();
Abbas Ahmed

Related

How to start Storyboard by means of data binding?

I have a Storyboard at Window resources as shown below.
<Window.Resources>
<!-- Storyboard as a window resource -->
<Storyboard
x:Key="NB"
x:Name="NB_resource"
Completed="NB_resource_Completed"
RepeatBehavior="5x">
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="NB_image"
Storyboard.TargetProperty="Source"
Duration="0:0:1.2">
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="pack://application:,,,/CircleSurrogateButton;component/Images/NB_00.png" />
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:.3">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="pack://application:,,,/CircleSurrogateButton;component/Images/NB_01.png" />
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:.6">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="pack://application:,,,/CircleSurrogateButton;component/Images/NB_02.png" />
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:.9">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="pack://application:,,,/CircleSurrogateButton;component/Images/NB_03.png" />
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
The Storyboard can be started with the following string which is placed in regular Button.
<EventTrigger RoutedEvent="PreviewMouseLeftButtonDown">
<BeginStoryboard Storyboard="{DynamicResource NB}" />
</EventTrigger>
A question is How to use a data binding in order to start that Storyboard.
For example:
<DataTrigger Binding="{Binding Start_Storyboard}" Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{DynamicResource NB}"/>
</DataTrigger.EnterActions>
</DataTrigger>

Visibility Storyboard works only partial

Please see this Storyboard:
<Storyboard x:Key="visibilityStoryboardn">
<ObjectAnimationUsingKeyFrames BeginTime="0:0:0" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation BeginTime="0:0:0.0" Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:2.0"/>
<DoubleAnimation BeginTime="0:0:10.0" Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:2.0"/>
<ObjectAnimationUsingKeyFrames BeginTime="0:0:2" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
I try to change my element Visibility from Collapsed to Visible with duration of 2 seconds, then wait 10 seconds and change the Visibility back to Collapsed.
currently this do only the first thing, i mean this change my element to Visible with this 2 seconds duration but then start immediately to hide it back to Collapsed but now without and animation style.
I think your only problem is that you defined BeginTime="0:0:2" for your Collapsed keyframe. It should be BeginTime="0:0:12"
<ObjectAnimationUsingKeyFrames BeginTime="0:0:0" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:12.0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation BeginTime="0:0:0.0" Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:2.0"/>
<DoubleAnimation BeginTime="0:0:10.0" Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:2.0"/>

WPF: switch back Grid visibility into first state (Collapsed) after animation

So i have this Grid:
<Grid x:Name="notificarionGrid" Visibility="Collapsed"/>
And i want to change its Visibility value with animation, so i have this 2 Storyboard:
<Storyboard x:Key="fadeIn">
<ObjectAnimationUsingKeyFrames BeginTime="0:0:0" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation BeginTime="0:0:0.0" Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:2.0"/>
</Storyboard>
<Storyboard x:Key="fadeOut">
<DoubleAnimation BeginTime="0:0:0:0" Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:2.0"/>
</Storyboard>
Now this code works fine but the only problem here is that after the fadeOut my Grid Visibility become Hidden instead of Collapsed what cause some elements become not responsible under this Grid.
Any idea how to switch my Grid again to Collapsed ?
You could handle the Completed event for the Storyboard:
private void Storyboard_Completed(object sender, EventArgs e)
{
notificarionGrid.Visibility = Visibility.Collapsed;
}
XAML:
<Storyboard x:Key="fadeOut" Completed="Storyboard_Completed">
<DoubleAnimation BeginTime="0:0:0" Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:2.0"/>
</Storyboard>
Or add an ObjectAnimationUsingKeyFrames to your Storyboard:
<Storyboard x:Key="fadeOut">
<DoubleAnimation BeginTime="0:0:0" Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:2.0"/>
<ObjectAnimationUsingKeyFrames BeginTime="0:0:2" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
Add another ObjectAnimationUsingKeyFrames for the Visibility with an appropriate BeginTime:
<Storyboard x:Key="fadeOut">
<DoubleAnimation Storyboard.TargetProperty="Opacity"
To="0" Duration="0:0:2"/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility"
BeginTime="0:0:2">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>

Silverlight Image Flip Animation

In my silverlight app, I have two images of equal dimension.
When the user clicks on the image I would like to animate the transition of one image to the other as if it were a piece of paper being flipped with the first image on the front and the other on the back.
I haven't worked with silverlight animation, yet so I don't know where to begin.
Basically you will need two Storybards to begin with. Each Storyboard will be using PlaneProjection (in this case I am using RotationX which rotates the images around the x-axis of rotation) to do the flipping animation.
In the following example, I have created FlippingDown and FlippingUp two Storyboards. I attached a ControlStoryboardAction behavior to each of them, they will be triggered when MouseLeftButtonDown is fired.
You'll need to reference System.Windows.Interactivity and Microsoft.Expression.Interactions.
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" mc:Ignorable="d" x:Class="FilppingAnimation.MainPage" Width="640" Height="480">
<UserControl.Resources>
<Storyboard x:Name="FlippingDown">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationX)" Storyboard.TargetName="Front">
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="90.0146"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.6" Value="180"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationX)" Storyboard.TargetName="Back">
<EasingDoubleKeyFrame KeyTime="0" Value="-180"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="-90"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.6" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Front">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:0.3">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Back">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:0.3">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Name="FlippingUp">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Front">
<DiscreteObjectKeyFrame KeyTime="0:0:0.3">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation Duration="0:0:0.6" To="0" Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationX)" Storyboard.TargetName="Front" d:IsOptimized="True"/>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationX)" Storyboard.TargetName="Back">
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="-90.0146"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.6" Value="-180"/>
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Back">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:0.3">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="#FFCC9E9E">
<Image x:Name="Back" HorizontalAlignment="Center" VerticalAlignment="Center" Source="/311438.jpg" Height="226" Width="129">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<ei:ControlStoryboardAction Storyboard="{StaticResource FlippingUp}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<Image.Projection>
<PlaneProjection/>
</Image.Projection>
</Image>
<Image x:Name="Front" HorizontalAlignment="Center" VerticalAlignment="Center" Source="/318549.jpg" Height="226" Width="129" d:IsHidden="True">
<Image.Projection>
<PlaneProjection/>
</Image.Projection>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<ei:ControlStoryboardAction Storyboard="{StaticResource FlippingDown}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Image>
</Grid>
</UserControl>
Hope this helps. :)
You could search for info on Projection animations in Blend. This looks like what you need: http://www.silverlightbuzz.com/2009/10/14/using-the-3d-tools-to-animate-in-blend/

Change the source of Image using StoryBoard

I want to change the source of an image using storyboard in silverlight blend on mouse over:
<VisualState x:Name="MouseOver">
<Storyboard>
---code here--
</Storyboard>
</VisualState>
Ok finally solved it :
On mouse hover i just turn out the visbility of an image to colapsed and made the visibility of other image to visible. That's it :)
<VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="fillColor">
<SplineDoubleKeyFrame KeyTime="0" Value=".35"/>
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="image">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="hoverimage">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>

Resources