跳转至内容
  • 版块
  • 最新
  • 标签
  • 热门
  • Online Tools
  • 用户
  • 群组
折叠
品牌标识

D2Learn Forums

  1. 主页
  2. Blogs | 博客
  3. Sunrisepeak's Blog
  4. 如何使用ImGui中的DrawList制动一个动画控件? - Loading动画控件

如何使用ImGui中的DrawList制动一个动画控件? - Loading动画控件

已定时 已固定 已锁定 已移动 Sunrisepeak's Blog
imguicpphanimwidgetsanimations
4 帖子 2 发布者 223 浏览
  • 从旧到新
  • 从新到旧
  • 最多赞同
登录后回复
此主题已被删除。只有拥有主题管理权限的用户可以查看。
  • sunrisepeakS 离线
    sunrisepeakS 离线
    sunrisepeak d2learn-dev
    写于 最后由 编辑
    #1

    基本介绍

    控件效果

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

    hanim-loading.gif

    控件接口

    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: 控件的底色/背景色

    控件元素与动画

    基本元素

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

    动画

    • 往返运动 的位移动画

    设计与实现

    基本元素

    矩形背景

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

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

    文本

    // 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

    image.png

    获取文本坐标后, 使用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需要动态更新, 下面将介绍动态更新方法。

    位移动画与滑动块

    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注册一个移动动画, 从pos 到 pos + HVec2{wh.x - blockWidth, 0}; 高度保持不变, 水平移动距离为控件的宽减去滑动块的宽度。

    image (2).png

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

    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的实现了


    示例代码: https://github.com/Sunrisepeak/Hanim/blob/main/old_project/ImGui.hanim.hpp

    sky-littlestarS 1 条回复 最后回复
    1
    • sky-littlestarS 离线
      sky-littlestarS 离线
      sky-littlestar
      写于 最后由 编辑
      #2

      请问在滑块移动的过程中是先把滑块,通过父对象渲染的方式,把父对象还原,然后再通过计算滑块的坐标,重新在父对象上面绘制滑块来实现的吗?(还原父对象->计算滑块坐标->重新绘制滑块形成新的一帧),是这种方法吗?

      1 条回复 最后回复
      0
      • sky-littlestarS 离线
        sky-littlestarS 离线
        sky-littlestar
        在 回复了 sunrisepeak 最后由 编辑
        #3

        @sunrisepeak 在 如何使用ImGui中的DrawList制动一个动画控件? - Loading动画控件 中说:

        根据每一帧到lambda表达式的插值动画数据实现动态的更新滑动块的坐标

        请问这个具体的计算过程的怎样的呢?有相关的参考资料吗?

        sunrisepeakS 1 条回复 最后回复
        0
        • sunrisepeakS 离线
          sunrisepeakS 离线
          sunrisepeak d2learn-dev
          在 回复了 sky-littlestar 最后由 编辑
          #4

          @sky-littlestar

          https://github.com/Sunrisepeak/Hanim/blob/main/old_project/ImGui.hanim.hpp 这个里有具体实现

          动画数据是用相对坐标生成的(假设开始是(0, 0)), 渲染的时候根据父窗口做平移

          1 条回复 最后回复
          1

          • 登录

          • 没有帐号? 注册

          • 登录或注册以进行搜索。
          d2learn forums Powered by NodeBB
          • 第一个帖子
            最后一个帖子
          0
          • 版块
          • 最新
          • 标签
          • 热门
          • Online Tools
          • 用户
          • 群组