#过年不停更#HarmonyOS 基于JS封装渐变圆环进度条组件 原创 精华
春节不停更,此文正在参加「星光计划-春节更帖活动」
作者:杨尚晓
前言
圆环进度条组件在开发过程中是经常会用到的组件,比如在loading加载、升级过程,下载过程等等都需要用到。本文是基于HarmonyOS JSPAI开发,使用canvas画布封装的组件。方便直接引入上手使用。
效果展示
属性
属性名 | 类型 | 默认值 | 作用 |
---|---|---|---|
cWidth | Number | 200 | 外环宽度 |
cHeight | Number | 200 | 外环高度 |
staticScale | Number | 4 | 缩放级,值越大,越清晰,渲染压力越大 |
cRate | Number | 0 | 当前进度 |
lineWidth | Number | 20 | 圆环宽度 |
cColor | String | #86C1FF,#2B5BF9 | 进度颜色(必须是hex),当只有一个颜色值时为纯色进度,最多只支持两个颜色,使用半角逗号分开 |
bgColor | String | #e9ebed | 圆环背景颜色 |
text | String | - | 显示的文本 |
textSize | Number | - | 显示的文本字体大小 |
对应组件传入的prop参数
调用组件
实现原理
我们知道,在canvas中可以实现线性渐变和径向渐变,但是这些渐变都不够美观并且无法实现根据圆环方向线性渐变。
本文通过将圆环弧切片成若干等分绘制指定的颜色来实现的。
下面拆分各个步骤
- 创建canvas对象并且设置canvas大小
- 使用canvas的arc() API绘制一个圆充当圆环背景,给lineWidth设置圆环宽度的值
- 计算两个颜色之间的渐变颜色值。确定需要切片的精度,来确定渐变颜色值之间的差级。
- 在原来的背景圆环上,再绘制一个圆弧,圆弧是根据开始位置和结束位置,然后绘制一段圆弧之间的所有切片
1. 初始化canvas
这里需要有个关键点,getContext(contextType, contextAttributes)方法可以传入两个参数
- contextType 上下文类型 可选 2d、webgl
- contextAttributes 上下文属性
注意:在HarmonyOS 的JSPAI官网文档没有提到这两个属性,但是案例上有看到const ctx = el.getContext('2d', { antialias: true });
这样一句话。这里似乎跟webAPI的有些区别。
antialias属性是设置是否开启抗锯齿,但是在webAPI中,只有在上下文类型为webgl的时候才有这个属性。
先写个canvas标签
再初始化canvas对象
2. 绘制背景圆环
通过canvas的arc(x,y,r,sAngle,eAngle,counterclockwise)方法绘制一个圆
参数值
参数 | 描述 |
---|---|
x | 圆的中心的 x 坐标。 |
y | 圆的中心的 y 坐标。 |
r | 圆的半径。 |
sAngle | 起始角,以弧度计(弧的圆形的三点钟位置是 0 度)。 |
eAngle | 结束角,以弧度计。 |
counterclockwise | 可选。规定应该逆时针还是顺时针绘图。False = 顺时针,true = 逆时针。 |
在canvas绘制圆的其实位置是在x+r的位置开始,完整的圆弧为2PI。因为我们要在最顶端开始绘制,所以我们的开始位置是1.5PI,而我们的结束位置就不是2PI了,而是1.5PI + 2 * PI,这个才是绘制的完整的一个圆弧。最后
上面代码我们这里绘制了一个圆心坐标在(100,100),半径为100,边框为20,边框颜色为 #ff9800的圆环
3. 实现圆弧切片绘制方法
3.1. 获取两颜色之间的渐变值组
- 首先我们需要把获取到的hex色值转换成rgb三原色值,
- 然后通过计算开始颜色和结束颜色总差值来获取每一步的颜色值,
- 最后再转换成hex设置
将hex色值转换成rgb三原色值方法
通过计算开始颜色和结束颜色总差值来获取每一步的颜色值
将rgb三原色值转换成hex色值方法
3.2. 开始绘制一段圆弧之前的渐变值
这里有个渐变精度unit,这个值确定了我们渐变之间的缓和度,比如一段100像素的长方形,我们每一个像素绘制一个颜色,和每10个像素绘制一个颜色,效果是不一样的。
因为我们需要绘制的整个圆弧是2 * PI ≈ 6.28318;那么就是说在开始颜色到结束颜色之间需要绘制长达6.28318的长度,这里设置unit = 0.01;就是每0.01个圆弧里绘制一个颜色。这样大约需要绘制6.28318 / 0.01 ≈ 628个渐变颜色就可以了,把两个颜色之间色值拆分成628个色值组,会让渐变更缓和,当然还可以调整更多,但是这样也会导致渲染压力正大,耗时,耗性能,而且在手机上其实也看不出更细的区别来。
每次绘制的时候,需要记录当前上一次绘制的结束位置,作为下一次绘制的开始位置,这样子就不需要每次绘制都从头开始,也可以拼接起来。
最后附上hml、css代码
hml文件
css文件
最后再来看一下效果:
总结
在开发过程中也遇到了一些坑,比如SDK版本问题:在SDK version7的时候渲染没有问题,但是IDE预览器经常崩溃掉。后来改回SDK6就好了。
以往在开发vue的时候,会直接把canvas对象赋值到data函数里,方便其他方法直接调用,但是在这里却发现不行。最后发现这里data并非是一个函数,而是一个对象,这里还没有深入研究。
在使用组件的时候未必一定需要使用text属性,可以使用slot插槽实现多样文本显示。
源码
更多原创内容请关注:中软国际 HarmonyOS 技术团队
入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。
这方法真是太厉害了吧,高实在是高。
可以,很nice
太实用了
尚晓老师太强了