Blackspike Design Ltd

Free Silverlight and WPF loading spinners

Here’s some free spinners we’ve been making with Blend and Illustrator that you can use as indeterminate loaders for Silverlight or any WPF app, all that needs changing to suit is the storyboard trigger. Enjoy!

Click to see sample XAML code of DotCircle:
<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"
mc:Ignorable="d"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:im="clr-namespace:Microsoft.Expression.Interactivity.Media;assembly=Microsoft.Expression.Interactions"
x:Class="xamlSpinners.ucSpinner_1">
<UserControl.Resources>
<Storyboard x:Name="spinner" RepeatBehavior="ForEver" BeginTime="00:00:00">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ellipse01" Storyboard.TargetProperty="(UIElement.Opacity)">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.1000000" Value="0.5"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.2000000" Value="0.25"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ellipse12" Storyboard.TargetProperty="(UIElement.Opacity)">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="0.5"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.1000000" Value="0.25"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.2000000" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:01" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:01.1000000" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ellipse11" Storyboard.TargetProperty="(UIElement.Opacity)">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="0.25"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.1000000" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.9000000" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:01" Value="1"/>
<EasingDoubleKeyFrame KeyTime="00:00:01.1000000" Value="0.5"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ellipse02" Storyboard.TargetProperty="(UIElement.Opacity)">
<EasingDoubleKeyFrame KeyTime="00:00:00.1000000" Value="1"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.2000000" Value="0.5"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0.25"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.4000000" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ellipse03" Storyboard.TargetProperty="(UIElement.Opacity)">
<EasingDoubleKeyFrame KeyTime="00:00:00.1000000" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.2000000" Value="1"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0.5"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.4000000" Value="0.25"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5000000" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ellipse04" Storyboard.TargetProperty="(UIElement.Opacity)">
<EasingDoubleKeyFrame KeyTime="00:00:00.1000000" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.2000000" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.3000000" Value="1"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.4000000" Value="0.5"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5000000" Value="0.25"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.6000000" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ellipse05" Storyboard.TargetProperty="(UIElement.Opacity)">
<EasingDoubleKeyFrame KeyTime="00:00:00.1000000" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.4000000" Value="1"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5000000" Value="0.5"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.6000000" Value="0.25"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.7000000" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ellipse06" Storyboard.TargetProperty="(UIElement.Opacity)">
<EasingDoubleKeyFrame KeyTime="00:00:00.1000000" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.4000000" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.6000000" Value="0.5"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.7000000" Value="0.25"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.8000000" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ellipse07" Storyboard.TargetProperty="(UIElement.Opacity)">
<EasingDoubleKeyFrame KeyTime="00:00:00.1000000" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5000000" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.6000000" Value="1"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.7000000" Value="0.5"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.8000000" Value="0.25"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.9000000" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ellipse08" Storyboard.TargetProperty="(UIElement.Opacity)">
<EasingDoubleKeyFrame KeyTime="00:00:00.1000000" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.6000000" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.7000000" Value="1"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.8000000" Value="0.5"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.9000000" Value="0.25"/>
<EasingDoubleKeyFrame KeyTime="00:00:01" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ellipse09" Storyboard.TargetProperty="(UIElement.Opacity)">
<EasingDoubleKeyFrame KeyTime="00:00:00.1000000" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.7000000" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.8000000" Value="1"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.9000000" Value="0.5"/>
<EasingDoubleKeyFrame KeyTime="00:00:01" Value="0.25"/>
<EasingDoubleKeyFrame KeyTime="00:00:01.1000000" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ellipse10" Storyboard.TargetProperty="(UIElement.Opacity)">
<EasingDoubleKeyFrame KeyTime="00:00:00.1000000" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.8000000" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.9000000" Value="1"/>
<EasingDoubleKeyFrame KeyTime="00:00:01" Value="0.5"/>
<EasingDoubleKeyFrame KeyTime="00:00:01.1000000" Value="0.25"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</UserControl.Resources>

<Canvas x:Name="spinner_1" HorizontalAlignment="Center" Width="24" Height="24">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<im:ControlStoryboardAction Storyboard="{StaticResource spinner}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<Ellipse x:Name="ellipse01" Fill="White" Height="4" Width="4" Canvas.Top="10" Opacity="0" />
<Ellipse x:Name="ellipse02" Fill="White" Height="4" Width="4" Canvas.Top="5" Opacity="0" Canvas.Left="1.33975" />
<Ellipse x:Name="ellipse03" Fill="White" Height="4" Width="4" Canvas.Top="1.4" Opacity="0" Canvas.Left="5"/>
<Ellipse x:Name="ellipse04" Fill="White" Height="4" Width="4" Canvas.Top="0" Opacity="0" Canvas.Left="10"/>
<Ellipse x:Name="ellipse05" Fill="White" Height="4" Width="4" Canvas.Top="1.4" Opacity="0" Canvas.Left="15"/>
<Ellipse x:Name="ellipse06" Fill="White" Height="4" Width="4" Canvas.Top="5" Opacity="0" Canvas.Left="18.6603"/>
<Ellipse x:Name="ellipse07" Fill="White" Height="4" Width="4" Canvas.Top="10" Canvas.Left="20" Opacity="0" />
<Ellipse x:Name="ellipse08" Fill="White" Height="4" Width="4" Canvas.Top="15" Canvas.Left="18.7" Opacity="0" />
<Ellipse x:Name="ellipse09" Fill="White" Height="4" Width="4" Canvas.Top="18.66025" Canvas.Left="15" Opacity="0"/>
<Ellipse x:Name="ellipse10" Fill="White" Height="4" Width="4" Canvas.Top="20" Canvas.Left="10" Opacity="0"/>
<Ellipse x:Name="ellipse11" Fill="White" Height="4" Width="4" Canvas.Top="18.66025" Canvas.Left="5" Opacity="0"/>
<Ellipse x:Name="ellipse12" Fill="White" Height="4" Width="4" Canvas.Top="15" Canvas.Left="1.4" Opacity="0"/>

<Grid x:Name="LayoutRoot" Height="24" Width="24"/>
</Canvas>
</UserControl>

Update

Several people have requested a WPF version, so we created a WPF project and added it below :)

Update 2

These are now available on GitHub!

Fork these on GitHub

17 Responses

  1. Wow, this is really awesome. I particularly like the spinning gears, and the flipping squares? Nice job!

  2. […] Also as a related point, with this release we've update all the build-in container templates, they now match the Silverlight's standard way of templating content controls. Another changes is that the template now shows an overlay with an animated indicator whilst navigating (it uses a spinning indicator by Felix Corke). […]

  3. Normski says:

    Excellent work, can I provide a WPF version? Also if you group the canvas into a ViewBox you can size the spinners.

    Thanks for sharing.

  4. felix says:

    WPF project added. Also Normski, rather than using a viewbox, I’d recommend using a scale transform, it’s more efficient. Cheers!

  5. Normski says:

    Felix
    Thanks for the WPF version and the Transform scaling tip.

  6. Rev says:

    Cool ….
    I love it….

  7. Dmitry says:

    Thanks!!!

  8. Beej says:

    Why does the lower cog seem to skip a beat every rotation?

  9. CodeNinja says:

    These are awesome! Easily customizable from other wpf spinners I’ve seen. Great job – easy to integrate.

  10. Glen says:

    They are indeed very good.

    Is there an easy way to scale them bigger?

    I need one that is about 4 or 5 times bigger.

  11. felix says:

    @glen – sure, just use a scale transform on the usercontrol



  12. madscientist says:

    Awesome stuff. Just what I was looking for.

    However one thing, the .cs files are not in the zip for the silverlight project ? I get an error when trying to compile in VS2010.

  13. Kevin says:

    Is there any way I can change the color of the user controls? Like the white Apple spinner to black.

  14. Robin Anderson says:

    Fantastic! I extended it slightly by allowing customisable colours. Others wishing to do the same can simply replace Fill=”White” in the XAML with Fill=”{Binding Path=SpinColor, ElementName=UserControl}”
    (Or whatever x:Name you have for the control)

    And in the code behind add:
    public Brush SpinColor
    {
    get { return (Brush)this.GetValue(SpinColorProperty); }
    set { this.SetValue(SpinColorProperty, value); }
    }

    public static readonly DependencyProperty SpinColorProperty =
    DependencyProperty.RegisterAttached(“SpinColor”, typeof(Brush),
    typeof(AppleSpinner),
    new UIPropertyMetadata(Brushes.White));

  15. Brendan Forster says:

    I’d love to use some of these in an open-source project, but there is no license attached to the downloads. I’d love to update and tweak them too, so is this possible?

  16. felix says:

    Hey Brendan, feel free to use as you like, no license involved at all. Fill your boots! Cheers

  17. […] 查了一些資料,這個TeamFoundation Framework,需要安裝VS 2010, 2012才會有。所以,打消了使用這個Framework上的元件的念頭。問了一下谷哥,找到了另一個可用的元件,用來呈現Busy Spinner。它提供了幾種Spinner的樣式,可以在這個網頁看Demo的樣子。 […]

Open/Close menu