# animation播放动画异常突变

#### 问题现象

转场动画期望由大缩小，且动画连贯流畅。但是实际的情况是，当页面显示发生转场，页面中圆初始显示为小的状态，待延时结束，再突然变大，然后由大缓慢缩小。其中突然变大导致整体效果不连贯，如何实现转场动画从页面开始显示，圆一直保持大的状态到延时结束，然后缩小？

问题代码示例参考如下：

```
@Entry
@ComponentV2
struct ShackHand {
  @Param serverActive: boolean = false
  // 动画点信息
  @Local colorArray: Array<JumpTrans> = [
    new JumpTrans('#8002ECFC', 500),
    new JumpTrans('#802d2de3', 1000),
    new JumpTrans('#8002ECFC', 1500),
    new JumpTrans('#802d2de3', 2000),
    new JumpTrans('#8002ECFC', 2500),
  ]

  build() {
    RelativeContainer() {
      ForEach(this.colorArray, (jump: JumpTrans, index: number) => {
        Circle({ width: '180lpx', height: '180lpx' })
          .stroke(Color.White)
          .margin({
            left: index * 30
          })
          .strokeWidth('5lpx')
          .fill(jump.color)
          .transition(generateEffect(jump.delay)) // 设置动画效果
      })

    }
    .backgroundColor(Color.Black)
    .width('600lpx')
    .height('600lpx')

  }
}

// 动画效果
function generateEffect(delay: number): TransitionEffect {
  return TransitionEffect.scale({ x: 0.1, y: 0.1 })
    .animation({
      duration: 1000,
      playMode: PlayMode.Reverse, // 动画反向播放
      delay: delay
    })

}

// 信息类
class JumpTrans {
  color: ResourceColor
  delay: number

  constructor(color: ResourceColor, delay: number) {
    this.color = color
    this.delay = delay
  }
}
```

问题效果预览：

#### 效果预览

#### 背景知识

*   组件内转场 (transition)主要通过transition属性配置转场参数，在组件插入和删除时显示过渡动效，主要用于容器组件中的子组件插入和删除时，提升用户体验。
*   属性动画 (animation)组件的某些通用属性变化时，可以通过属性动画实现渐变过渡效果，提升用户体验。其中delay属性用于设置动画延迟播放时间，PlayMode用于设置动画的播放方式。

#### 问题定位

该问题涉及动画播放的两个阶段：

*   动画之前形态：transition会在转场动画播放前保持设置的动画初始形态，即scale({ x: 0.1, y: 0.1 })。因为delay延迟了动画播放，所以这个形态会展示到UI。
*   动画开始形态：因为使用了PlayMode.Reverse动画反向播放，所以动画的开始形态变成了scale({ x: 1, y: 1 })。

由上述可知动画播放之前形态和动画开始形态有较大差距，因此出现突兀变化。

#### 分析结论

delay和PlayMode.Reverse属性设置不当会导致动画播放前出现组件形态的突兀变化，因此不建议组合使用。

#### 修改建议

若有延时效果，建议使用PlayMode.Normal，同时动画效果与目标状态翻转设置一下即可。

完整示例参考如下：

```
@Entry
@ComponentV2
struct JumpTransCustom {
  // 动画数据
  @Local colorArray: Array<JumpTrans> = [
    new JumpTrans('#8002ECFC', 500),
    new JumpTrans('#802d2de3', 1000),
    new JumpTrans('#8002ECFC', 1500),
    new JumpTrans('#802d2de3', 2000),
    new JumpTrans('#8002ECFC', 2500),
  ];

  build() {
    Column() {
      RelativeContainer() {
        ForEach(this.colorArray, (jump: JumpTrans, index: number) => {
          Circle({ width: '180lpx', height: '180lpx' })
            .stroke(Color.White)
            .margin({
              left: index * 30
            })
            .strokeWidth('5lpx')
            .fill(jump.color)
            .transition(generateEffect(jump.delay))  // 调用动画函数
            .scale({ x: 0.1, y: 0.1 });
        });
      }
      .backgroundColor(Color.Black)
      .width('600lpx')
      .height('600lpx');
    };
  }
}

// 动画效果
function generateEffect(delay: number): TransitionEffect {
  return TransitionEffect.scale({ x: 8, y: 8 })
    .animation({
      duration: 1000,
      playMode: PlayMode.Normal,
      delay: delay
    });
}

// 数据类
class JumpTrans {
  color: ResourceColor;
  delay: number;

  constructor(color: ResourceColor, delay: number) {
    this.color = color;
    this.delay = delay;
  }
}
```