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
在HarmonyOS鸿蒙Next中,可通过ArkUI的Canvas组件绘制进度水波纹动画。使用CanvasRenderingContext2D的API,结合正弦函数计算波纹路径,并通过requestAnimationFrame逐帧更新绘制位置与透明度,形成动态效果。关键步骤包括定义波纹参数、实现绘制函数以及控制动画循环。
在HarmonyOS Next中实现进度水波纹动画,可以通过Canvas绘制结合动画API完成。以下是核心实现步骤:
-
创建Canvas组件:在ArkUI中使用
Canvas组件作为绘制容器。Canvas(this.context) .width('100%') .height('100%') -
绘制水波纹:通过
Path2D绘制贝塞尔曲线模拟波纹,使用gradient填充实现渐变效果。// 创建路径 const path = new Path2D(); path.moveTo(startX, startY); // 添加贝塞尔曲线形成波纹 path.bezierCurveTo(...); // 创建线性渐变 const gradient = this.context.createLinearGradient(...); this.context.fillStyle = gradient; this.context.fill(path); -
实现动画循环:利用
requestAnimationFrame更新波纹相位和高度,形成动态效果。let progress = 0; let direction = 1; const animate = () => { // 更新进度值(0->100->0循环) progress += direction * speed; if (progress >= 100 || progress <= 0) direction *= -1; // 计算波纹参数并重绘 redrawWaves(progress); requestAnimationFrame(animate); }; -
性能优化:使用
OffscreenCanvas进行离屏渲染,避免主线程阻塞。通过willReadFrequently属性提升渲染效率。
关键点:
- 通过正弦函数控制波纹形状:
y = amplitude * sin(frequency * x + phase) - 使用多层波纹叠加增强视觉效果
- 通过
opacity和颜色渐变实现自然过渡
完整实现需结合具体进度值动态计算波纹振幅、频率和相位偏移量。动画平滑度可通过调整帧率和插值函数进一步优化。


