Hanim+Imgui动画控件设计 - Loading动画控件

Loading动画控件

基本介绍

控件效果

一个滑动块来回运动的加载动画控件

控件接口

cpp 复制代码
static void Loading(
    const char *text, HVec2 pos, HVec2 wh,
    unsigned int frameNums = 120,
    ImVec4 color = ImVec4(0.9, 0.9, 0.9, 0.5),
    ImVec4 background = ImVec4(0.2, 0.6, 0.9, 1)
)
  • text: 控件文本
  • pos: 控件(左上角)位置
  • wh: 控件的宽和高
  • frameNums: 控件滑动块移动动画单趟的帧数
  • color: 滑动块的颜色
  • background: 控件的底色/背景色

控件元素与动画

基本元素

  • 一个矩形背景
  • 一个文本
  • 一个与背景等高的滑动块

动画

  • 往返运动 的位移动画

设计与实现

基本元素

矩形背景

cpp 复制代码
// Canvas()指向当前窗口区域
// draw bg
Canvas().addRectFilled(pos, pos + wh, ImColor(background));

使用pos作为左上顶点, pos + wh 作为右下顶点, background做为填充色绘制背景矩形

文本

cpp 复制代码
// draw text
ImVec2 textSize = ImGui::CalcTextSize(text);
auto textPos = pos + HVec2{(wh.x - textSize.x) / 2, (wh.y - textSize.y) / 2};
ImGui::SetCursorPosX(textPos.x);
ImGui::SetCursorPosY(textPos.y);
ImGui::Text(text);

使用ImGui::CalcTextSize获取文本的大小(包围盒的W和H), 用控件(背景矩形)的wh计算出文本的相对坐标, 再加上控件坐标pos, 得到最终的文本坐标textPos

获取文本坐标后, 使用ImGui::SetCursorPosX 和 ImGui::SetCursorPosY 设置文本控件坐标, 再使用ImGui::Text进行显示(绘制)

滑动块

复制代码
float blockWidth = wh.x * 0.2;
//....
Canvas().addRectFilled(pos, pos + HVec2{blockWidth, wh.y}, ImColor(color));

它和背景一样使用addRectFilled绘制一个与背景矩形等高,且宽度为0.2倍(blockWidth)的小的填充矩形, 但是这里滑动块的pos需要动态更新, 下面将介绍动态更新方法。

位移动画与滑动块

cpp 复制代码
auto anim = HEngine::AManager::registerAnimate<hanim::Move>(
    pos, pos + HVec2{wh.x - blockWidth, 0},
    HAnimate::Config {
        .playType = hanim::HAnimate::PlayType::RT,
        .frameNums = frameNums
    }
);

使用HEngine::AManager::registerAnimate注册一个移动动画, 从pospos + HVec2{wh.x - blockWidth, 0}; 高度保持不变, 水平移动距离为控件的宽减去滑动块的宽度。

同时把动画的播放类型配置为PlayType::RT,实现目标对象的往返运动

cpp 复制代码
if (auto animPtr = anim.lock()) {
    HEngine::PlayFrame(
        *animPtr,
        [ & ](int type, const hanim::IAFrame &frame) {
            auto pos = HVec2{frame.data[0], frame.data[1]};
            Canvas().addRectFilled(pos, pos + HVec2{blockWidth, wh.y}, ImColor(color));
        }
    );
}

这里使用HEngine::PlayFrame把动画和滑动块进行结合, 生成按帧播放的动画

其中, *animPtr 为前面创建的移动动画 , [ & ](int type, const hanim::IAFrame &frame) {...} 为具体要渲染的对象, 根据每一帧到lambda表达式的插值动画数据实现动态的更新滑动块的坐标, 进而形成滑动块往返运动的效果

综合上面的代码, 就可以得到一个简单动画控件Loading的实现了

核心接口(API)列表

Hanim

接口 简述
Canvas() 对ImGui的drawList的封装, 简化当前窗口绘制区域的步骤
HEngine::AManager::registerAnimate 用于进行注册并创建动画, 返回对应动画的指针(std::weak_ptr)
arduino hanim::Move(pos1, pos2, config) 创建位移动画的接口/对象
arduino HAnimate::Config 动画基础属性配置类型
arduino HEngine::PlayFrame(animate, hobj) 把anim动画作用到hobj对象上, 可以使用lambda表达式做为临时对象
arduino std::function<void (int, const IAFrame &)> 插值动画lambda表达式的签名要求类型

ImGui

接口 简述
DrawList->AddRectFilled(...) 绘制带填充色的矩形
ImGui::CalcTextSize(text) 计算文本的大小
ImGui::SetCursorPosX(.) / ImGui::SetCursorPosY(.) 设置下一个控件的坐标(当前窗口坐标视为(0,0))
ImGui::Text(text) 绘制文本

Other

代码仓库

文档仓库 ​ github.com/Sunrisepeak/hanim-docs

在线文档 ​ speaks-organization.gitbook.io/hanim+imgui-dong-hua-kong-jian-she-ji/

相关推荐
slim~7 小时前
CLion实现ini 解析器设计与实现
c++·后端·clion
AA陈超8 小时前
虚幻引擎5 GAS开发俯视角RPG游戏 P05-05 游戏效果委托
c++·游戏·ue5·游戏引擎·虚幻
杨小码不BUG8 小时前
Davor的北极探险资金筹集:数学建模与算法优化(洛谷P4956)
c++·算法·数学建模·信奥赛·csp-j/s
mit6.8248 小时前
10.5 数位dp
c++·算法
初圣魔门首席弟子8 小时前
C++ STL 向量(vector)学习笔记:从基础到实战
c++·笔记·学习
青草地溪水旁9 小时前
Visual Studio Code中launch.json深度解析:C++调试的艺术
c++·vscode·json
m0_552200829 小时前
《UE5_C++多人TPS完整教程》学习笔记62 ——《P63 多人游戏中的开火特效(Fire Effects in Multiplayer)》
c++·游戏·ue5
Moonbit9 小时前
MoonBit高校行 | 中大、深技大、深大、港科广回顾
后端·开源·编程语言
liu****9 小时前
基于websocket的多用户网页五子棋(九)
服务器·网络·数据库·c++·websocket·网络协议·个人开发
liu****9 小时前
基于websocket的多用户网页五子棋(八)
服务器·前端·javascript·数据库·c++·websocket·个人开发