【学习笔记】Windows GDI绘图(十三)动画播放ImageAnimator(可调速)

本文主要是介绍【学习笔记】Windows GDI绘图(十三)动画播放ImageAnimator(可调速),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 前言
  • 定义
  • 方法
    • CanAnimate 是否可动画显示
    • Animate 动画显示多帧图像
    • UpdateFrames
    • StopAnimate终止动画
    • Image.GetFrameCount 获取动画总帧数
    • Image.GetPropertyItem(0x5100) 获取帧延迟
  • 自定义GIF播放(可调速)

前言

在前一篇文章中用到ImageAnimator获取了GIF动画的一些属性,但没有真正使用ImageAnimator来进行GIF动画播放(还可能误导),所有这篇就深入了解ImageAnimator的使用。
本文使用的动画为另一篇文章 心动(GDI+) 使用 GDI+纯手工绘制生成,有兴趣的可以查看原文,并配原码。

定义

public sealed class ImageAnimator

作用:对具有基于时间帧的图像进行动画显示。

方法

CanAnimate 是否可动画显示

原型:

public static bool CanAnimate (System.Drawing.Image image);

作用:判断指定图像是否包含基于时间帧。

Animate 动画显示多帧图像

原型:

public static void Animate (System.Drawing.Image image, EventHandler onFrameChangedHandler);

作用:将多帧图像显示为动画。

UpdateFrames

原型:

public static void UpdateFrames ();
public static void UpdateFrames (System.Drawing.Image image);

作用:使多帧动画前推进,下次渲染时,使用新的图像。

1、加载一个动画Image.FromFile
2、判断该图像是基于时间帧的图像 CanAnimate
3、指定帧切换事件 Animate
4、推进多帧动画
5、绘制最新图像

private Image gifImg = null;
/// <summary>
/// 加载多帧图像
/// </summary>
private void LoadGif()
{gifImg = Image.FromFile("Heartbeat.gif");if (ImageAnimator.CanAnimate(gifImg)){ImageAnimator.Animate(gifImg, OnFrameChanged);}
}
//切换帧事件
private void OnFrameChanged(object o, EventArgs e)
{//强制显示this.paintCtrl_Main.Panel_Main.Invalidate();
}[System.ComponentModel.Description("ImageAnimator的Animate方法")]
public void Demo13_01(PaintEventArgs e)
{if (gifImg == null){LoadGif();}ImageAnimator.UpdateFrames(gifImg);e.Graphics.DrawImage(gifImg, 0, 0, this.paintCtrl_Main.Panel_Main.Width, this.paintCtrl_Main.Panel_Main.Height);
}

由以上代码,使用ImageAnimator加GDI+绘制,可以很容易实现GIF动画的播放。
Gif动画播放

StopAnimate终止动画

原型:

public static void StopAnimate (System.Drawing.Image image, EventHandler onFrameChangedHandler);

作用:停止动画显示。(实际上没有真正停止,还需要其他条件配合)

private Image gifImg = null;
EventHandler OnFrameChangedEventHandler;
/// <summary>
/// 加载多帧图像
/// </summary>
private void LoadGif()
{gifImg = Image.FromFile("Heartbeat.gif");if (ImageAnimator.CanAnimate(gifImg)){OnFrameChangedEventHandler = new EventHandler(OnFrameChanged);isStop = false;ImageAnimator.Animate(gifImg, OnFrameChangedEventHandler);this.paintCtrl_Main.Panel_Main.Click += PaintCtrl_Main_Click; ;}
}private void PaintCtrl_Main_Click(object sender, EventArgs e)
{if (isStop){ImageAnimator.Animate(gifImg, OnFrameChangedEventHandler);}else{ImageAnimator.StopAnimate(gifImage, OnFrameChangedEventHandler);}isStop = !isStop;
}private bool isStop = false;
private void OnFrameChangedStop(object o, EventArgs e)
{isStop = true;
}//切换帧事件
private void OnFrameChanged(object o, EventArgs e)
{//强制显示this.paintCtrl_Main.Panel_Main.Invalidate();
}[System.ComponentModel.Description("ImageAnimator的Animate方法")]
public void Demo13_01(PaintEventArgs e)
{if (gifImg == null){LoadGif();}if (!isStop){ImageAnimator.UpdateFrames(gifImg);}e.Graphics.DrawImage(gifImg, 0, 0, this.paintCtrl_Main.Panel_Main.Width,this.paintCtrl_Main.Panel_Main.Height);
}

通过鼠标点击,控制Gif动画开始,还是停止。

Image.GetFrameCount 获取动画总帧数

原型:

public int GetFrameCount (System.Drawing.Imaging.FrameDimension dimension);

作用:返回指定维度的帧数。

Image.GetPropertyItem(0x5100) 获取帧延迟

作用:返回每帧的延迟数

/// <summary>
/// 获取帧总数、帧延迟
/// </summary>
private void GetFrameDelays()
{//总帧数var frameCount = gifImg.GetFrameCount(FrameDimension.Time);var frameDelay = gifImg.GetPropertyItem(0x5100);//FrameDelay 帧延迟//var loopCount= gifImg.GetPropertyItem(0x5110);//LoopCount GIF循环计数byte[] values = frameDelay.Value;// 每个延迟时间占 4 个字节var frameDelays = new int[frameCount];for (int i = 0; i < frameCount; i++){frameDelays[i] = BitConverter.ToInt32(values, i * 4) * 10; // 单位是 1/100 秒,转换为毫秒}
}

自定义GIF播放(可调速)

