Introduction
GIF images cannot be used directly in a WPF application. There are lot of third party libraries which support GIF images in WPF. Here is one which could play animated sprite sheets in WPF.
Background
If you are good with WPF custom controls, Dispatcher timer, and Render Transforms, you are ready to read this tip.
Using the Code
We have a custom control which contains an image control in which the Source
property is bound to the ImageSource
property. The user will set the Sprite sheet image source to this property.
<Style TargetType="{x:Type local:Animator}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:Animator}">
<Grid >
<Canvas Background="{TemplateBinding Background}"
x:Name="PART_Border" HorizontalAlignment="Center"
VerticalAlignment="Center">
<Image Source="{TemplateBinding ImageSource}"
Stretch="UniformToFill" x:Name="PART_Image">
</Image>
</Canvas>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Normally a Sprite sheet can be horizontal or vertical or both (with rows and columns). A small portion of the sprite image will be exposed by clipping it. We used the HorizontalOffset
and VerticalOffset
properties to decide the Clip
rect.
private void SetRect()
{
if (_image != null)
{
_border.Clip = new RectangleGeometry(new Rect(0, 0, HorizontalOffset, VerticalOffset));
_border.Height = VerticalOffset;
_border.Width = HorizontalOffset;
if (HorizontalOffset > 0.0)
_maxHpieces = Convert.ToInt16(_image.ActualWidth / HorizontalOffset);
if (VerticalOffset > 0.0)
_maxVpieces = Convert.ToInt16(_image.ActualHeight / VerticalOffset);
}
}
Choosing the offset values is the only challenge here. It simply defines the size of each image in the Sprite map. We are going to change the translate transform based on the offset values at a specific interval. Since we already clipped a particular portion of the image based on the offset, it gives an impression of animation.
void Animator_Loaded(object sender, RoutedEventArgs e)
{
_timer = new DispatcherTimer(Interval, DispatcherPriority.Normal, Callback, Dispatcher);
SetRect();
Loaded -= Animator_Loaded;
Unloaded += Animator_Unloaded;
_timer.Start();
}
private void Callback(object sender, EventArgs eventArgs)
{
_Hcount++;
if (_Hcount >= _maxHpieces)
{
_Hcount = 0;
_Vcount++;
if (_Vcount >= _maxVpieces)
{
_Vcount = 0;
}
}
_image.RenderTransform = new TranslateTransform
(-HorizontalOffset * _Hcount, -VerticalOffset * _Vcount);
}
The offset values may change based on the size of the sprite image. I have attached a demo which contains the various sizes of Sprite images.
Points of Interest
There are many online tools and sites which convert GIF images to Sprite images. The following one looks good: