983aaf0bb6234d87aeb4f772af3f21ff~noop.image?_iz=58558&from=article.jpg
过去,我们已经看到了一些HMI 显示器的一些惊人的图形功能,例如2021 年 5 月 10 日。我们还没有详细讨论的是透明度和(在几行代码的帮助下)褪色效果。那么,让我们仔细看看这个!(一如既往)有一个示例项目和解释的代码,以便您可以在自己的开发中使用这些技术。

在这种情况下,什么是透明度?
简而言之,透明度是不透明的反面。某些东西,例如屏幕组件,如果它完全隐藏它背后的所有东西,例如屏幕背景颜色或图片,则称为 100% 不透明。如果它根本不可见(但它在那里并且甚至可能对触摸事件做出反应)并且背景内容以 100% 的亮度发光,则称为 100% 透明。在这两种极端情况之间,所有程度的部分透明度都是可能的,例如 60% 的透明度将使 40% 的背景透过。
为了量化透明度,人们可以不使用百分比,而是使用简单的整数值来简化计算。在许多图形系统中,使用所谓的 Alpha 值。如果 alpha(.aph 属性)为 0,则组件是完全透明的。在另一端,alpha=127 给出了完全不透明的渲染。虽然这两个极端对于嵌入式处理器来说仍然很容易处理,但中间值需要一些计算。这就是为什么我们只在 Intelligent 或 P 系列 HMI 上找到 .aph 属性的原因。
要绘制具有部分透明度的像素,处理器不仅需要知道其 R、G 和 B 值,还需要知道相应背景像素的 R、G 和 B 值。然后,这是一系列数学运算,计算每个像素的分离的前景和背景颜色通道的加权和:
R_drawn = (alpha * R_foreground + (127 – alpha) * R_background)/127
  • G_drawn = (alpha * G_foreground + (127 – alpha) * G_background)/127
  • B_drawn = (alpha * B_foreground + (127 – alpha) * B_background)/ 127
  • 复制代码
    你看,它比简单地将相同像素的 RGB 值直接写入 LCD 屏幕缓冲区要复杂得多!

    淡入淡出
    当透明度(或 alpha 值)不是恒定的而是发生变化时,称为淡入淡出。Nextion 固件中没有此功能。因此,我们必须编写几行代码来实现 alpha=0 和 alpha=127(淡入)或反之(淡出)之间的平滑过渡。

    示例项目
    在我们的示例项目中,如上图所示,我们有 3 个按钮:“淡入”、“淡出”和“继续”。当你启动项目时,巨大的红色文本框“Fading…”是不可见的,它的 alpha 值默认为 0。点击“淡入”会慢慢出现。可以使用文本组件下方的滑块设置出现的速度。“淡出”的功能类似,但文本字段或多或少会慢慢消失。顾名思义,“连续”将不断淡入淡出文本,直到您按下其他按钮之一。

    它是如何工作的
    在program.s文件中,我们首先定义了几个变量,来控制我们的动画:“con”是连续的效果,它会被“Continuous”按钮设置为1,其他的都设置为0,这样后者的动作仍然是一次性的,这意味着动画将在达到完全不透明或完全透明时停止。“dir”是控制我们是增加(1)alpha值还是减少(-1)它。“cid”是要设置动画的组件的对象 ID。在动画代码中使用间接寻址 (b[cid].aph) 可以轻松地将文本字段与任何其他组件交换,而无需修改所有出现的 t0.aph。最后,我们将 sys0 声明为动画例程的内部缓冲区变量。
    int con=0 //0=once or 1=continuous
  • int dir=1 //1=fade in or -1=fade out
  • int cid=1 //component id to fade
  • int sys0   //内部临时变量
  • page 0
  • 复制代码
    所有三个按钮都具有相似的功能,这就是为什么我决定将它们的触摸事件代码打包到一个 TouchCap 组件中。“淡入”设置 dir=1(淡入),con=0(一次拍摄),并启用动画计时器。“淡出”设置 dir=-1(淡出),con=0(一次拍摄),并启用动画计时器。“Continuous”不会影响 dir 值,它会沿之前的方向继续,并且由于这次 con=1,当达到完全透明或不透明时,它会自动恢复方向。
    如果(tc0.val==3)
  • {
  •   con=0 //once
  •   dir=1 //fade in
  •   tm0.en=1 //start timer
  • } else  if (tc0.val==4)
  • {
  •   con=0 //once
  •   dir=-1 //淡出
  •   tm0.en=1 //启动计时器
  • } else  if (tc0.val==5)
  • {
  •   con=1 //continuous
  •   //dir 保持不变
  •   tm0.en=1 //启动定时器
  • }
  • 复制代码
    由这些变量和动画速度滑块控制的核心动画发生在 50 毫秒计时器内。首先,通过将 dir 与放入 sys0 的 h0.val 与当前 alpha 值 b[cid].aph 相乘来计算下一个 alpha 步骤。然后,必须区分不同的情况。如果保存理论下一个 alpha 值的 sys0 介于 0 和 127 之间,则不会执行所有 if() 子句,代码直接跳转到 b[cid].aph 获取其新值 sys0 的最后一行。
    但是在某些情况下,sys0 中计算的新 alpha 值会超过 127(假设它是 125,滑块设置为 5,因此下一步将是 130)并且会发生错误情况。为了防止这种情况,我们检查 sys0 是否 > 127 并将其限制或饱和到恰好 127。然后,由于我们处于最大值,我们检查是否启用了连续模式并恢复动画方向,或者如果没有,我们只需禁用计时器,因为达到了动画目标。
    执行类似的代码块以防止 alpha 低于 0。动画连续性或停止检查是相同的。
    sys0=h0.val*dir+b[cid].aph
  • if (sys0>127)
  • {
  •   系统0=127
  •   如果(con>0)
  •   {
  •     dir*=-1 //反向
  •   } else
  •   {
  •     tm0.en=0 //或停止
  •   }
  • } else  if (sys0<0)
  • {
  •   系统0=0
  •   如果(con>0)
  •   {
  •     dir*=-1 //反向
  •   } else
  •   {
  •     tm0.en=0 //或停止
  •   }
  • }
  • b[cid].aph=sys0
  • 复制代码
    就是这样。没有黑魔法,没有火箭科学,只有几行代码……
    此示例项目的 HMI 文件位于:
    drawing_with_transparency.HMI
    复制代码
    即使您手头没有 4.3 英寸智能系列 HMI 显示器,您也可以在调试器/模拟器中运行所有内容并在那里找到您的灵感。



    来源:电子资料库