A control that plays key frame animation
USAGE
Add this to your XAML:
<cc:KeyFrameAnimationControl
PlayAnimation="{x:Bind PhotoVM.PlayLikeAnimation,Mode=TwoWay}"
ImagesSource="{x:Bind PhotoVM.LikeIconsSrc,Mode=OneWay}"
AnimationTimeSpan="300"
IsStayInLastFrame="False"/>
Key property:
-
PlayAnimation
is a bool type property. To begin the animation, just set this property totrue
. -
ImagesSource
is aIEnumerable<Image>
type property. It's the source of images in each frame in the animation. -
AnimationTimeSpan
is an int type property. It defines the timespan of the animation. -
AutoRePlay
is a bool type property,which by default isfalse
. Setting it to true means the animation will repeat after it reach the end.
Source code
XAML:
<Style TargetType="local:KeyFrameAnimationControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:KeyFrameAnimationControl">
<Grid x:Name="RootGrid"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
cs:
public class KeyFrameAnimationControl : ContentControl
{
public IEnumerable<Image> ImagesSource
{
get { return (IEnumerable<Image>)GetValue(ImagesSourceProperty); }
set { SetValue(ImagesSourceProperty, value); }
}
public static readonly DependencyProperty ImagesSourceProperty =
DependencyProperty.Register("ImagesSource", typeof(IEnumerable<Image>), typeof(KeyFrameAnimationControl), new PropertyMetadata(null));
public int AnimationTimeSpan
{
get { return (int)GetValue(AnimationTimeSpanProperty); }
set { SetValue(AnimationTimeSpanProperty, value); }
}
public static readonly DependencyProperty AnimationTimeSpanProperty =
DependencyProperty.Register("AnimationTimeSpan", typeof(int), typeof(KeyFrameAnimationControl), new PropertyMetadata(1000));
public bool PlayAnimation
{
get { return (bool)GetValue(PlayAnimationProperty); }
set { SetValue(PlayAnimationProperty, value); }
}
public static readonly DependencyProperty PlayAnimationProperty =
DependencyProperty.Register("PlayAnimation", typeof(bool), typeof(KeyFrameAnimationControl), new PropertyMetadata(false,
(sender,e)=>
{
var control = sender as KeyFrameAnimationControl;
if ((bool)e.NewValue) control.StartAnimation();
}));
public bool AutoRePlay
{
get { return (bool)GetValue(AutoRePlayProperty); }
set { SetValue(AutoRePlayProperty, value); }
}
public static readonly DependencyProperty AutoRePlayProperty =
DependencyProperty.Register("AutoRePlay", typeof(bool), typeof(KeyFrameAnimationControl), new PropertyMetadata(false));
public bool IsStayInLastFrame
{
get { return (bool)GetValue(IsStayInLastFrameProperty); }
set { SetValue(IsStayInLastFrameProperty, value); }
}
public static readonly DependencyProperty IsStayInLastFrameProperty =
DependencyProperty.Register("IsStayInLastFrame", typeof(bool), typeof(KeyFrameAnimationControl), new PropertyMetadata(true));
private Grid RootGrid;
private TaskCompletionSource<int> tcs;
private DispatcherTimer timer = new DispatcherTimer();
private int currentFrame = 0;
public KeyFrameAnimationControl()
{
DefaultStyleKey = typeof(KeyFrameAnimationControl);
tcs = new TaskCompletionSource<int>();
}
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
RootGrid = GetTemplateChild("RootGrid") as Grid;
InitialStoryBoard();
tcs.SetResult(0);
}
private void InitialStoryBoard()
{
if(ImagesSource==null)
{
throw new ArgumentException("The ImagesSource should not be null!");
}
else if(ImagesSource.Count()==0)
{
throw new ArgumentException("The ImagesSources count should greater than 1!");
}
foreach (var image in ImagesSource)
{
RootGrid.Children.Add(image);
}
timer.Interval = new TimeSpan(0, 0, 0, 0, (AnimationTimeSpan / ImagesSource.Count()));
timer.Tick += ((sender, et) =>
{
currentFrame++;
//reach the last frame
if (currentFrame == ImagesSource.Count())
{
currentFrame = 0;
if (!AutoRePlay)
{
PlayAnimation = false;
timer.Stop();
}
if(!IsStayInLastFrame)
{
DismissAll();
}
return;
}
var previousFrame = currentFrame == 0 ? ImagesSource.Count()-1 : currentFrame - 1;
ImagesSource.ElementAt(previousFrame).Visibility = Visibility.Collapsed;
ImagesSource.ElementAt(currentFrame).Visibility = Visibility.Visible;
});
}
public void StartAnimation()
{
currentFrame = 0;
timer.Start();
}
public void StopAnimation()
{
timer.Stop();
currentFrame = 0;
}
public void DismissAll()
{
ImagesSource.ToList().ForEach(s => s.Visibility = Visibility.Collapsed);
}
}
Subscribe to JuniperPhoton's Blog
Get the latest posts delivered right to your inbox