1.创建空白项目
2.Page文件夹下面新建Spin.ets文件,代码如下:
// ===== 接口定义(必须放在使用前)===== /** * 关键帧动画整体配置参数 */ interface KeyframeAnimationConfig { iterations: number; delay: number; } /** * 单个关键帧动画项 */ interface KeyframeItem { duration: number; curve: Curve; event: () => void; } /** * 动画状态更新参数 */ interface AnimationUpdateParams { scale1?: number; scale2?: number; } // ===== 接口定义结束 ===== /** * SpinKit 风格的弹性缩放加载动画组件。 * * @component * @param spinSize - 动画容器大小(必须为正数) * @param spinColor - 动画颜色(支持资源引用) * * 示例: * ```ets * SpinTwo({ * spinSize: 60, * spinColor: '#FF0000' * }) * ``` */ @ComponentV2 export struct SpinTwo { // 参数定义(父组件必须传入) @Require @Param spinSize: number = 48; @Require @Param spinColor: ResourceColor = '#209ED8'; // 局部状态 @Local scale1: number = 0; @Local scale2: number = 1; // 常量定义 private readonly ANIMATION_DURATION: number = 1000; build() { Stack() { Canvas() .scale({ x: this.scale1, y: this.scale1 }) .bounceStyle() Canvas() .scale({ x: this.scale2, y: this.scale2 }) .bounceStyle() } .width(this.spinSize) .height(this.spinSize) .onAppear(() => { this.startAnimation(); }); } /** * 启动无限循环的关键帧动画 */ private startAnimation(): void { const uiContext = this.getUIContext(); if (!uiContext) return; const animationConfig: KeyframeAnimationConfig = { iterations: -1, delay: 0 }; uiContext.keyframeAnimateTo(animationConfig, [ this.createKeyframe(this.ANIMATION_DURATION, { scale1: 1, scale2: 0 }), this.createKeyframe(this.ANIMATION_DURATION, { scale1: 0, scale2: 1 }) ]); } /** * 创建关键帧动画配置项 * @param duration - 动画持续时间 * @param update - 更新的状态对象 */ private createKeyframe( duration: number, update: AnimationUpdateParams ): KeyframeItem { return { duration, curve: Curve.EaseInOut, event: () => { if (update.scale1 !== undefined) this.scale1 = update.scale1; if (update.scale2 !== undefined) this.scale2 = update.scale2; } }; } /** * 公共样式封装 */ @Styles bounceStyle() { .width('100%') .height('100%') .opacity(0.6) .borderRadius(this.spinSize / 2) // 圆形效果 .backgroundColor(this.spinColor) } }
代码如下:
// ===== 接口定义(必须放在使用前)=====
/**
* 关键帧动画整体配置参数
*/
interface KeyframeAnimationConfig {
iterations: number;
delay: number;
}
/**
* 单个关键帧动画项
*/
interface KeyframeItem {
duration: number;
curve: Curve;
event: () => void;
}
/**
* 动画状态更新参数
*/
interface AnimationUpdateParams {
scale1?: number;
scale2?: number;
}
// ===== 接口定义结束 =====
/**
* SpinKit 风格的弹性缩放加载动画组件。
*
* @component
* @param spinSize - 动画容器大小(必须为正数)
* @param spinColor - 动画颜色(支持资源引用)
*
* 示例:
* ```ets
* SpinTwo({
* spinSize: 60,
* spinColor: '#FF0000'
* })
* ```
*/
@ComponentV2
export struct SpinTwo {
// 参数定义(父组件必须传入)
@Require @Param spinSize: number = 48;
@Require @Param spinColor: ResourceColor = '#209ED8';
// 局部状态
@Local scale1: number = 0;
@Local scale2: number = 1;
// 常量定义
private readonly ANIMATION_DURATION: number = 1000;
build() {
Stack() {
Canvas()
.scale({ x: this.scale1, y: this.scale1 })
.bounceStyle()
Canvas()
.scale({ x: this.scale2, y: this.scale2 })
.bounceStyle()
}
.width(this.spinSize)
.height(this.spinSize)
.onAppear(() => {
this.startAnimation();
});
}
/**
* 启动无限循环的关键帧动画
*/
private startAnimation(): void {
const uiContext = this.getUIContext();
if (!uiContext) return;
const animationConfig: KeyframeAnimationConfig = {
iterations: -1,
delay: 0
};
uiContext.keyframeAnimateTo(animationConfig, [
this.createKeyframe(this.ANIMATION_DURATION, { scale1: 1, scale2: 0 }),
this.createKeyframe(this.ANIMATION_DURATION, { scale1: 0, scale2: 1 })
]);
}
/**
* 创建关键帧动画配置项
* @param duration - 动画持续时间
* @param update - 更新的状态对象
*/
private createKeyframe(
duration: number,
update: AnimationUpdateParams
): KeyframeItem {
return {
duration,
curve: Curve.EaseInOut,
event: () => {
if (update.scale1 !== undefined) this.scale1 = update.scale1;
if (update.scale2 !== undefined) this.scale2 = update.scale2;
}
};
}
/**
* 公共样式封装
*/
@Styles
bounceStyle() {
.width('100%')
.height('100%')
.opacity(0.6)
.borderRadius(this.spinSize / 2) // 圆形效果
.backgroundColor(this.spinColor)
}
}
3.修改Index.ets文件,代码如下:
import { SpinTwo } from './Spin'; @Entry @Component struct Index { @State message: string = 'Hello World'; build() { Column() { SpinTwo({ spinSize: 60, spinColor: '#FF0000' }) } .alignItems(HorizontalAlign.Center) .justifyContent(FlexAlign.Center) .height('100%') .width('100%') } }
代码如下:
import { SpinTwo } from './Spin';
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
build() {
Column() {
SpinTwo({
spinSize: 60,
spinColor: '#FF0000'
})
}
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Center)
.height('100%')
.width('100%')
}
}
4.运行项目,登录华为账号,需进行签名
5.动画效果如下: