1.创建空白项目
2.Page文件夹下面新建Spin.ets文件,代码如下:
/** * TODO SpinKit动画组件 - DotPulse 三点脉冲动画 * author: CSDN-鸿蒙布道师 * since: 2025/05/13 */ @ComponentV2 export struct SpinSeven { // 参数定义 @Require @Param spinSize: number = 48; @Require @Param spinColor: ResourceColor = '#209ED8'; // 局部状态 @Local scale1: number = 1; @Local scale2: number = 0.5; @Local scale3: number = 0; build() { Row() { Canvas() .chunkStyle() .scale({ x: this.scale1, y: this.scale1 }) Canvas() .chunkStyle() .scale({ x: this.scale2, y: this.scale2 }) Canvas() .chunkStyle() .scale({ x: this.scale3, y: this.scale3 }) } .width(this.spinSize) .height(this.spinSize / 3) .onAppear(() => { this.startAnimation(); }); } /** * 启动无限循环的关键帧动画 */ private startAnimation(): void { const uiContext = this.getUIContext(); if (!uiContext) return; const keyframes1 = this.createKeyframes( (value: number) => { this.scale1 = value; }, [0, 1, 1] ); const keyframes2 = this.createKeyframes( (value: number) => { this.scale2 = value; }, [1, 0, 0.5] ); const keyframes3 = this.createKeyframes( (value: number) => { this.scale3 = value; }, [1, 0, 0] ); uiContext.keyframeAnimateTo( { iterations: -1, delay: 280 }, keyframes1 ); uiContext.keyframeAnimateTo( { iterations: -1, delay: 120 }, keyframes2 ); uiContext.keyframeAnimateTo( { iterations: -1, delay: 0 }, keyframes3 ); } /** * 创建通用的缩放动画关键帧序列 * @param updateFn 更新状态的方法 * @param values 要依次应用的 scale 值数组 */ private createKeyframes( updateFn: (value: number) => void, values: number[] ): Array<KeyframeState> { const keyframes: Array<KeyframeState> = []; values.forEach((value, index) => { keyframes.push({ duration: index === 0 || index === 2 ? 280 : 560, curve: Curve.Linear, event: (): void => { updateFn(value); } }); }); // 补充空帧用于节奏同步 keyframes.push({ duration: 280, event: (): void => {} }); return keyframes; } @Styles chunkStyle() { .height(this.spinSize / 3) .width(this.spinSize / 3) .borderRadius(this.spinSize / 3) .backgroundColor(this.spinColor) .shadow(ShadowStyle.OUTER_DEFAULT_XS) } }
代码如下:
/**
* TODO SpinKit动画组件 - DotPulse 三点脉冲动画
* author: CSDN-鸿蒙布道师
* since: 2025/05/13
*/
@ComponentV2
export struct SpinSeven {
// 参数定义
@Require @Param spinSize: number = 48;
@Require @Param spinColor: ResourceColor = '#209ED8';
// 局部状态
@Local scale1: number = 1;
@Local scale2: number = 0.5;
@Local scale3: number = 0;
build() {
Row() {
Canvas()
.chunkStyle()
.scale({ x: this.scale1, y: this.scale1 })
Canvas()
.chunkStyle()
.scale({ x: this.scale2, y: this.scale2 })
Canvas()
.chunkStyle()
.scale({ x: this.scale3, y: this.scale3 })
}
.width(this.spinSize)
.height(this.spinSize / 3)
.onAppear(() => {
this.startAnimation();
});
}
/**
* 启动无限循环的关键帧动画
*/
private startAnimation(): void {
const uiContext = this.getUIContext();
if (!uiContext) return;
const keyframes1 = this.createKeyframes(
(value: number) => { this.scale1 = value; },
[0, 1, 1]
);
const keyframes2 = this.createKeyframes(
(value: number) => { this.scale2 = value; },
[1, 0, 0.5]
);
const keyframes3 = this.createKeyframes(
(value: number) => { this.scale3 = value; },
[1, 0, 0]
);
uiContext.keyframeAnimateTo(
{ iterations: -1, delay: 280 },
keyframes1
);
uiContext.keyframeAnimateTo(
{ iterations: -1, delay: 120 },
keyframes2
);
uiContext.keyframeAnimateTo(
{ iterations: -1, delay: 0 },
keyframes3
);
}
/**
* 创建通用的缩放动画关键帧序列
* @param updateFn 更新状态的方法
* @param values 要依次应用的 scale 值数组
*/
private createKeyframes(
updateFn: (value: number) => void,
values: number[]
): Array<KeyframeState> {
const keyframes: Array<KeyframeState> = [];
values.forEach((value, index) => {
keyframes.push({
duration: index === 0 || index === 2 ? 280 : 560,
curve: Curve.Linear,
event: (): void => {
updateFn(value);
}
});
});
// 补充空帧用于节奏同步
keyframes.push({
duration: 280,
event: (): void => {}
});
return keyframes;
}
@Styles
chunkStyle() {
.height(this.spinSize / 3)
.width(this.spinSize / 3)
.borderRadius(this.spinSize / 3)
.backgroundColor(this.spinColor)
.shadow(ShadowStyle.OUTER_DEFAULT_XS)
}
}
3.修改Index.ets文件,代码如下:
import { SpinSeven } from './Spin'; @Entry @Component struct Index { @State message: string = 'Hello World'; build() { Column() { SpinSeven({ spinSize: 60, spinColor: '#FF0000' }) } .alignItems(HorizontalAlign.Center) .justifyContent(FlexAlign.Center) .height('100%') .width('100%') } }
代码如下:
import { SpinSeven } from './Spin';
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
build() {
Column() {
SpinSeven({
spinSize: 60,
spinColor: '#FF0000'
})
}
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Center)
.height('100%')
.width('100%')
}
}
4.运行项目,登录华为账号,需进行签名
5.动画效果如下: