如何使用图片实现旋转加载效果
==============

#### 问题现象

如何实现图片在当前位置不停地转动，做出加载中的动态效果？

#### 效果预览

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/f1/v3/mOCUCMspShqERkaB7CxprA/zh-cn_image_0000002628601522.gif?HW-CC-KV=V1&HW-CC-Date=20260709T134038Z&HW-CC-Expire=86400&HW-CC-Sign=F58CEFCF31122633AD43832CEBD3052469731132983A8D1B3F8357D2E1BBE54B "点击放大")

#### 背景知识

*   [animateTo](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-uicontext-uicontext#animateto)：提供animateTo接口来指定由于闭包代码导致的状态变化插入过渡动效。
*   [onAppear](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-events-show-hide#onappear)：是组件挂载到组件树并显示后触发的回调函数，常用于执行初始化操作（如数据加载、动画启动）。
*   [if/else：条件渲染](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-rendering-control-ifelse)：条件渲染可根据应用状态，使用if、else和else if渲染相应的UI内容。

#### 解决方案

通过条件渲染机制触发animateTo动画，实现显示状态的切换。在状态切换过程中，同步执行加载层的淡出动画与内容层的淡入动画，并结合旋转动画，从而实现从加载状态到正式内容展示的平滑过渡。

@Entry
@Component
struct RotatingLoadPage {
  @State imageAngle: number = 0;
  @State flag: boolean = false;
  @State opacityValue: number = 0;
  @State opacityValueNum: number = 1;

  _// 通过生命周期模拟请求数据_
  aboutToAppear(): void {
    setTimeout(() => {
      this.getUIContext()?.animateTo({ duration: 1000 }, () => {
        this.flag = true;
        this.opacityValueNum = 0;
        this.opacityValue = 1;
      });
    }, 3000);
  }

  build() {
    Column({ space: 20 }) {
      if (!this.flag) {
        Stack() {
          Image($r('app.media.startIcon')) _// 此处'app.media.startIcon'等资源仅作示例，请开发者自行替换。_
            .width(200)
            .height(200)
            .borderRadius(1000)
            .rotate({ z: 1, angle: this.imageAngle })
          Text('图片加载中...');
        }
        .opacity(this.opacityValueNum)
        .onAppear(() => {
          this.getUIContext()?.animateTo({ duration: 5000, iterations: -1 }, () => {
            this.imageAngle = 360;
            this.opacityValueNum = 0;
          });
        })
      } else {
        Image($r('app.media.startIcon'))  _// 此处'app.media.startIcon'等资源仅作示例，请开发者自行替换。_
          .width(200)
          .height(200)
          .borderRadius(1000) _// 绑定透明度属性_
          .opacity(this.opacityValue)
          .onAppear(() => {
            _// 执行透明度渐变动画_
            this.getUIContext()?.animateTo({
              duration: 5000, curve: Curve.EaseOut,
              iterations: 1
            }, () => {
              _// 从0到1实现淡入效果_
              this.opacityValue = 1;
            });
          })
      }
    }
    .justifyContent(FlexAlign.Center)
    .height('100%')
    .width('100%')
  }
}