Image Transition in VB.NET Windows Forms
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
TheSystem.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:- Declare timer:
Private m_timer As New System.Timers.Timer()
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
Elapsed
event is raised:Private Sub TimerTick(ByVal source As Object, _
ByVal e As System.Timers.ElapsedEventArgs)
Invalidate()
End Sub
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
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
' ........ rest of the code as explained before
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
' .......... rest of code
End Class
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
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)
' define & calculate ellapsed time
Dim timeEllapsed As TimeSpan = DateTime.Now - m_startTime
' define animation time
'the lowest the value the highest the speed
Dim AnimationTime As Integer = 2
' calcualte transition steps
m_Steps = CSng((100.0F / AnimationTime * timeEllapsed.TotalSeconds))
' check transition steps value & fix it
If m_Steps > 100 Then
m_Steps = 100
End If
' invalidate the paint
Invalidate()
End Sub
' .......... rest of code
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.
- 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_Paint(ByVal sender As Object, _
ByVal e As PaintEventArgs) _
Handles MyBase.Paint
' define transition bitmap
Dim bmp As New Bitmap(My.Resources.baby_5)
' define transition rectangle
Dim m_rect As New Rectangle(0, 0, 100, 100)
' draw the top part barns effect
' draw the top part of the image based on transition steps
' define the top part of destination rectangle
Dim destTopRect As New Rectangle(0, 0, m_rect.Width, _
CInt(m_rect.Height * m_Steps / 200))
' define the image top part source rectangle
Dim srcTopRect As New Rectangle(0, 0, bmp.Width, CInt(bmp.Height / 2))
' draw the top part of the image
e.Graphics.DrawImage(bmp, destTopRect, srcTopRect, GraphicsUnit.Pixel)
' let us repeat the steps above to draw the bottom part of the barns effect
' define the destination rectangle bottom part
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)))
' define the image's bottom part source rectangle
Dim srcBottomRect As New Rectangle(0, CInt(bmp.Height / 2), _
bmp.Width, CInt(bmp.Height / 2))
' draw the bottom part of the image
e.Graphics.DrawImage(bmp, destBottomRect, srcBottomRect, GraphicsUnit.Pixel)
End Sub
Private Sub frmTransition_Load(ByVal sender As Object, _
ByVal e As EventArgs) Handles MyBase.Load
StartTimer(60)
End Sub
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)
' draw the left part barns effect
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)
' draw the right part barns effect
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)
' ------------------------------------------------------->
' draw the left part of the barn
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)
' ------------------------------------------------------->
' draw the right part of the barn
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)
' ------------------------------------------------------->
' draw the top part of the barn
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)
' ------------------------------------------------------->
' draw the bottom part of the barn
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
TheDrawin2D.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
Private Sub frmTransition_Paint(ByVal sender As Object, _
ByVal e As PaintEventArgs) Handles MyBase.Paint
' draw maximize effect
Dim bmp As New Bitmap(My.Resources.baby_5)
Dim m_rect As New Rectangle(0, 0, 150, 150)
' define and calculate transition scale factor used in the matrix
Dim sf As Single = m_Steps / 100
If sf = 0 Then
sf = 0.01F
End If
' define the matrix class & pass the scale factor to it
' effect will strat from the rectangle mid-point
Dim mx As New Drawing2D.Matrix(sf, 0, 0, sf, m_rect.Width / 2, m_rect.Height / 2)
' pass the matrix to graphics
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 toAppend
(for Spin effect, just set theDrawing2D.MatrixOrder
value toPrepend
) - 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
' draw maximize effect
Dim bmp As New Bitmap(My.Resources.baby_5)
Dim m_rect As New Rectangle(0, 0, 150, 150)
' define and calculate transition scale factor used in the matrix
Dim sf As Single = m_Steps / 100
If sf = 0 Then
sf = 0.01F
End If
' define the matrix class & pass the scale factor to it
' effect will strat from the rectangle mid-point
Dim mx As New Drawing2D.Matrix(sf, 0, 0, sf, _
m_rect.Width / 2, m_rect.Height / 2)
' pass the matrix to graphics
' define rotation factor
Dim rf As Single = m_Steps * 360 / 100
' pass the rotation factor to the matrix
' to rotate the matrix and set the matrixorder
' for spin set MatrixOrder value to Prepend
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 speedAnimationType
: used to set theAnimationtypes
enumAnimatedImage
: used to set the image required for the visual effectAnimatedFadeImage
: used to set the fade image which will be used with the animated imageOpacity
,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
BuildAnimationControl
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
' rest of code
End Class
Download the attached file, play with it, and you may add your own visual effects ....... it is simple and funny. Enjoy it.
Comments
Post a Comment