最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

css - Animating changes in an angular @for list without having the list 'jump' when every item is changed - Stac

programmeradmin4浏览0评论

I am trying to animate the change of items in a list in angular. The animation should be a simpel fade-in-out. This works absolutely fine for individual items getting inserted or removed. However the code has pagination logic, so when changing a page every single item in the list is changed. This causes all the new items to fade in while all the old items are still fading out. So for around 300ms the list is double the size which causes the view to jump.

What I want to achieve is that the first 'page' of items finishes fading out before any new items start fading in, thus preventing the page from jumping.

The list

<div class="relative">
  @for (item of items(); track item.id; let idx = $index) {
    <list-item
      @fadeInOut
      [item]="item"
      [idx]="idx"
    >
    </list-item>
  }
</div>

Component:

Component({
  /** ... **/
})
export class TaskListComponent {
  /** ... **/
  items = computed((): Item[] => {
    const items = // signal from a store
    const pagination = this.pagination(); // boolean
    const paginationOffset = this.paginationOffset(); // increases with 10 on next page
    let paginatedTasks = []
    if (pagination) {
      for(let i = 0; i < items.length; i++) {
        if (i < paginationOffset + 10 && i >= paginationOffset) {
          paginatedItems.push(items[i]);
        }
      }
    } else {
      paginatedItems = items;
    }
    return paginatedItems
  });
}

Animation:

export const fadeInOutAnimation = trigger('fadeInOut', [
  state('void', style({ opacity: 0,})), // Initial state when the element is not present
  transition(':enter', [animate('300ms ease-in')]), // When the element enters
  transition(':leave', [animate('300ms ease-out')]) // When the element leaves
]);

I am trying to animate the change of items in a list in angular. The animation should be a simpel fade-in-out. This works absolutely fine for individual items getting inserted or removed. However the code has pagination logic, so when changing a page every single item in the list is changed. This causes all the new items to fade in while all the old items are still fading out. So for around 300ms the list is double the size which causes the view to jump.

What I want to achieve is that the first 'page' of items finishes fading out before any new items start fading in, thus preventing the page from jumping.

The list

<div class="relative">
  @for (item of items(); track item.id; let idx = $index) {
    <list-item
      @fadeInOut
      [item]="item"
      [idx]="idx"
    >
    </list-item>
  }
</div>

Component:

Component({
  /** ... **/
})
export class TaskListComponent {
  /** ... **/
  items = computed((): Item[] => {
    const items = // signal from a store
    const pagination = this.pagination(); // boolean
    const paginationOffset = this.paginationOffset(); // increases with 10 on next page
    let paginatedTasks = []
    if (pagination) {
      for(let i = 0; i < items.length; i++) {
        if (i < paginationOffset + 10 && i >= paginationOffset) {
          paginatedItems.push(items[i]);
        }
      }
    } else {
      paginatedItems = items;
    }
    return paginatedItems
  });
}

Animation:

export const fadeInOutAnimation = trigger('fadeInOut', [
  state('void', style({ opacity: 0,})), // Initial state when the element is not present
  transition(':enter', [animate('300ms ease-in')]), // When the element enters
  transition(':leave', [animate('300ms ease-out')]) // When the element leaves
]);
Share Improve this question asked Jan 20 at 15:23 crazythingcrazything 551 silver badge7 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

I ended up setting a 150ms delay and setting display:none to make the item disappear completely before animating in the new list. This seems to work in all my required cases.

export const fadeInOutListItemAnimation = trigger('fadeInOutListItem', [
  state('void', style({ opacity: 0, display: 'none'})), // Initial state when the element is not present
  transition(':enter', [
    animate('150ms 150ms ease-in', style({ opacity: 1, display: '*'}))
  ]), // When the element enters
  transition(':leave', [
    animate('150ms ease-out', style({ opacity: 0, display: 'none' })),
  ]) // When the element leaves
]);

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论