鸿蒙NEXT开发动画案例10

[复制链接]
发表于 2025-5-31 05:48:35 | 显示全部楼层 |阅读模式
 1.创建空白项目


2.Page文件夹下面新建Spin.ets文件,代码如下:


  1. interface TranslateOffset {
  2.   x?:number
  3.   y?:number
  4. }
  5. /**
  6. * SpinKit动画组件 - SpinTen
  7. * author: CSDN-鸿蒙布道师
  8. * since: 2025/05/16
  9. */
  10. @ComponentV2
  11. export struct SpinTen {
  12.   @Require @Param spinSize: number = 36;
  13.   @Require @Param spinColor: ResourceColor;
  14.   @Local scaleSize: number = this.spinSize * 0.75;
  15.   @Local tran1: number = 0;
  16.   private oldSize: number = this.spinSize;
  17.   aboutToAppear(): void {
  18.     this.oldSize = this.spinSize;
  19.     this.scaleSize = this.spinSize * 0.75;
  20.   }
  21.   build() {
  22.     Stack() {
  23.       Grid() {
  24.         // 使用循环构建9个 GridItem
  25.         ForEach([0, 1, 2, 3, 4, 5, 6, 7, 8], (index: number) => {
  26.           GridItem() {
  27.             Canvas()
  28.               .chunkStyle()
  29.           }
  30.           .translate(this.getTranslateOffset(index))
  31.         })
  32.       }
  33.       .rowsTemplate('1fr 1fr 1fr')
  34.       .columnsTemplate('1fr 1fr 1fr')
  35.       .width(this.scaleSize)
  36.       .height(this.scaleSize)
  37.     }
  38.     .width(this.oldSize)
  39.     .height(this.oldSize)
  40.     .alignContent(Alignment.Center)
  41.     .onAppear(() => {
  42.       this.startAnimation();
  43.     })
  44.   }
  45.   // 抽取 translate 偏移量计算逻辑
  46.   getTranslateOffset(index: number): TranslateOffset {
  47.     switch (index) {
  48.       case 0: return { x: this.tran1 };
  49.       case 1: return { x: this.tran1 };
  50.       case 2: return { y: this.tran1 };
  51.       case 3: return { y: -this.tran1 };
  52.       case 4: return {}; // 中间项无偏移
  53.       case 5: return { y: this.tran1 };
  54.       case 6: return { y: -this.tran1 };
  55.       case 7: return { x: -this.tran1 };
  56.       case 8: return { x: -this.tran1 };
  57.       default: return {};
  58.     }
  59.   }
  60.   // 启动 Keyframe 动画
  61.   startAnimation(): void {
  62.     this.getUIContext().keyframeAnimateTo({ iterations: -1, delay: 0 }, [
  63.       {
  64.         duration: 500,
  65.         curve: Curve.EaseInOut,
  66.         event: () => {
  67.           this.tran1 = 0;
  68.           this.scaleSize = this.oldSize * 1.1;
  69.         }
  70.       },
  71.       {
  72.         duration: 190,
  73.         curve: Curve.Linear,
  74.         event: () => {
  75.           this.tran1 = this.oldSize / 3;
  76.         }
  77.       },
  78.       {
  79.         duration: 0,
  80.         curve: Curve.Linear,
  81.         event: () => {
  82.           this.tran1 = 0;
  83.         }
  84.       },
  85.       {
  86.         duration: 10,
  87.         curve: Curve.Linear,
  88.         event: () => {}
  89.       },
  90.       {
  91.         duration: 500,
  92.         curve: Curve.EaseIn,
  93.         event: () => {
  94.           this.scaleSize = this.oldSize * 0.75;
  95.           this.tran1 = 0;
  96.         }
  97.       }
  98.     ]);
  99.   }
  100.   @Styles
  101.   chunkStyle() {
  102.     .width(this.oldSize * 0.25)
  103.     .height(this.oldSize * 0.25)
  104.     .backgroundColor(this.spinColor)
  105.     .shadow(ShadowStyle.OUTER_DEFAULT_XS)
  106.   }
  107. }
复制代码
  1. <strong>代码如下:</strong>
复制代码
  1. interface TranslateOffset {
  2.   x?:number
  3.   y?:number
  4. }
  5. /**
  6. * SpinKit动画组件 - SpinTen
  7. * author: CSDN-鸿蒙布道师
  8. * since: 2025/05/16
  9. */
  10. @ComponentV2
  11. export struct SpinTen {
  12.   @Require @Param spinSize: number = 36;
  13.   @Require @Param spinColor: ResourceColor;
  14.   @Local scaleSize: number = this.spinSize * 0.75;
  15.   @Local tran1: number = 0;
  16.   private oldSize: number = this.spinSize;
  17.   aboutToAppear(): void {
  18.     this.oldSize = this.spinSize;
  19.     this.scaleSize = this.spinSize * 0.75;
  20.   }
  21.   build() {
  22.     Stack() {
  23.       Grid() {
  24.         // 使用循环构建9个 GridItem
  25.         ForEach([0, 1, 2, 3, 4, 5, 6, 7, 8], (index: number) => {
  26.           GridItem() {
  27.             Canvas()
  28.               .chunkStyle()
  29.           }
  30.           .translate(this.getTranslateOffset(index))
  31.         })
  32.       }
  33.       .rowsTemplate('1fr 1fr 1fr')
  34.       .columnsTemplate('1fr 1fr 1fr')
  35.       .width(this.scaleSize)
  36.       .height(this.scaleSize)
  37.     }
  38.     .width(this.oldSize)
  39.     .height(this.oldSize)
  40.     .alignContent(Alignment.Center)
  41.     .onAppear(() => {
  42.       this.startAnimation();
  43.     })
  44.   }
  45.   // 抽取 translate 偏移量计算逻辑
  46.   getTranslateOffset(index: number): TranslateOffset {
  47.     switch (index) {
  48.       case 0: return { x: this.tran1 };
  49.       case 1: return { x: this.tran1 };
  50.       case 2: return { y: this.tran1 };
  51.       case 3: return { y: -this.tran1 };
  52.       case 4: return {}; // 中间项无偏移
  53.       case 5: return { y: this.tran1 };
  54.       case 6: return { y: -this.tran1 };
  55.       case 7: return { x: -this.tran1 };
  56.       case 8: return { x: -this.tran1 };
  57.       default: return {};
  58.     }
  59.   }
  60.   // 启动 Keyframe 动画
  61.   startAnimation(): void {
  62.     this.getUIContext().keyframeAnimateTo({ iterations: -1, delay: 0 }, [
  63.       {
  64.         duration: 500,
  65.         curve: Curve.EaseInOut,
  66.         event: () => {
  67.           this.tran1 = 0;
  68.           this.scaleSize = this.oldSize * 1.1;
  69.         }
  70.       },
  71.       {
  72.         duration: 190,
  73.         curve: Curve.Linear,
  74.         event: () => {
  75.           this.tran1 = this.oldSize / 3;
  76.         }
  77.       },
  78.       {
  79.         duration: 0,
  80.         curve: Curve.Linear,
  81.         event: () => {
  82.           this.tran1 = 0;
  83.         }
  84.       },
  85.       {
  86.         duration: 10,
  87.         curve: Curve.Linear,
  88.         event: () => {}
  89.       },
  90.       {
  91.         duration: 500,
  92.         curve: Curve.EaseIn,
  93.         event: () => {
  94.           this.scaleSize = this.oldSize * 0.75;
  95.           this.tran1 = 0;
  96.         }
  97.       }
  98.     ]);
  99.   }
  100.   @Styles
  101.   chunkStyle() {
  102.     .width(this.oldSize * 0.25)
  103.     .height(this.oldSize * 0.25)
  104.     .backgroundColor(this.spinColor)
  105.     .shadow(ShadowStyle.OUTER_DEFAULT_XS)
  106.   }
  107. }
复制代码
3.修改Index.ets文件,代码如下:
  1. import { SpinTen } from './Spin';
  2. @Entry
  3. @Component
  4. struct Index {
  5.   @State message: string = 'Hello World';
  6.   build() {
  7.     Column() {
  8.       SpinTen({
  9.         spinSize: 60,
  10.         spinColor: '#FF0000'
  11.       })
  12.     }
  13.     .alignItems(HorizontalAlign.Center)
  14.     .justifyContent(FlexAlign.Center)
  15.     .height('100%')
  16.     .width('100%')
  17.   }
  18. }
复制代码
  1. <strong>代码如下:</strong>
复制代码
  1. import { SpinTen } from './Spin';
  2. @Entry
  3. @Component
  4. struct Index {
  5.   @State message: string = 'Hello World';
  6.   build() {
  7.     Column() {
  8.       SpinTen({
  9.         spinSize: 60,
  10.         spinColor: '#FF0000'
  11.       })
  12.     }
  13.     .alignItems(HorizontalAlign.Center)
  14.     .justifyContent(FlexAlign.Center)
  15.     .height('100%')
  16.     .width('100%')
  17.   }
  18. }
复制代码
4.运行项目,登录华为账号,需举行署名

5.动画结果如下:

 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表