Silverlight Analog/Retro Flip Numbers

I’m not sure what to call these exactly. I’ve created a relatively simple Silverlight 4 control that emulates the old mechanical flip style numbers (or letters) displays found at airports and in old clock-radios.

image

I call it the RetroFlipper.

It’s easy to use (at least for my needs). Declare an instance of the control in XAML:

xmlns:wpcontrols="clr-namespace:WiredPrairie.Controls;assembly=WiredPrairie.RetroFlipperControl"             

 

        <wpcontrols:RetroFlipper Margin="5,20" 
                                 x:Name="numberFlip100" Grid.RowSpan="1" Grid.Column="1"/>

And then respond to the “Flipped” event and set the “Text” property as needed.

            numberFlip0.Flipped += new EventHandler(numberFlip1_Flipped);
            numberFlip0.Text = "0"; //(0, 0);

The default animation speed can be adjusted:

numberFlip0.AnimationSpeed = 1;

It’s a percentage – 1.0 is the default. If you want the animation of the flip to be half speed for example, just set it to .5.

The class that drives the demo is really simple:

public partial class MainPage : UserControl
{
    private DispatcherTimer _timer;
    private int _inc = 0;

    public MainPage()
    {
        InitializeComponent();
        numberFlip0.Text = "0"; //(0, 0);
        numberFlip0.AnimationSpeed = 1;
        numberFlip10.Text = "0"; //(0, 0);
        numberFlip10.AnimationSpeed = .7;
        numberFlip100.Text = "0"; //(0, 0);
        numberFlip100.AnimationSpeed = .4;
        _timer = new DispatcherTimer();
        _timer.Interval = TimeSpan.FromSeconds(.5);
        _timer.Tick += new EventHandler(_timer_Tick); 
        
    }

    void _timer_Tick(object sender, EventArgs e)
    {
        int current = _inc;
        int next = ++_inc;
        if (next % 10 == 0)
        {
            numberFlip10.Text = Math.Floor(next / 10 % 10).ToString(); 
        }
        if (next % 100 == 0)
        {
            numberFlip100.Text = Math.Floor(next / 100 % 100).ToString(); 
        }

        numberFlip0.Text = (next % 10).ToString();            
    }

    private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        _timer.Start();
    }
}

(And no, it doesn’t handle numbers > 1000).

Building the control required a few tricks.

The most interesting was that I decided to use 4 layers to actually represent and animate the flip cards:

image

Using a few OpacityMasks

<Border.OpacityMask>
    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
        <GradientStop Color="Transparent" Offset="0.5"/>
        <GradientStop Color="Black" Offset="1"/>
        <GradientStop Color="Black" Offset="0.5"/>
        <GradientStop Color="Transparent"/>
    </LinearGradientBrush>
</Border.OpacityMask>

and some creative PlaneProjection and animations,

<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationX)" Storyboard.TargetName="backBottom">
    <EasingDoubleKeyFrame KeyTime="0:0:0.17" Value="270"/>
    <EasingDoubleKeyFrame KeyTime="0:0:0.27" Value="180"/>
    <EasingDoubleKeyFrame KeyTime="0:0:0.30" Value="220"/>
    <EasingDoubleKeyFrame KeyTime="0:0:0.32" Value="180"/>
</DoubleAnimationUsingKeyFrames>

it’s possible to create the illusion of the mechanical parts moving.

Any text may be set into the Text property – it’s automatically sized to fill. So, it could be words, double digits, anything you’d like, as long as it’s text.

In any case, the demo is here.

The source code, licensed under BSD, is here.

Enjoy.

3 Comments

  1. This is great and exactly what I need — only I need it for Windows Phone. I am working on back-porting it but have stumbled on your use of . Any ideas how to get around it?

    Very well done! Thank you very much.

  2. Oh. It looks like XAML tags don’t come through in your comments. Sorry about that.

    The problem is that the control won’t build for WP7 with this tag in place:
    ei:ExtendedVisualStateManager

    Because the ExtendedVisualStateManager is SL4 specific.

    And then (I don’t know if this is related) if I take the ExtendedVisualStateManager out, this line results in a NULL at runtime:

    _partContainer = this.GetTemplateChild(“PART_Container”) as Panel;

    even if I take out the cast to Panel, it is still null.

    I see you are doing WP7 stuff now, too, so I thought you might have a better idea than I do on how to work around the SL4 specific stuff.

    Thanks!
    –Jason

Comments are closed.