Introduction
This article demonstrates how to implement a simple transition on images in VB.NET.
Transitions are one of the most useful features used in slide shows, business presentations, videos, screensavers, and with transitions, coders can build simple and easy visual effects on their web pages/Windows Forms/videos with simple and very minimal code.
Background
You may find a lot of articles that demonstrate how to implement image transitions using Silverlight or Dynamic HTML, but it's rare to find articles that talk about image transitions either in C# or VB.NET Windows Forms ...... apparently, image transitions are very good business.
In this article, I'll try to explain some of the most popular image transition methods and how they are done.
Transitions and Visual Effects
The list below shows the most popular image visual effects/transitions. You may follow the same transition names or rename the transitions to your convenience
- Barn: motion that resembles a doors opening or closing effect
- Blinds: motion that appears to open or close blinds
- CheckBoard: squares placed like a checker or chess board
- Iris: motion similar to opening of camera aperture
- Fade: fading out one or two images
- Slide: sliding sections or the whole image into place
- Spiral: spiral motion
Transitions Timing
The System.Threading.Timer
class implements a simple light-weight timer that uses callback functions, and yes, it only has a few features, but it also has some nice benefits such as a way to specify the callback, a way to specify the time to wait before the first time the callback is run, and a way to specify the period between calls. These are very important to have an upper hand over the speed of GDI+ during transitions and to calculate a transition's steps.
Also, some people may prefer to use the System.Timers.Timer
class instead of the System.Threading.Timer
class and hook up the Elapsed
event for the Timer
class to accelerate GDI+.
The following simple code illustrates how to use the System.Timers
class to draw something on the form:
Private m_timer As New System.Timers.Timer()
Hook up the Elapsed
event for the timer and enable the timer (the StartTimer
routine):
Private Sub StartTimer(ByVal m_Interval As Integer)
AddHandler m_timer.Elapsed, AddressOf TimerTick
m_timer.Interval = m_Interval
m_timer.Enabled = True
End Sub
Specify what you want to happen when the Elapsed
event is raised:
Private Sub TimerTick(ByVal source As Object, _
ByVal e As System.Timers.ElapsedEventArgs)
Invalidate()
End Sub
Draw something in the Paint
event:
Private Sub Form2_Paint(ByVal sender As System.Object, _
ByVal e As PaintEventArgs) Handles MyBase.Paint
Dim path As New Drawing2D.GraphicsPath()
Dim stringText As String = Date.Now
Dim family As New FontFamily("Verdana")
Dim myfontStyle As Integer = CInt(FontStyle.Bold)
Dim emSize As Integer = 20
Dim origin As New Point(0, 0)
Dim format As StringFormat = StringFormat.GenericDefault
path.AddString(stringText, family, myfontStyle, emSize, origin, format)
Using lgb As New Drawing2D.LinearGradientBrush(path.GetBounds(), _
Color.Cyan, Color.Blue, 90, 0)
e.Graphics.FillPath(lgb, path)
End Using
End Sub
Pass the StartTime
routine to the Form Load event and run:
Private Sub Form2_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
StartTimer(1000)
End Sub
The following code illustrates how to use System.Threading.Timer
to draw something on the form by following the same steps above:
Public Class Form1
Private ThreadTimer As System.Threading.Timer
Private Sub StartTimer(ByVal Interval As Integer)
Dim CallBackTimer As New Threading.TimerCallback(AddressOf TimerTick)
ThreadTimer = New System.Threading.Timer(CallBackTimer, Nothing, 0, Interval)
End Sub
End Class
Barn Visual Effect
The following code example illustrates how to apply a simple vertical Barn transition:
- Declare variables such as the timer, transition steps, and starting time:
Public Class frmTransition
Private m_timer As New System.Timers.Timer()
Private m_Steps As Single
Private m_startTime As DateTime
End Class
Hook up the Elapsed
event for the timer, initialize the variables, and enable the timer (the StartTimer
routine):
Private Sub StartTimer(ByVal m_Interval As Integer)
AddHandler m_timer.Elapsed, AddressOf TimerTick
m_timer.Interval = m_Interval
m_timer.Enabled = True
m_Steps = 0
m_startTime = DateTime.Now
Invalidate()
End Sub
' .......... rest of code
Specify what you want to happen when the Elapsed
event is raised. Define and calculate the elapsed time, define the animation time (the lowest the value, the highest the speed), calculate the transition steps and invalidate the paint:
Private Sub TimerTick(ByVal source As Object, _
ByVal e As System.Timers.ElapsedEventArgs)
Dim timeEllapsed As TimeSpan = DateTime.Now - m_startTime
Dim AnimationTime As Integer = 2
m_Steps = CSng((100.0F / AnimationTime * timeEllapsed.TotalSeconds))
If m_Steps > 100 Then
m_Steps = 100
End If
Invalidate()
End Sub
To draw the transition effect, follow these steps:
- Define a transition bitmap.
- Define a transition rectangle.
- Draw the top part Barn effect by defining the top part of the destination rectangle. Define the image top part source rectangle and then draw the top part of the image.
- Repeat step 3 to draw the bottom part of the Barn effect by defining the destination rectangle bottom part. Define the image's bottom part source rectangle and then draw the bottom part of the image.
Private Sub frmTransition_Paint(ByVal sender As Object, _
ByVal e As PaintEventArgs) _
Handles MyBase.Paint
Dim bmp As New Bitmap(My.Resources.baby_5)
Dim m_rect As New Rectangle(0, 0, 100, 100)
Dim destTopRect As New Rectangle(0, 0, m_rect.Width, _
CInt(m_rect.Height * m_Steps / 200))
Dim srcTopRect As New Rectangle(0, 0, bmp.Width, CInt(bmp.Height / 2))
e.Graphics.DrawImage(bmp, destTopRect, srcTopRect, GraphicsUnit.Pixel)
Dim destBottomRect As New Rectangle(0, _
CInt(m_rect.Height - CInt(m_rect.Height * m_Steps / 200)), _
m_rect.Width, _
CInt((m_rect.Height * m_Steps / 200)))
Dim srcBottomRect As New Rectangle(0, CInt(bmp.Height / 2), _
bmp.Width, CInt(bmp.Height / 2))
e.Graphics.DrawImage(bmp, destBottomRect, srcBottomRect, GraphicsUnit.Pixel)
End Sub
- Pass the
StartTime
routine to the Form Load event and run.
- Set the time interval to 60 milliseconds.
- To get better performance, I believe the interval value should not exceed 100 milliseconds. The smaller the value, the better the performance.
Private Sub frmTransition_Load(ByVal sender As Object, _
ByVal e As EventArgs) Handles MyBase.Load
StartTimer(60)
End Sub
The following code example illustrates how to apply a horizontal Barn transition:
Private Sub frmTransition_Paint(ByVal sender As Object, _
ByVal e As PaintEventArgs) Handles MyBase.Paint
Dim bmp As New Bitmap(My.Resources.baby_5)
Dim m_rect As New Rectangle(0, 0, 100, 100)
Dim destTopRect As New Rectangle(0, 0, _
CInt(m_rect.Width * m_Steps / 200), m_rect.Height)
Dim srcTopRect As New Rectangle(0, 0, CInt(bmp.Width / 2), bmp.Height)
e.Graphics.DrawImage(bmp, destTopRect, srcTopRect, GraphicsUnit.Pixel)
Dim destBottomRect As New Rectangle(_
CInt(m_rect.Width - CInt(m_rect.Width * m_Steps / 200)), _
0, _
CInt((m_rect.Width * m_Steps / 200)), _
m_rect.Height)
Dim srcBottomRect As New Rectangle(CInt(bmp.Width / 2), 0, _
CInt(bmp.Width / 2), bmp.Height)
e.Graphics.DrawImage(bmp, destBottomRect, srcBottomRect, GraphicsUnit.Pixel)
End Sub
What will happen if we mix between the above two Barn visual effects (horizontal and vertical effects).......!!!??? We will get a different effect ....... you may call it Barns Boom!
The following code example illustrates how to apply a Barns Boom transition:
Private Sub frmTransition_Paint(ByVal sender As Object, _
ByVal e As PaintEventArgs) Handles MyBase.Paint
Dim bmp As New Bitmap(My.Resources.baby_5)
Dim m_rect As New Rectangle(0, 0, 100, 100)
Dim destLeftRect As New Rectangle(0, 0, _
CInt(m_rect.Width * m_Steps / 200), m_rect.Height)
Dim srcLeftRect As New Rectangle(0, 0, CInt(bmp.Width / 2), bmp.Height)
e.Graphics.DrawImage(bmp, destLeftRect, srcLeftRect, GraphicsUnit.Pixel)
Dim destRightRect As New Rectangle(_
CInt(m_rect.Width - CInt(m_rect.Width * m_Steps / 200)), _
0, _
CInt((m_rect.Width * m_Steps / 200)), _
m_rect.Height)
Dim srcRightRect As New Rectangle(CInt(bmp.Width / 2), 0, _
CInt(bmp.Width / 2), bmp.Height)
e.Graphics.DrawImage(bmp, destRightRect, srcRightRect, GraphicsUnit.Pixel)
Dim destTopRect As New Rectangle(0, 0, m_rect.Width, _
CInt(m_rect.Height * m_Steps / 200))
Dim srcTopRect As New Rectangle(0, 0, bmp.Width, CInt(bmp.Height / 2))
e.Graphics.DrawImage(bmp, destTopRect, srcTopRect, GraphicsUnit.Pixel)
Dim destBottomRect As New Rectangle(0, _
CInt(m_rect.Height - CInt(m_rect.Height * m_Steps / 200)), _
m_rect.Width, _
CInt((m_rect.Height * m_Steps / 200)))
Dim srcBottomRect As New Rectangle(0, CInt(bmp.Height / 2), _
bmp.Width, CInt(bmp.Height / 2))
e.Graphics.DrawImage(bmp, destBottomRect, srcBottomRect, GraphicsUnit.Pixel)
End Sub
Rotate, Maximize, and Spin Visual Effect
The Drawin2D.Matrix
class plays an important role in transition effects such as rotate, maximize, and spin of an image, and the following steps highlight the main points used in the Maximize visual effect:
- Define the transition bitmap
- Define the transition rectangle
- Define and calculate the transition scale factor used in the matrix
- Define the matrix class and pass the scale factor to it, the effect will start from the rectangle mid-point
- Pass the matrix to the graphics and draw the effect
The following code example illustrates how to apply the Maximize transition:
Private Sub frmTransition_Paint(ByVal sender As Object, _
ByVal e As PaintEventArgs) Handles MyBase.Paint
Dim bmp As New Bitmap(My.Resources.baby_5)
Dim m_rect As New Rectangle(0, 0, 150, 150)
Dim sf As Single = m_Steps / 100
If sf = 0 Then
sf = 0.01F
End If
Dim mx As New Drawing2D.Matrix(sf, 0, 0, sf, m_rect.Width / 2, m_rect.Height / 2)
e.Graphics.Transform = mx
Dim destRect As New Rectangle(-m_rect.Width / 2, -m_rect.Height / 2, _
m_rect.Width, m_rect.Height)
Dim srcRect As New Rectangle(0, 0, bmp.Width, bmp.Height)
e.Graphics.DrawImage(bmp, destRect, srcRect, GraphicsUnit.Pixel)
End Sub
The following steps highlight the main points used with the Rotate and Spin visual effect:
- Define the transition bitmap
- Define the transition rectangle
- Define and calculate the transition scale factor used in the matrix
- Define the matrix class and pass the scale factor to it, the effect will start from the rectangle mid-point
- Define the rotation factor
- Pass the rotation factor to the matrix to rotate the matrix and set the
Drawing2D.MatrixOrder
value to Append
(for Spin effect, just set the Drawing2D.MatrixOrder
value to Prepend
)
- Pass the matrix to the graphics and draw the effect
Private Sub frmTransition_Paint(ByVal sender As Object, _
ByVal e As PaintEventArgs) _
Handles MyBase.Paint
Dim bmp As New Bitmap(My.Resources.baby_5)
Dim m_rect As New Rectangle(0, 0, 150, 150)
Dim sf As Single = m_Steps / 100
If sf = 0 Then
sf = 0.01F
End If
Dim mx As New Drawing2D.Matrix(sf, 0, 0, sf, _
m_rect.Width / 2, m_rect.Height / 2)
Dim rf As Single = m_Steps * 360 / 100
mx.Rotate(rf, Drawing2D.MatrixOrder.Append)
e.Graphics.Transform = mx
Dim destRect As New Rectangle(-m_rect.Width / 2, -m_rect.Height / 2, _
m_rect.Width, m_rect.Height)
Dim srcRect As New Rectangle(0, 0, bmp.Width, bmp.Height)
e.Graphics.DrawImage(bmp, destRect, srcRect, GraphicsUnit.Pixel)
End Sub
For further details about other effects (there are about 28 effects waiting for you to play with), you may download the file attached to the article:
The Animation Control
- Animation control files
- AnimationTypes.vb: Public enum of about 28 visual effects/transitions
- AnimationControl.vb: Extending the
Control
class
- Control property
AnimationSpeed
: used to set the animation speed; the greater the value, the slower the speed
AnimationType
: used to set the Animationtypes
enum
AnimatedImage
: used to set the image required for the visual effect
AnimatedFadeImage
: used to set the fade image which will be used with the animated image
Opacity
, Transparent
, TransparenColor
: used to set the transparency of the control (for further details, you may refer to my earlier article about VB.NET translucent controls using GDI+, available in this link)
Using the Control
Build AnimationControl
and use it in your forms. The following simple code illustrates how to use AnimationControl
with Windows Forms:
Public Class TestForm
Private bmp As New Bitmap(My.Resources.baby_5)
Private Sub TestForm_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
AnimationControl1.AnimatedFadeImage = Panel1.BackgroundImage
AnimationControl1.AnimatedImage = bmp
End Sub
Private Sub btnSpiarlBoom_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnSpiarlBoom.Click
AnimationControl1.AnimationType = AnimationTypes.SpiralBoom
AnimationControl1.Animate(40)
End Sub
End Class
Download the attached file, play with it, and you may add your own visual effects ....... it is simple and funny. Enjoy it.
History
- 7th November, 2009: First release.