Transition animation within HarmonyOS Developer component


Transition animation within component

The insertion and deletion process of components is the transition process of the component itself, and the insertion and deletion animation of components is called transition animation within the component. Through the transition animation within the component, you can define the effect of the component appearing and disappearing.

The interface for transition animation within the component is:

transition(value: TransitionOptions)

The input parameter of the transition function is the transition effect within the component. You can define single or combined transition effects of translation, transparency, rotation, and scaling. , must be used together with animateTo to produce component transition effects.

Common usage of transition

type is used to specify the change scene in which the current transition effect takes effect in the component. The type is TransitionType.

  • Insertion and deletion of components use the same animation effect
Button()
  .transition({
    
     type: TransitionType.All, scale: {
    
     x: 0, y: 0 } })

When the type attribute is TransitionType.All, it means that the specified transition effect takes effect in all changes (insertions and deletions) of the component. At this time, deleting animation and inserting animation are the opposite processes, and deleting animation is the reverse of inserting animation. For example, the above code defines a Button control. When inserted, the component changes from the state where scale's x and y are both 0 to the default state where scale's x and y are both 1 (that is, fully displayed), and appears in a gradually enlarged manner. When deleted, the component changes from the default state where the x and y of the scale are both 1, to the state where the x and y of the specified scale are both 0, and gradually shrinks to a size of 0.

  • Insertion and deletion of components use different animation effects
Button()
  .transition({
    
     type: TransitionType.Insert, translate: {
    
     x: 200, y: -200 }, opacity: 0 })
  .transition({
    
     type: TransitionType.Delete, rotate: {
    
     x: 0, y: 0, z: 1, angle: 360 } })

When the insertion and deletion of components require different transition animation effects, you can call the transition function twice and set the type attribute to TransitionType.Insert and TransitionType.Delete respectively. For example, the above code defines a Button control. When inserted, the component changes from an initial state in which the x-direction translation is 200vp, the y-direction translation is -200vp, and the transparency is 0 relative to the normal layout position of the component, to a default state in which the x- and y-direction translation amounts are 0 and the transparency is 1. The inserted animation is a combination of translation animation and transparency animation. When deleted, the component changes from the default state with a rotation angle of 0 to the terminal state of rotating 360 degrees around the z-axis, that is, rotating once around the z-axis.

  • Only define one of the animation effects for component insertion or deletion.
Button()
  .transition({
    
     type: TransitionType.Delete, translate: {
    
     x: 200, y: -200 } })

When you only need the transition animation effect of component insertion or deletion, you only need to set the type attribute to the transition effect of TransitionType.Insert or TransitionType.Delete. For example, the above code defines a Button control. When deleted, the component changes from the default state of normal position and no translation to a position with a translation of 200vp in the x direction and a translation of -200vp in the y direction relative to the normal layout position. Inserting this component will not produce a transition animation for this component.

if/else generates transition animation within component

if/else statements can control the insertion and deletion of components. The following code can use Button's click event to control whether the if condition is met to control whether the Image component under the if is displayed.

@Entry
@Component
struct IfElseTransition {
    
    
  @State flag: boolean = true;
  @State show: string = 'show';

  build() {
    
    
    Column() {
    
    
      Button(this.show).width(80).height(30).margin(30)
        .onClick(() => {
    
    
          if (this.flag) {
    
    
            this.show = 'hide';
          } else {
    
    
            this.show = 'show';
          }
          // 点击Button控制Image的显示和消失
          this.flag = !this.flag;
        })
      if (this.flag) {
    
    
          Image($r('app.media.mountain')).width(200).height(200)
      }
    }.height('100%').width('100%')
  }
}

The above code does not configure any animation. Next, we will add the effect of transition within the component to the above code. First of all, the Image component is a component controlled by if, and transition parameters need to be added to it to specify the specific effect of the transition within the component. For example, you can use the following code to add a translation effect when inserting, and a scaling and transparency effect when deleting.

if (this.flag) {
    
    
  Image($r('app.media.mountain')).width(200).height(200)
    .transition({
    
     type: TransitionType.Insert, translate: {
    
     x: 200, y: -200 } })
    .transition({
    
     type: TransitionType.Delete, opacity: 0, scale: {
    
     x: 0, y: 0 } })
}

Although the above code specifies the animation style, it does not specify the animation parameters. It is not yet known how long and what kind of curve it will take to complete the animation. Transition must be used together with animateTo, and the insertion and deletion of components are controlled in the closure of animateTo. For the above example code, it is to change the value of flag in the animateTo closure. This part of the code is as follows. Specify the animation duration as 1000ms, use the default curve of the animateTo function for the curve, and change the value of the flag. All changes caused by flag changes will be animated according to the animation parameters. Here, flag affects the appearance and disappearance of Image.

animateTo({
    
     duration: 1000 }, () => {
    
    
  this.flag = !this.flag;
})

After the above process, when animateTo and transition are used together, an in-component transition animation is generated. The complete sample code is as follows:

@Entry
@Component
struct IfElseTransition {
    
    
  @State flag: boolean = true;
  @State show: string = 'show';

  build() {
    
    
    Column() {
    
    
      Button(this.show).width(80).height(30).margin(30)
        .onClick(() => {
    
    
          if (this.flag) {
    
    
            this.show = 'hide';
          } else {
    
    
            this.show = 'show';
          }
          
          animateTo({
    
     duration: 1000 }, () => {
    
    
            // 动画闭包内控制Image组件的出现和消失
            this.flag = !this.flag;
          })
        })
      if (this.flag) {
    
    
        // Image的出现和消失配置为不同的过渡效果
        Image($r('app.media.mountain')).width(200).height(200)
          .transition({
    
     type: TransitionType.Insert, translate: {
    
     x: 200, y: -200 } })
          .transition({
    
     type: TransitionType.Delete, opacity: 0, scale: {
    
     x: 0, y: 0 } })
      }
    }.height('100%').width('100%')
  }
}

Insert image description here

ForEach generates transition animation within the component

Similar to if/else, ForEach can control the insertion and deletion of components by controlling the number of elements in the array. To generate transition animation within a component through ForEach, two conditions are still required:

  • The components in ForEach are configured with transition effects.
  • Control the insertion or deletion of components in the closure of animateTo, that is, control the addition and deletion of elements in the array.

The following code is an example of using ForEach to generate transition animation within a component.

@Entry
@Component
struct ForEachTransition {
    
    
  @State numbers: string[] = ["1", "2", "3", "4", "5"]
  startNumber: number = 6;

  build() {
    
    
    Column({
     
      space: 10 }) {
    
    
      Column() {
    
    
        ForEach(this.numbers, (item) => {
    
    
          // ForEach下的直接组件需配置transition效果
          Text(item)
            .width(240)
            .height(60)
            .fontSize(18)
            .borderWidth(1)
            .backgroundColor(Color.Orange)
            .textAlign(TextAlign.Center)
            .transition({
    
     type: TransitionType.All, translate: {
    
     x: 200 }, scale: {
    
     x: 0, y: 0 } })
        }, item => item)
      }
      .margin(10)
      .justifyContent(FlexAlign.Start)
      .alignItems(HorizontalAlign.Center)
      .width("90%")
      .height("70%")

      Button('向头部添加元素')
        .fontSize(16)
        .width(160)
        .onClick(() => {
    
    
          animateTo({
    
     duration: 1000 }, () => {
    
    
            // 往数组头部插入一个元素,导致ForEach在头部增加对应的组件
            this.numbers.unshift(this.startNumber.toString());
            this.startNumber++;
          })
        })
      Button('向尾部添加元素')
        .width(160)
        .fontSize(16)
        .onClick(() => {
    
    
          animateTo({
    
     duration: 1000 }, () => {
    
    
            // 往数组尾部插入一个元素,导致ForEach在尾部增加对应的组件
            this.numbers.push(this.startNumber.toString());
            this.startNumber++;
          })
        })
      Button('删除头部元素')
        .width(160)
        .fontSize(16)
        .onClick(() => {
    
    
          animateTo({
    
     duration: 1000 }, () => {
    
    
            // 删除数组的头部元素,导致ForEach删除头部的组件
            this.numbers.shift();
          })
        })
      Button('删除尾部元素')
        .width(160)
        .fontSize(16)
        .onClick(() => {
    
    
          animateTo({
    
     duration: 1000 }, () => {
    
    
            // 删除数组的尾部元素,导致ForEach删除尾部的组件
            this.numbers.pop();
          })
        })
    }
    .width('100%')
    .height('100%')
  }
}

Insert image description here

Since the Column layout mode is set to FlexAlign.Start, the layout starts from the head in the vertical direction. Therefore, when adding an element to the end of the array, it will not affect the position of the component corresponding to the existing element in the array. It will only trigger the insertion animation of the new component. When adding elements to the head of the array, the subscripts of all elements in the original array are increased. Although their addition or deletion will not be triggered, it will affect the position of the corresponding component. Therefore, in addition to the newly added components that will perform transition animation, the components that previously existed in ForEach will also perform position animation.

Reference: Hongmeng Document Guide

Guess you like

Origin blog.csdn.net/qzmlyshao/article/details/133991661