使用ImageAnimator的Animate的速度由Gif内置的每帧时间延迟控制,具体可见GetFrameDelays函数示例。如果需要实现自定义速度播放,可使用Timer来控制播放速度。
1、使用Image.FromFile加载Gif动画
2、用ImageAnimator.CanAnimate判断是否为多帧动画
3、获取Gif动画的FrameDimension和总帧数
4、定义并启用一个Timer,设置Interval控制播放速度
5、设置Timer.Tick函数,切换当前帧数和强制控件刷新
6、设置控件MouseClick事件,左键timer.Interval减小,右键Interval加大
7、在Paint事件中SelectActiveFrame激活指定帧,然后绘制

[System.ComponentModel.Description("ImageAnimator的GIF动画播放可调速")]
public void Demo13_02(PaintEventArgs e)
{if (gifImg == null){LoadGif2();}if (FrameCount > 0){gifImg.SelectActiveFrame(dimension, currentFrame);e.Graphics.DrawImage(gifImg, 0, 0, gifImg.Width, gifImg.Height);e.Graphics.DrawString($"左键加速/右键减速 {1000 / GifTimer.Interval}帧/秒,当前帧:{currentFrame}", Font, Brushes.Red, new PointF(20, 20));}
}FrameDimension dimension;
/// <summary>
/// 加载多帧图像
/// </summary>
private void LoadGif2()
{gifImg = Image.FromFile("Heartbeat.gif");if (ImageAnimator.CanAnimate(gifImg)){dimension = new FrameDimension(gifImg.FrameDimensionsList[0]);FrameCount = gifImg.GetFrameCount(dimension);GifTimer = new Timer();GifTimer.Interval = 40;GifTimer.Tick += OnTick;GifTimer.Start();this.paintCtrl_Main.Panel_Main.MouseClick += Panel_Main_MouseClick;}
}
private int currentFrame = 0;
/// <summary>
/// 切换当前帧数
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnTick(object sender, EventArgs e)
{currentFrame = (currentFrame + 1) % FrameCount;this.paintCtrl_Main.Panel_Main.Invalidate();
}private Timer GifTimer;
//加/减速
private void Panel_Main_MouseClick(object sender, MouseEventArgs e)
{if (e.Button == MouseButtons.Right){GifTimer.Interval *= 2;}else{var interval = GifTimer.Interval / 2;if (interval < 1){interval = 1;}GifTimer.Interval = interval;}
}
int FrameCount = 0;

使用Timer控制Gif播放

这篇关于【学习笔记】Windows GDI绘图(十三)动画播放ImageAnimator(可调速)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1041359

相关文章

windows系统下shutdown重启关机命令超详细教程

《windows系统下shutdown重启关机命令超详细教程》shutdown命令是一个强大的工具,允许你通过命令行快速完成关机、重启或注销操作,本文将为你详细解析shutdown命令的使用方法,并提... 目录一、shutdown 命令简介二、shutdown 命令的基本用法三、远程关机与重启四、实际应用

Windows自动化Python pyautogui RPA操作实现

《Windows自动化PythonpyautoguiRPA操作实现》本文详细介绍了使用Python的pyautogui库进行Windows自动化操作的实现方法,文中通过示例代码介绍的非常详细,对大... 目录依赖包睡眠:鼠标事件:杀死进程:获取所有窗口的名称:显示窗口:根据图片找元素:输入文字:打开应用:依

最好用的WPF加载动画功能

《最好用的WPF加载动画功能》当开发应用程序时,提供良好的用户体验(UX)是至关重要的,加载动画作为一种有效的沟通工具,它不仅能告知用户系统正在工作,还能够通过视觉上的吸引力来增强整体用户体验,本文给... 目录前言需求分析高级用法综合案例总结最后前言当开发应用程序时,提供良好的用户体验(UX)是至关重要

javafx 如何将项目打包为 Windows 的可执行文件exe

《javafx如何将项目打包为Windows的可执行文件exe》文章介绍了三种将JavaFX项目打包为.exe文件的方法:方法1使用jpackage(适用于JDK14及以上版本),方法2使用La... 目录方法 1:使用 jpackage(适用于 JDK 14 及更高版本)方法 2:使用 Launch4j(

基于Python实现PDF动画翻页效果的阅读器

《基于Python实现PDF动画翻页效果的阅读器》在这篇博客中,我们将深入分析一个基于wxPython实现的PDF阅读器程序,该程序支持加载PDF文件并显示页面内容,同时支持页面切换动画效果,文中有详... 目录全部代码代码结构初始化 UI 界面加载 PDF 文件显示 PDF 页面页面切换动画运行效果总结主

windows端python版本管理工具pyenv-win安装使用

《windows端python版本管理工具pyenv-win安装使用》:本文主要介绍如何通过git方式下载和配置pyenv-win,包括下载、克隆仓库、配置环境变量等步骤,同时还详细介绍了如何使用... 目录pyenv-win 下载配置环境变量使用 pyenv-win 管理 python 版本一、安装 和

Python使用pysmb库访问Windows共享文件夹的详细教程

《Python使用pysmb库访问Windows共享文件夹的详细教程》本教程旨在帮助您使用pysmb库,通过SMB(ServerMessageBlock)协议,轻松连接到Windows共享文件夹,并列... 目录前置条件步骤一:导入必要的模块步骤二:配置连接参数步骤三:实例化SMB连接对象并尝试连接步骤四:

Qt QWidget实现图片旋转动画

《QtQWidget实现图片旋转动画》这篇文章主要为大家详细介绍了如何使用了Qt和QWidget实现图片旋转动画效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 一、效果展示二、源码分享本例程通过QGraphicsView实现svg格式图片旋转。.hpjavascript

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用