如何在ImGui中实现图片闪烁的告警效果?
实现ImGui图片告警闪烁的靠谱方案
别用计数器了,那玩意儿受帧率影响太大,闪得不稳定。直接用实时时间来控制闪烁,不管程序帧率多少,周期都稳。ImGui自带的ImGui::GetTime()能拿到程序运行的秒数,刚好用来做这个。
方案一:透明度闪烁(简单实用)
通过调整图片的透明度(alpha通道),让它在半透明和完全显示之间平滑过渡,效果柔和但明显:
// 设置闪烁周期,比如1秒完成一次亮暗循环 const float blinkCycle = 1.0f; // 计算当前相位,让它在0到2π之间循环 float phase = fmod(ImGui::GetTime() * 2 * IM_PI / blinkCycle, 2 * IM_PI); // 用余弦函数把相位转换成0.2到1之间的alpha值,实现平滑过渡 float alpha = 0.2f + (0.8f) * (cos(phase) + 1.0f) / 2.0f; // 绘制图片时传入计算好的alpha值 ImGui::Image((void*)(intptr_t)mImageTexture, ImVec2(Dp2Px(55), Dp2Px(55)), ImVec2(0, 0), ImVec2(1, 1), ImVec4(1, 1, 1, alpha));
方案二:颜色/纹理切换(告警感更强)
要是想要更扎眼的告警效果,直接切换颜色或者替换告警图片:
颜色切换示例
// 更快的切换周期,0.5秒完成一次切换 const float blinkCycle = 0.5f; // 判断当前处于闪烁的亮态还是暗态 bool isBlinkActive = fmod(ImGui::GetTime(), blinkCycle) < blinkCycle / 2; // 亮态用正常白色,暗态用半透明红色强化告警感 ImVec4 tintColor = isBlinkActive ? ImVec4(1,1,1,1) : ImVec4(1,0,0,0.8f); ImGui::Image((void*)(intptr_t)mImageTexture, ImVec2(Dp2Px(55), Dp2Px(55)), ImVec2(0, 0), ImVec2(1, 1), tintColor);
双纹理切换
如果有专门的告警状态图片,直接切换显示的纹理更直观:
const float blinkCycle = 0.5f; bool isBlinkActive = fmod(ImGui::GetTime(), blinkCycle) < blinkCycle / 2; // 切换显示正常图片还是告警图片 GLuint currentTexture = isBlinkActive ? mImageTexture : mAlarmImageTexture; ImGui::Image((void*)(intptr_t)currentTexture, ImVec2(Dp2Px(55), Dp2Px(55)));
为啥之前的计数器效果不好?
计数器是每帧加1,帧率高的时候闪得快,帧率低的时候闪得慢,完全不稳定。而用ImGui::GetTime()基于真实时间计算,不管帧率波动,闪烁周期都是固定的,效果自然就稳定了。
内容的提问来源于stack exchange,提问作者Gagan karanth
相关产品推荐
相关产品推荐

