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.動畫效果如下: