下面是对渐变与动画的一个经验记录。
一.如何实现一个类似心跳的动画效果。
这其实有两个注意点,类似心跳的效果,需要动画变换到一定尺寸后,又从当前尺寸变换回之前的尺寸,如此循环往复。
private imageAnimator: AnimatorResult | undefined = undefined
@State strokeWidth: number = 3
/// 在fill属性和direction属性的同时配合下,就可以实现
createImageAnimation() {
this.imageAnimator = Animator.create({
duration: 700,
easing: "linear",
delay: 0,
fill: "forwards",/// 在动画结束后,目标将保留动画结束时的状态,在最后一个关键帧中定义(也就是每次动画结束后,保留当时的状态和尺寸)
direction: "alternate",/// 动画交替循环播放,奇数次正向播放,偶数次反向播放。
iterations: -1,/// 无限次循环播放.
begin: 7,///从7开始播放
end: 15, ///播到15结束
})
this.imageAnimator!.onFrame = (value: number) => {
this.strokeWidth = value
}
}
运行效果就是一个圆环的曲线宽度在不断的向外扩大或者缩小.
二.如何实现一个从上到下渐变的圆环
我为什么说是一个从上到下渐变的圆环呢?我了解到现在鸿蒙的情况是,要实现一个渐变的圆环效果,在鸿蒙中是需要取巧去实现的,有一个叫做"DataPanel"的组件可以取巧实现,要不最快的你找UI要一张圆环图片。
好的,话说回来,实现一个从上到下或者说从下到上,或者说从左到右,或者说从右到左的圆环渐变.
private settings: RenderingContextSettings = new RenderingContextSettings(true)
/// 我们使用Canvas来绘制圆环.
private circleContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
/// 设置圆环画笔的宽度.
private circleContextLineWidth:number = 7
build() {
Stack(){
/// 使用Canvas绘制
Canvas(this.circleContext)
.width(110)
.height(110)
.onReady(() => {
/**
* 1.在此生命周期中,宽高已经确定,可以使用this.circleContext.width和
this.circleContext.width / 2等值.
2.这里使用线性渐变createLinearGradient,在整个Canvas中,它是一个矩形。
所以不管你怎么做,它只可能从四个方向上进行渐变,不可能从圆的0角度开始到第360度进行渐变,可以使用另外一种角度渐变的方式。
3.createLinearGradient线性渐变的四个参数就是:前两个参数是开始渐变的位置坐标,后两个参数是结束渐变的位置坐标。
4.这里是从正中间的上方渐变到正中间的下方。
*/
let gradient =
this.circleContext.createLinearGradient(this.circleContext.width / 2, 0, this.circleContext.width / 2,
this.circleContext.height)
gradient.addColorStop(0, 'rgba(54, 119, 242, 0.4)')
gradient.addColorStop(0.4, 'rgba(54, 119, 242, 0.5)')
gradient.addColorStop(0.5, 'rgba(54, 119, 242, 0.6)')
gradient.addColorStop(0.6, 'rgba(54, 119, 242, 0.7)')
gradient.addColorStop(0.7, 'rgba(54, 119, 242, 0.8)')
gradient.addColorStop(0.8, 'rgba(54, 119, 242, 0.9)')
gradient.addColorStop(0.9, 'rgba(54, 119, 242, 0.95)')
gradient.addColorStop(1, 'rgba(54, 119, 242, 1)')
this.circleContext.strokeStyle = gradient
/// 线条宽度
this.circleContext.lineWidth = this.circleContextLineWidth
/// 使用arc函数进行绘制圆形路径,需要注意的是对于圆形半径的计算!
/// 需要减去的是线条宽度的一半,如果不相减this.circleContext.width / 2是整个Canvas绘图组件的一半,以它为半径会超出。
/// 在有线条宽度的情况下,计算机认为的半径是:从线条宽度的中心点到圆心的距离,即为半径。
this.circleContext.arc(this.circleContext.width / 2, this.circleContext.height / 2,
this.circleContext.width / 2 - this.circleContextLineWidth / 2, 0, Math.PI*2 )
this.circleContext.stroke()
})
Column(){
Text('58')
.fontColor(Color.Black)
.fontSize(30)
.fontWeight(FontWeight.Bold)
Text('次/秒')
.fontColor(Color.Black)
.fontSize(20)
.fontWeight(FontWeight.Regular)
}
.justifyContent(FlexAlign.Start)
}
.align(Alignment.Center)
.width(118)
.height(118)
.borderRadius(118/2)
.backgroundColor(Color.White)
.shadow({ radius: 10, color: 'rgba(154, 154, 154, 0.55)' })
}
运行的效果图如下:
三.实现圆环从角度上的渐变
1.找UI要一张圆环图片,快捷、高效、无Bug.
2.使用数据组件“DataPanel”,在其中只设置一个数据值,并且该数据占满它的整个max,然后设置它的 valueColors属性为LinearGradient类型的颜色数组,即可实现单一的渐变圆环,但是当它出现的时候,它会有一个动画在那里.
/// 需要渐变的颜色数组.
public gradientColors: LinearGradient = new LinearGradient(
[
{ color: "rgba(45, 152, 248, 0)", offset: 0 },
{ color: "rgba(45, 152, 248, 1)", offset: 0.5 },
{ color: "rgba(82, 65, 230, 1)", offset: 1 },
],
)
@State colorArray: Array<LinearGradient | ResourceColor> = [this.gradientColors]
build() {
DataPanel(
{
values: [99.99,], /// 当前数据为99.99几乎占满.
max: 100, /// 数据最大值为100
type: DataPanelType.Circle, /// 设置为圆环
})
.width(110)
.height(110)
.valueColors(this.colorArray) /// 设置各数据段颜色.
.trackShadow(null) /// 投影样式:设置null为不开启投影.
.strokeWidth(10) /// 设置圆环粗细
.trackBackgroundColor('#08182431') /// 底板颜色
// 设置组件的旋转.
// .rotate({
// x: 0,
// y: 0,
// z: 1,
// centerX: '50%',
// centerY: '50%',
// angle: 90
// })
}
3.使用角度渐变
Stack(){
Row()
.width(110)
.height(110)
.borderRadius(55)
.sweepGradient({
center:[55,55],/// 角度渐变的中点.
start:0,/// 开始角度.
end:360,/// 结束角度,注意这里不要使用数学函数Math.PI,因为这里角度口径不太一样。Math.PI的值才圆周律大小。
colors:[
[Color.Red,0],
[Color.Yellow,0.25],
[Color.Blue,0.5],
[Color.Green,0.75],
[Color.Orange,1]
]
})
/// 白色占位覆盖,
Row()
.width(90)
.height(90)
.borderRadius(45)
.backgroundColor(Color.White)
}
效果如下