
#HarmonyOS NEXT 体验官# 长按组件颜色刷新 原创
需求描述
实现一个工具,可以帮助我们实现根据触摸时间来动态更新当前的颜色
原理讲解
ARGB
ARGB颜色字符串是一种用于表示颜色的编码方式,它结合了RGB色彩模式与Alpha(透明度)通道。
ARGB颜色字符串由四个部分组成,分别代表Alpha(透明度)、Red(红色)、Green(绿色)、Blue(蓝色)四个通道的值。每个通道的值通常用十六进制数表示,范围从00到FF(十六进制),对应于十进制中的0到255。因此,一个完整的ARGB颜色字符串看起来像这样:#AARRGGBB,其中AA是Alpha值,RR是红色值,GG是绿色值,BB是蓝色值。
渐变
在渐变中,A、R、G、B四个颜色通道的值会沿着渐变方向逐渐变化。例如,从红色(R:255, G:0, B:0)渐变到蓝色(R:0, G:0, B:255),则红色通道的值会逐渐减小,而蓝色通道的值会逐渐增加,绿色通道的值可能保持不变(取决于中间是否有绿色过渡)。
实现思路
- 定义起始和结束颜色:确定用户在未长按时的颜色(起始颜色)和长按时想要达到的颜色(结束颜色),长按到达结束颜色的时间。
- 颜色解析:将起始颜色 和 结束颜色相应的ARGB值进行重新解码,得到每个通道单独的ARGB值。
- 颜色线性插值计算:根据时间的变化,在两个指定的颜色之间平滑过渡。它首先计算了从某个起始时间到当前时间的差值,并将这个差值限制在一个指定的时间间隔内。然后,它使用线性插值方法来计算当前时间下应该显示的颜色的各个颜色通道(红、绿、蓝、透明度)的值。这些值可以用来在图形界面上动态地改变元素的颜色。
- 颜色编码:将拿到的十进制ARGB值重新编码成十六进制。
- 触摸事件:抓取触摸事件的按下和抬起事件,将记录手指触摸组件的时间点和手指离开组件的时间点。用来给颜色计算。并且定时刷新颜色
实现源码
1.定义起始和结束颜色:
2. 解析颜色
我们只需要将十六进制的ARGB的颜色通道进行切割,就可以得到每个独立的通道的十六进制值,下面是编写的十六进制切割转义函数。
3.颜色插值
根据时间的变化,在两个指定的颜色之间平滑过渡。它首先计算了从某个起始时间到当前时间的差值,并将这个差值限制在一个指定的时间间隔内。然后,它使用线性插值方法来计算当前时间下应该显示的颜色的各个颜色通道(红、绿、蓝、透明度)的值。
3.1 线性插值计算
3.2 线性插值计算
3.2.1. 这段代码的原理是基于时间插值来计算从一个颜色(startColor)到另一个颜色(endColor)的过渡色。它使用了一个时间间隔(timeInterval)来控制颜色过渡的速度,以及当前时间差(time)来确定在过渡过程中的位置。此外,它还通过插值函数(this.linearInterpolate)和颜色处理函数(如this.hexToNumber)来实现具体的颜色计算。以下是详细的原理描述:
3.2.2. 计算当前时间差:
首先,计算从触摸按下(downTime)到当前时间(nowTime)的时间差(time)。
然后,检查这个时间差是否超过了设定的时间间隔(timeInterval)。如果超过了,就将时间差设置为时间间隔的值,以确保颜色过渡不会超出设定的时间范围。
3.2.3. 颜色通道插值:
对于每个通道,代码首先设置颜色偏移量(colorDrift),它用于从颜色字符串(如#RRGGBB)中定位到当前要处理的通道的开始位置。
使用this.hexToNumber函数将颜色字符串中指定位置的十六进制颜色值转换为十进制数值。这个函数需要起始和结束位置的索引,这里通过colorDrift和colorDrift + 2来指定(因为每个颜色通道占用两个十六进制字符)。
然后,使用this.linearInterpolate函数进行线性插值。这个函数接收四个参数:当前时间差(time)、插值范围的起始值(0)、插值范围的结束值(timeInterval)、以及要插值的起始颜色和结束颜色的十进制值。它返回在指定时间差下,从起始颜色到结束颜色的过渡颜色的十进制值。
最后,对于每个通道,都会得到一个过渡颜色的十进制值(A、R、G、B)。
4. 颜色编码
颜色通道拼接原理
颜色代码格式:在Harmony开发中,颜色通常以十六进制代码的形式表示,格式为#AARRGGBB(对于ARGB颜色)。这里的RR、GG、BB和AA分别代表红色、绿色、蓝色和透明度通道的值,每个值都是一个两位的十六进制数。
拼接过程:为了生成这样的颜色代码,我们需要将每个颜色通道的值转换为十六进制字符串,并将它们按顺序拼接起来。首先,我们添加一个"#"作为前缀,然后依次拼接红色、绿色、蓝色(以及可能的透明度)通道的十六进制字符串。
函数调用:在上述代码中,numberToHex函数被用于将每个颜色通道的值转换为两位的十六进制字符串。这个函数接收颜色通道的值和期望的字符串长度(在这个场景下是2)作为参数,并返回转换后的字符串。然后,这些字符串被拼接起来以形成完整的颜色代码。
5.触摸事件
5.1. 时间追踪:
使用两个属性(downTime 和 nowTime)来追踪触摸事件的时间。downTime 记录触摸按下的时间,而 nowTime 用于记录当前时间或最后一次更新颜色的时间。
当触摸按下时(TouchType.Down),downTime 和 nowTime 被设置为当前时间。
当触摸抬起时(TouchType.Up),downTime 和 nowTime 被重置为0,表示触摸事件已结束。
5.2. 定时器使用:
在触摸按下时,设置一个定时器(通过 setInterval),该定时器以固定的频率(大约每秒61次)执行一个匿名函数。
这个匿名函数负责更新 nowTime 为当前时间,并调用 colorEvent 回调函数来报告基于 downTime 和 nowTime 计算出的新颜色。getColor 函数它使用这两个时间戳来计算并返回一个颜色值。
定时器的ID被存储在 intervalID 数组中,以便稍后可以清除它。
5.3. 定时器管理:
当触摸抬起时,遍历 intervalID 数组并使用 clearInterval 函数来清除每个定时器,以停止进一步的颜色更新。
清除所有定时器后,清空 intervalID 数组以避免内存泄漏。
颜色更新:
触摸按下时,通过定时器定期调用 colorEvent 来报告颜色的变化。
触摸抬起时,虽然 downTime 和 nowTime 被重置,但代码示例中在抬起之前或之后(取决于具体实现)仍然会调用一次 colorEvent 来报告一个最终颜色。
