🎯 目标
封装一个经典的旋转加载组件 SpinLoader
,适用于:
-
页面加载、接口请求、提交处理过程中的等待反馈
-
可自定义图标(SVG / Emoji / 图片)
-
支持无限旋转、手动控制开始/暂停
-
可嵌套在按钮、卡片、全屏遮罩中使用
-
后续可扩展为组合动画(旋转+闪烁)、变速旋转、点击加速等效果
🧱 动效结构示意
🔄 图标围绕中心连续旋转(如刷新、加载中)
🧰 组件实现:SpinLoader.ets(无限旋转动画)
@Component
export struct SpinLoader {
@Prop size: number = 40
@Prop icon: string = '🔄'
@Prop duration: number = 800
@Prop autoStart: boolean = true
@State angle: number = 0
@State spinning: boolean = this.autoStart
aboutToAppear() {
if (this.spinning) {
this.rotateLoop()
}
}
build() {
Text(this.icon)
.fontSize(this.size)
.rotate({ angle: this.angle })
.animateTo({ duration: this.duration, curve: Curve.Linear })
}
private async rotateLoop() {
while (this.spinning) {
this.angle += 360
if (this.angle >= 360000) this.angle = 0 // 避免值过大
await this.sleep(this.duration)
}
}
private sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms))
}
public stop() {
this.spinning = false
}
public start() {
if (!this.spinning) {
this.spinning = true
this.rotateLoop()
}
}
}
📦 使用示例
@Entry
@Component
struct DemoSpinLoader {
@State loading: boolean = true
@State loaderRef: SpinLoader | null = null
build() {
Column({ space: 20 }).padding(20).alignItems(HorizontalAlign.Center) {
if (this.loading) {
SpinLoader({
size: 48,
icon: '⏳',
duration: 600,
autoStart: true,
}).bind(this, 'loaderRef')
Text('加载中...').fontSize(14).fontColor('#666')
} else {
Text('✅ 加载完成!').fontSize(16).fontColor('#28C76F')
}
Button(this.loading ? '停止加载' : '开始加载')
.onClick(() => {
this.loading = !this.loading
if (this.loading) {
this.loaderRef?.start()
} else {
this.loaderRef?.stop()
}
})
}
}
}
✨ 可扩展能力建议
功能 | 说明 |
---|---|
旋转方向控制(顺时针/逆时针) | 支持正负角度控制旋转方向 |
自定义 Loading 图标 | 使用图片、SVG 或 Lottie 动画自定义旋转对象 |
动画组合(旋转 + 缩放 / 跳动) | 添加缩放、透明度、放大缩小组合动画 |
状态联动:加载完成后替换内容 | 加载完成自动切换为结果组件或提示框 |
📘 下一篇预告
第19篇:【HarmonyOS 5.0.0 或以上】构建点击水波纹组件 RippleEffect:支持扩散半径 / 动态中心点 / 动画曲线配置