1.创建空白项目
2.Page文件夹下面新建Spin.ets文件,代码如下:
/*** SpinKit 风格的旋转加载动画组件。** @component* @param spinSize - 动画容器大小(必须为正数)* @param spinColor - 动画颜色(支持资源引用)** 示例:* ```ets* SpinOne({* spinSize: 60,* spinColor: '#FF0000'* })* ```*/// 定义关键帧动画配置接口 interface KeyframeItem {duration: number;curve: Curve;event: () => void; }// 动画整体配置接口(已存在) interface KeyframeAnimationConfig {iterations: number;delay: number; }// 更新动画状态的参数接口 interface AnimationUpdateParams {angle?: number;x?: number;y?: number; }@ComponentV2 export struct SpinOne {@Require @Param spinSize: number = 48; // 父组件必须传值,这里默认值不会实际生效@Require @Param spinColor: ResourceColor = '#209ED8';@Local angle: number = 0;@Local x: number = 0;@Local y: number = 0;private readonly ANIMATION_DURATION: number = 600;build() {Canvas().width(this.spinSize).height(this.spinSize).backgroundColor(this.spinColor).renderFit(RenderFit.CENTER).shadow(ShadowStyle.OUTER_DEFAULT_XS).rotate({perspective: this.spinSize,x: this.x,y: this.y,angle: this.angle}).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, { angle: 180, x: this.spinSize / 2, y: 0 }),this.createKeyframe(0, { angle: 0 }),this.createKeyframe(this.ANIMATION_DURATION, { angle: 180, x: 0, y: this.spinSize / 2 })]);}/*** 创建关键帧动画配置项* @param duration 动画持续时间* @param update 动画更新参数*/private createKeyframe(duration: number,update: AnimationUpdateParams): KeyframeItem {return {duration,curve: Curve.EaseInOut,event: () => {if (update.angle !== undefined) this.angle = update.angle;if (update.x !== undefined) this.x = update.x;if (update.y !== undefined) this.y = update.y;}};} }代码如下:
/*** SpinKit 风格的旋转加载动画组件。** @component* @param spinSize - 动画容器大小(必须为正数)* @param spinColor - 动画颜色(支持资源引用)** 示例:* ```ets* SpinOne({* spinSize: 60,* spinColor: '#FF0000'* })* ```*/// 定义关键帧动画配置接口
interface KeyframeItem {duration: number;curve: Curve;event: () => void;
}// 动画整体配置接口(已存在)
interface KeyframeAnimationConfig {iterations: number;delay: number;
}// 更新动画状态的参数接口
interface AnimationUpdateParams {angle?: number;x?: number;y?: number;
}@ComponentV2
export struct SpinOne {@Require @Param spinSize: number = 48; // 父组件必须传值,这里默认值不会实际生效@Require @Param spinColor: ResourceColor = '#209ED8';@Local angle: number = 0;@Local x: number = 0;@Local y: number = 0;private readonly ANIMATION_DURATION: number = 600;build() {Canvas().width(this.spinSize).height(this.spinSize).backgroundColor(this.spinColor).renderFit(RenderFit.CENTER).shadow(ShadowStyle.OUTER_DEFAULT_XS).rotate({perspective: this.spinSize,x: this.x,y: this.y,angle: this.angle}).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, { angle: 180, x: this.spinSize / 2, y: 0 }),this.createKeyframe(0, { angle: 0 }),this.createKeyframe(this.ANIMATION_DURATION, { angle: 180, x: 0, y: this.spinSize / 2 })]);}/*** 创建关键帧动画配置项* @param duration 动画持续时间* @param update 动画更新参数*/private createKeyframe(duration: number,update: AnimationUpdateParams): KeyframeItem {return {duration,curve: Curve.EaseInOut,event: () => {if (update.angle !== undefined) this.angle = update.angle;if (update.x !== undefined) this.x = update.x;if (update.y !== undefined) this.y = update.y;}};}
}
3.修改Index.ets文件,代码如下:
import { SpinOne } from './Spin';
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
build() {
Column() {
SpinOne({
spinSize: 60,
spinColor: '#FF0000'
})
}
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Center)
.height('100%')
.width('100%')
}
}
代码如下:
import { SpinOne } from './Spin';@Entry
@Component
struct Index {@State message: string = 'Hello World';build() {Column() {SpinOne({spinSize: 60,spinColor: '#FF0000'})}.alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.Center).height('100%').width('100%')}
}
4.运行项目,登录华为账号,需进行签名
5.动画效果如下: