如何将 GIF 动画播放到最后一帧,然后停止动画?

问题描述

在我的项目中,我想在 PictureBox 中播放 GIF。
我需要播放 GIF 动画包含的所有帧,然后停止动画。

我正在使用 ImageAnimator 类为 GIF 图像制作动画,我只是不知道如何停止它。

Private image As Image = My.Resources.icon_confirmation
'Private frames As Integer
Dim FDimensions As System.Drawing.Imaging.FrameDimension = New System.Drawing.Imaging.FrameDimension(image.FrameDimensionsList(0))
Dim frames As Integer = image.GetFrameCount(FDimensions)

Private Sub paintFrame(ByVal sender As Object,ByVal e As EventArgs)
    If frames < 33 Then PictureBox1.Image = image Else ImageAnimator.StopAnimate(image,AddressOf StopAnim)
End Sub

Private Sub StopAnim(ByVal sender As Object,ByVal e As EventArgs)
    PictureBox1.dispose()
End Sub

Private Sub PictureBox1_Paint(ByVal sender As Object,ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
    If frames = 12 Then
        ImageAnimator.UpdateFrames()
        e.Graphics.DrawImage(image,Point.Empty)
        frames -= 1
    End If
End Sub

GIF

解决方法

要跟踪在您的 PictureBox 上绘制的当前帧,您需要一个 Field 来存储当前进度并将其与动画包含的帧数进行比较。

当进度到达最后一帧(或最后一帧之前的任何其他帧,无论需要什么)时,您将停止调用 ImageAnimator.StopAnimate() 的动画。

要开始动画,您首先检查是否ImageAnimator.CanAnimate()(它可能无法为您指定的图像设置动画)。如果可以,则调用 ImageAnimator.Animate(),将 Image 对象和处理 FrameChanged 事件的方法的地址传递给方法。

这个处理程序用于检查动画是否应该继续。如果满足所有条件(并非所有帧都已绘制),Invalidate() 控件用于显示动画,并在其 Paint 事件处理程序中调用 ImageAnimator.UpdateFrames() 以更改当前帧,然后 e.Graphics.DrawImage() 绘制图像(绘制现在是当前的帧)。

▶ 正如您在可视化示例中看到的,我使用按钮 (btnAnimate) 来启动动画。如果您愿意,您可以将该代码移至 Form.Shown 事件处理程序。
▶ 我添加了一个循环计数器,以防动画应该循环多次。

视觉效果如下:

ImageAnimator Animate GIF

Imports System.Drawing.Imaging
' [...]

Private animation As Image = My.Resources.icon_confirmation
Private animationFrames As Integer = 0
Private currentFrame As Integer = 0
Private animationMaxLoops As Integer = 1
Private loops As Integer = 0

Private Sub btnAnimate_Click(sender As Object,e As EventArgs) Handles btnAnimate.Click
    animationFrames = animation.GetFrameCount(New FrameDimension(animation.FrameDimensionsList(0)))
    AnimateImage()
End Sub

Public Sub AnimateImage()
    If ImageAnimator.CanAnimate(animation) Then
        ImageAnimator.Animate(animation,AddressOf OnFrameChanged)
    End If
End Sub

Private Sub OnFrameChanged(o As Object,e As EventArgs)
    If currentFrame >= animationFrames Then
        currentFrame = 0
        loops += 1
        If loops >= animationMaxLoops Then
            animationFrames = 0
            loops = 0
            ImageAnimator.StopAnimate(animation,AddressOf OnFrameChanged)
        End If
    Else
        pictureBox1.Invalidate()
        currentFrame += 1
    End If
End Sub

Private Sub pictureBox1_Paint(sender As Object,e As PaintEventArgs) Handles pictureBox1.Paint
    If animationFrames > 0 Then
        ImageAnimator.UpdateFrames()
        e.Graphics.DrawImage(animation,Point.Empty)
    End If
End Sub

使用项目资源中的图像执行动画的 PasteBin of a complete Form