HarmonyOS鸿蒙Next中怎么实现水波纹进度动画?
HarmonyOS鸿蒙Next中怎么实现水波纹进度动画? 主体为中间有水波纹效果的圆形控件,需要实现0->100->0的加载动画。
4 回复
效果图:

改进自:Circle显示不同进度水波纹。
核心代码:
const startAnimation = () => {
let v = 0; // 当前值 0-100
let dir = 1; // 步进方向:+1 或 -1
const tick = () => {
v += dir; // 先走一步
if (v === 0 || v === 100) {
dir *= -1;
} // 头尾掉头
this.outSetValue = v;
this.pathCommands = this.calPathCommands(v);
const delay = (v === 0 || v === 100) ? 500 : 40; // 头尾停 500ms,其余 40ms
setTimeout(tick, delay);
};
tick();
};
startAnimation();
完整代码:
const COLOR_TRANSPARENT = '#00000000';
const COLOR_BACKGROUND_FILL = '#007DFF';
const DIAMETER = 200;
const BIG_DIAMETER = 220;
@Entry
@ComponentV2
struct WaterRipplePage {
@Local outSetValue: number = 50;
@Local pathCommands: string = '';
private RADIUS_IN_PX: number = this.getUIContext().vp2px(DIAMETER / 2.0);
aboutToAppear() {
const startAnimation = () => {
let v = 0; // 当前值 0-100
let dir = 1; // 步进方向:+1 或 -1
const tick = () => {
v += dir; // 先走一步
if (v === 0 || v === 100) {
dir *= -1;
} // 头尾时掉头
this.outSetValue = v;
this.pathCommands = this.calPathCommands(v);
const delay = (v === 0 || v === 100) ? 500 : 40; // 头尾停 500ms,其余 40ms
setTimeout(tick, delay);
};
tick();
};
startAnimation();
}
calXSquare(y: number) {
return this.RADIUS_IN_PX * this.RADIUS_IN_PX - (y - this.RADIUS_IN_PX) * (y - this.RADIUS_IN_PX);
}
calY(k: number) {
return (1 - k) * this.RADIUS_IN_PX * 2;
}
formatPathCommands(x1: number, x2: number, y: number, radius: number) {
return `M${x1} ${y} A${radius} ${radius} 0 ${y > this.RADIUS_IN_PX ? 0 : 1} 0 ${x2} ${y} ` +
`Q${(x1 + 3 * x2) / 4} ${y + 12.5 * (x2 - x1) / radius}, ${(x1 + x2) / 2} ${y} T${x1} ${y}`;
}
calPathCommands(value: number): string {
let y = this.calY(value / 100.0);
let squareX = this.calXSquare(y);
if (squareX >= 0) {
let x = Math.sqrt(squareX);
let x1 = this.RADIUS_IN_PX - x;
let x2 = this.RADIUS_IN_PX + x;
return this.formatPathCommands(x1, x2, y, this.RADIUS_IN_PX);
}
return '';
}
build() {
Column() {
Stack() {
// 外框圆环
Circle({ width: BIG_DIAMETER, height: BIG_DIAMETER })
.fill(COLOR_TRANSPARENT)
.stroke(COLOR_BACKGROUND_FILL)
.strokeWidth(5);
// 进度显示
Circle({ width: DIAMETER, height: DIAMETER })
.fill(this.outSetValue == 100 ? COLOR_BACKGROUND_FILL : COLOR_TRANSPARENT);
Path()
.width(DIAMETER)
.height(DIAMETER)
.stroke(COLOR_BACKGROUND_FILL)
.commands(this.pathCommands)
.fill(COLOR_BACKGROUND_FILL);
// 进度
Text(this.outSetValue.toFixed(0) + '%')
.fontSize(60);
}
.width(BIG_DIAMETER)
.height(BIG_DIAMETER);
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center);
}
}
更多关于HarmonyOS鸿蒙Next中怎么实现水波纹进度动画?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
666
在HarmonyOS Next中,实现水波纹进度动画可以使用Canvas组件结合Path2D绘制贝塞尔曲线来模拟水波纹效果。通过Animator或关键帧动画改变波纹的相位偏移和振幅,形成动态进度。主要步骤包括:定义CanvasRenderingContext2D绘图上下文,使用bezierCurveTo绘制波形路径,并通过fill方法填充颜色。利用setInterval或requestAnimationFrame更新波纹的offsetX属性,结合进度值控制波纹宽度。
在HarmonyOS Next中实现水波纹进度动画,可以通过Canvas自定义绘制结合动画API来完成。以下是核心实现思路和关键代码示例:
1. 创建自定义组件
使用@Component定义自定义组件,通过CanvasRenderingContext2D进行波纹绘制:
@Component
export struct RippleProgress {
private settings: RenderingContextSettings = new RenderingContextSettings(true)
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
@State private progress: number = 0
@State private direction: number = 1 // 1表示增加,-1表示减少
}
2. 实现波纹绘制函数
在onDraw方法中绘制动态波纹效果:
onDraw(context: CanvasRenderingContext2D) {
// 清空画布
context.clearRect(0, 0, this.width, this.height)
// 绘制背景圆
context.beginPath()
context.arc(this.width/2, this.height/2, this.radius, 0, Math.PI * 2)
context.fillStyle = '#F0F0F0'
context.fill()
// 计算当前波纹半径(基于progress)
const rippleRadius = this.radius * (this.progress / 100)
// 绘制水波纹
context.beginPath()
context.arc(this.width/2, this.height/2, rippleRadius, 0, Math.PI * 2)
context.strokeStyle = `rgba(0, 150, 255, ${0.7 - (this.progress/100)*0.3})`
context.lineWidth = 3
context.stroke()
}
3. 添加动画控制
使用animateTo实现0→100→0的循环动画:
aboutToAppear() {
this.startAnimation()
}
private startAnimation() {
animateTo({
duration: 2000,
iterations: -1, // 无限循环
onStart: () => {
this.progress = 0
this.direction = 1
},
onUpdate: (value: number) => {
// 计算进度值
if (this.direction > 0) {
this.progress = value * 100
if (this.progress >= 100) {
this.direction = -1
}
} else {
this.progress = 100 - (value * 100)
if (this.progress <= 0) {
this.direction = 1
}
}
}
})
}
4. 布局中使用
@Entry
@Component
struct Index {
build() {
Column() {
RippleProgress()
.width(200)
.height(200)
}
}
}
关键点说明:
- 状态管理:使用
@State装饰器管理进度值和方向状态 - 动画控制:通过
animateTo的iterations: -1实现无限循环 - 性能优化:建议使用
Canvas的离屏渲染或LazyForEach处理复杂波纹效果 - 自定义扩展:可通过参数控制波纹颜色、速度、振幅等视觉效果
这种实现方式利用了HarmonyOS Next的声明式UI和动画能力,能够流畅地渲染水波纹动画效果。

