Wheel Clockwise animation in WPF

This animation is like the Wheel Clockwise, 1 spoke, animation of MS power point. Some people also call this animation as Radial animation. This animation starts from a line, which points from the centre to top middle, and then it rotates 360 degrees in clockwise direction and makes the underlying object visible. I know one picture can tell what is the animation looks like instead of writing many sentences. The animation looks like the following:

Wheel_40F6EBFA

How this animation effect is achieved?

As we know, every WPF UIelement type has a clip property and you can set any geometry object to clip. I have used this clip property to make this animation. I have changed the geometry object with time so that it looks like a wheel animation. All the challenges to make this animation in this way is making the exact geometry object with time.

I am showing this animation for Image type, which is a Uielement type. However, this trick is applicable to any UIelement type. PathGeometry is used here as the geometry to clip the image. Line segments are added to the path geometry dynamically to make the visible region bigger with time. I have calculated the height and width of the image. Then set the first line segment from (width/2, height/2) to (Width/2, 0). Then added the other line segments when they are needed and also change their points. For this animation, i have used DispatcherTimer, which runs in UI thread instead of worker thread. The code for this is in the following:

   1: public partial class Window1 : Window
   2:     {
   3:         DispatcherTimer _timer = null;
   4:         Ellipse _grdMain = null;
   5:         ContentPresenter _circleContentPresenter = null;
   6:         LineSegment LineSegment2 = null;
   7:         PathFigure PathFigure1 = null;
   8:         bool ISIncrementdirectionX = true;
   9:         bool IsIncrementX = true;
  10:         bool IsIncrementY = true;
  11:         LineSegment LineSegmentFirstcorner = null;
  12:         LineSegment LineSegmentseconcorner = null;
  13:         LineSegment LineSegmentThirdcorner = null;
  14:         LineSegment LineSegmentFourthcorner = null;
  15:         double _ofsetOfAnimation = 2;
  16:  
  17:         double _height = 0;
  18:         double _width = 0;
  19:  
  20:         public Window1()
  21:         {
  22:             InitializeComponent();
  23:             this.Loaded += new RoutedEventHandler(Window1_Loaded);
  24:         }
  25:  
  26:         void Window1_Loaded(object sender, RoutedEventArgs e)
  27:         {
  28:  
  29:             image.Source = loadBitmap(WheelClockwise.Properties.Resources.images1);
  30:             _height = image.Height;
  31:             _width = image.Width;
  32:             string topCentre = Convert.ToString(_width / 2) + ",0";
  33:             string centre = Convert.ToString(_width / 2) + "," + Convert.ToString(_height / 2);        
  34:  
  35:             PathGeometry PathGeometry1 = new PathGeometry();      
  36:             PathFigure1 = new PathFigure();
  37:             PathFigure1.StartPoint = ((Point)new PointConverter().ConvertFromString(centre));
  38:             PathGeometry1.Figures.Add(PathFigure1);
  39:             LineSegment LineSegmentdummy = new LineSegment();
  40:             LineSegmentdummy.Point = ((Point)new PointConverter().ConvertFromString(topCentre));
  41:             PathFigure1.Segments.Add(LineSegmentdummy);
  42:             LineSegmentseconcorner = new LineSegment();
  43:             LineSegmentseconcorner.Point = ((Point)new PointConverter().ConvertFromString(topCentre));
  44:             PathFigure1.Segments.Add(LineSegmentseconcorner);
  45:             LineSegmentThirdcorner = new LineSegment();
  46:             LineSegmentThirdcorner.Point = ((Point)new PointConverter().ConvertFromString(topCentre));
  47:             PathFigure1.Segments.Add(LineSegmentThirdcorner);
  48:             LineSegmentFourthcorner = new LineSegment();
  49:             LineSegmentFourthcorner.Point = ((Point)new PointConverter().ConvertFromString(topCentre));
  50:             PathFigure1.Segments.Add(LineSegmentFourthcorner);
  51:             LineSegmentFirstcorner = new LineSegment();
  52:             LineSegmentFirstcorner.Point = ((Point)new PointConverter().ConvertFromString(topCentre));
  53:             PathFigure1.Segments.Add(LineSegmentFirstcorner);
  54:             LineSegment2 = new LineSegment();
  55:             LineSegment2.Point = ((Point)new PointConverter().ConvertFromString(topCentre));
  56:             PathFigure1.Segments.Add(LineSegment2);
  57:             image.Clip = PathGeometry1;
  58:             _timer = new DispatcherTimer();
  59:             _timer.Interval = TimeSpan.FromSeconds(0.01);
  60:             _timer.Tick += new EventHandler(_timer_Tick);
  61:             _timer.IsEnabled = true;
  62:  
  63:         }
  64:         public static BitmapSource loadBitmap(System.Drawing.Bitmap source)
  65:         {
  66:             return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(source.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty,
  67:                 System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
  68:         }
  69:  
  70:         void _timer_Tick(object sender, EventArgs e)
  71:         {
  72:             if ((LineSegment2.Point.X <= 0) && (LineSegment2.Point.Y <= 0))
  73:             {
  74:  
  75:                 LineSegmentFirstcorner.Point = new Point(LineSegment2.Point.X, LineSegment2.Point.Y);
  76:                 ISIncrementdirectionX = true;
  77:                 IsIncrementX = true;
  78:             }
  79:             else if (((LineSegment2.Point.X >= _width) && (LineSegment2.Point.Y <= 0)))
  80:             {
  81:                 LineSegmentseconcorner.Point = new Point(LineSegment2.Point.X, LineSegment2.Point.Y);
  82:                 LineSegmentThirdcorner.Point = new Point(LineSegment2.Point.X, LineSegment2.Point.Y);
  83:                 LineSegmentFourthcorner.Point = new Point(LineSegment2.Point.X, LineSegment2.Point.Y);
  84:                 LineSegmentFirstcorner.Point = new Point(LineSegment2.Point.X, LineSegment2.Point.Y);
  85:                 ISIncrementdirectionX = false;
  86:                 IsIncrementY = true;
  87:             }
  88:  
  89:             else if ((LineSegment2.Point.X >= _width) && (LineSegment2.Point.Y >= _height))
  90:             {
  91:                 LineSegmentThirdcorner.Point = new Point(LineSegment2.Point.X, LineSegment2.Point.Y);
  92:                 LineSegmentFourthcorner.Point = new Point(LineSegment2.Point.X, LineSegment2.Point.Y);
  93:                 LineSegmentFirstcorner.Point = new Point(LineSegment2.Point.X, LineSegment2.Point.Y);
  94:                 ISIncrementdirectionX = true;
  95:                 IsIncrementX = false;
  96:             }
  97:  
  98:             else if ((LineSegment2.Point.X <= 0) && (LineSegment2.Point.Y >= _height))
  99:             {
 100:                 LineSegmentFourthcorner.Point = new Point(LineSegment2.Point.X, LineSegment2.Point.Y);
 101:                 LineSegmentFirstcorner.Point = new Point(LineSegment2.Point.X, LineSegment2.Point.Y);
 102:                 ISIncrementdirectionX = false;
 103:                 IsIncrementY = false;
 104:             }
 105:  
 106:             double x = 0, y = 0;
 107:  
 108:             if (ISIncrementdirectionX == true)
 109:             {
 110:                 if (IsIncrementX)
 111:                 {
 112:                     x = LineSegment2.Point.X + _ofsetOfAnimation;
 113:                     y = LineSegment2.Point.Y;
 114:                 }
 115:                 else
 116:                 {
 117:                     x = LineSegment2.Point.X - _ofsetOfAnimation;
 118:                     y = LineSegment2.Point.Y;
 119:                 }
 120:             }
 121:             else
 122:             {
 123:                 if (IsIncrementY)
 124:                 {
 125:                     x = LineSegment2.Point.X;
 126:                     y = LineSegment2.Point.Y + _ofsetOfAnimation;
 127:                 }
 128:                 else
 129:                 {
 130:                     x = LineSegment2.Point.X;
 131:                     y = LineSegment2.Point.Y - _ofsetOfAnimation;
 132:                 }
 133:  
 134:             }
 135:  
 136:             LineSegment2.Point = new Point(x, y);
 137:             if ((LineSegment2.Point.X == _width / 2) && (LineSegment2.Point.Y == 0)) _timer.IsEnabled = false;
 138:  
 139:         }
 140:     }

The used XAML for this is in the following

   1: <Window x:Class="WheelClockwise.Window1"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     Title="Window1" Height="400" Width="400">
   5:     <Canvas Name="canMain"  Background="White"    Height="300" Width="300"  >  
   6:         <Image Height="300" Width="300" Stretch="Fill"    Name="image" />
   7:     </Canvas>
   8: </Window>

You can download the sample code from here. Hope this will save some of your time.

No Comments