VB.NET Windows Forms 中的图像过渡
使用 GDI+ 在 VB.NET 中实现图像过渡和视觉效果。
引言
本文演示了如何在 VB.NET 中实现简单的图像过渡。
过渡是幻灯片放映、商务演示、视频、屏幕保护程序中最常用的功能之一,通过过渡,开发人员可以使用简单且极少的代码来构建简单易用的网页/Windows Forms/视频视觉效果。
背景
您可能会发现很多文章演示如何使用 Silverlight 或 Dynamic HTML 实现图像过渡,但很少有文章讨论 C# 或 VB.NET Windows Forms 中的图像过渡……显然,图像过渡是一个很好的商机。
在本文中,我将尝试解释一些最受欢迎的图像过渡方法以及它们的实现方式。
过渡和视觉效果
下表列出了最受欢迎的图像视觉效果/过渡。您可以沿用相同的过渡名称,或根据您的方便重命名这些过渡。
- 卷帘式 (Barn):运动类似于门打开或关闭的效果
- 百叶窗式 (Blinds):运动看起来像打开或关闭百叶窗
- 棋盘式 (CheckBoard):方形排列,像棋盘或国际象棋棋盘
- 虹膜式 (Iris):运动类似于相机光圈的打开
- 淡入淡出式 (Fade):淡入淡出一个或两个图像
- 滑动式 (Slide):将部分或整个图像滑动到位
- 螺旋式 (Spiral):螺旋运动
过渡计时
System.Threading.Timer
类实现了一个简单轻量级的定时器,它使用回调函数。是的,它只有少数功能,但也有一些很好的优点,例如指定回调的方式、指定第一次运行回调前等待的时间,以及指定调用间隔时间。这些对于在过渡期间掌握 GDI+ 的速度和计算过渡的步骤非常重要。
此外,有些人可能更喜欢使用 System.Timers.Timer
类而不是 System.Threading.Timer
类,并将 Timer
类的 Elapsed
事件挂接起来以加速 GDI+。
以下简单代码演示了如何使用 System.Timers
类在窗体上绘制内容。
- 声明定时器
Private m_timer As New System.Timers.Timer()
Elapsed
事件并启用定时器(StartTimer
例程)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
事件触发时要执行的操作。Private Sub TimerTick(ByVal source As Object, _
ByVal e As System.Timers.ElapsedEventArgs)
Invalidate()
End Sub
Paint
事件中绘制内容。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
例程传递给 Form Load 事件并运行。Private Sub Form2_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
StartTimer(1000)
End Sub
以下代码演示了如何使用 System.Threading.Timer
在窗体上绘制内容,遵循上述相同步骤。
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)
以下代码示例演示了如何应用简单的垂直卷帘式过渡。
- 声明变量,如定时器、过渡步数和开始时间。
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
事件,初始化变量,并启用定时器(StartTimer
例程)。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
事件触发时要执行的操作。定义和计算已用时间,定义动画时间(值越小,速度越快),计算过渡步数并使控件失效以进行重绘。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
要绘制过渡效果,请按照以下步骤操作:
- 定义一个过渡位图。
- 定义一个过渡矩形。
- 通过定义目标矩形的上部来绘制卷帘式的上部效果。定义图像的上部源矩形,然后绘制图像的上部。
- 重复步骤 3,通过定义目标矩形的下部来绘制卷帘式的下部效果。定义图像的下部源矩形,然后绘制图像的下部。
- 将
StartTime
例程传递给 Form Load 事件并运行。 - 将时间间隔设置为 60 毫秒。
- 为了获得更好的性能,我认为间隔值不应超过 100 毫秒。值越小,性能越好。
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
如果我们混合以上两种卷帘式视觉效果(水平和垂直效果)会发生什么……!!!??? 我们会得到不同的效果……您可能称之为“卷帘式爆炸” (Barns Boom)!
以下代码示例演示了如何应用卷帘式爆炸过渡。
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)
Drawin2D.Matrix
类在旋转、放大和旋转图像等过渡效果中起着重要作用,以下步骤重点介绍了最大化视觉效果中使用的主要要点。
- 定义过渡位图
- 定义过渡矩形
- 定义和计算矩阵中使用的过渡缩放因子。
- 定义矩阵类并将缩放因子传递给它,效果将从矩形的中点开始。
- 将矩阵传递给 graphics 对象并绘制效果。
以下代码示例演示了如何应用放大过渡。
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
以下步骤重点介绍了旋转和旋转视觉效果使用的主要要点。
- 定义过渡位图
- 定义过渡矩形
- 定义和计算矩阵中使用的过渡缩放因子。
- 定义矩阵类并将缩放因子传递给它,效果将从矩形的中点开始。
- 定义旋转因子
- 将旋转因子传递给矩阵以旋转矩阵,并将
Drawing2D.MatrixOrder
值设置为Append
(对于旋转效果,只需将Drawing2D.MatrixOrder
值设置为Prepend
)。 - 将矩阵传递给 graphics 对象并绘制效果。
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
有关其他效果(大约有 28 种效果等着您去尝试)的更多详细信息,您可以下载附加到文章的文件。
动画控件 (The Animation Control)
- 动画控件文件
- AnimationTypes.vb:大约 28 种视觉效果/过渡的公共枚举。
- AnimationControl.vb:扩展
Control
类。 - 控件属性
AnimationSpeed
:用于设置动画速度;值越大,速度越慢。AnimationType
:用于设置Animationtypes
枚举。AnimatedImage
:用于设置视觉效果所需的图像。AnimatedFadeImage
:用于设置将与动画图像一起使用的淡入淡出图像。Opacity
,Transparent
,TransparenColor
:用于设置控件的透明度(有关更多详细信息,您可以参考我关于使用 GDI+ 的 VB.NET 透明控件的上一篇文章,可在 此处 找到)。
使用控件
构建 AnimationControl
并在您的窗体中使用它。以下简单代码演示了如何在 Windows Forms 中使用 AnimationControl
。
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
下载附件文件,进行尝试,您还可以添加自己的视觉效果……这既简单又有趣。尽情享受吧。
历史
- 2009 年 11 月 7 日:首次发布。