首页 > 解决方案 > 如何让洗牌 css 动画在 Angular8 中工作?(类似的代码适用于 angular2)

问题描述

我有一个要制作动画的 app-transition-group 组件。在我的CSS中,我有:

.flip-list-move {
  transition: transform 1s;
}

虽然它在调用 shuffle 时出现,但它总是瞬间改变,并且从不使用 angular8 进行动画处理。它适用于angular2。问题是什么?

我的代码是这样的:

app.component.ts

@Component({
  selector: 'my-app',
  template: `
    <h2>Items reorder/shuffle animations with Angular8 ngFor</h2>
    <button (click)="shuffle()">Configure</button>
    <ul [transition-group]="'flip-list'">
      <li *ngFor="let item of items" transition-group-item>
        {{ item }}
      </li>
    </ul>
  `,
})
export class App {
  items = [1, 2, 3, 4, 5, 6, 7, 8, 9];

  shuffle() {
    this.items = this.shufflestuff(this.items)
  }
}

shufflestuff=function(array) {
  const length = array == null ? 0 : array.length
  if (!length) {
    return []
  }
  let index = -1
  const lastIndex = length - 1
  const result = this.copyArray(array)
  while (++index < length) {
    const rand = index + Math.floor(Math.random() * (lastIndex - index + 1))
    const value = result[rand]
    result[rand] = result[index]
    result[index] = value
  }
  return result
}

copyArray=function(source, array) {
  let index = -1
  const length = source.length

  array || (array = new Array(length))
  while (++index < length) {
    array[index] = source[index]
  }
  return array
}

我导入了模块,在我的 transition-group.ts 文件中我有:

从“@angular/core”导入{组件、ContentChildren、指令、ElementRef、输入、查询列表};

@Directive({
  selector: '[app-transition-group-item]'
})
export class TransitionGroupItemDirective {
  prevPos: any;
  newPos: any;
  el: HTMLElement;
  moved: boolean;
  moveCallback: any;

  constructor(elRef: ElementRef) {
    this.el = elRef.nativeElement;
  }
}

@Directive({
  selector: '[app-transition-group]'
})
export class TransitionGroupComponent {
  @Input('app-transition-group') class;

  @ContentChildren(TransitionGroupItemDirective) items: QueryList<TransitionGroupItemDirective>;

  ngAfterContentInit() {
    this.refreshPosition('prevPos');
    this.items.changes.subscribe(items => {
      items.forEach(item => {
        item.prevPos = item.newPos || item.prevPos;
      });

      items.forEach(this.runCallback);
      this.refreshPosition('newPos');
      items.forEach(this.applyTranslation);

      // force reflow to put everything in position
      const offSet = document.body.offsetHeight;
      this.items.forEach(this.runTransition.bind(this));
    })
  }

  runCallback(item: TransitionGroupItemDirective) {
    if(item.moveCallback) {
      item.moveCallback();
    }
  }

  runTransition(item: TransitionGroupItemDirective) {
    if (!item.moved) {
      return;
    }
    const cssClass = this.class + '-move';
    let el = item.el;
    let style: any = el.style;
    el.classList.add(cssClass);
    style.transform = style.WebkitTransform = style.transitionDuration = '';
    el.addEventListener('transitionend', item.moveCallback = (e: any) => {
      if (!e || /transform$/.test(e.propertyName)) {
        el.removeEventListener('transitionend', item.moveCallback);
        item.moveCallback = null;
        el.classList.remove(cssClass);
      }
    });
  }

  refreshPosition(prop: string) {
    this.items.forEach(item => {
      item[prop] = item.el.getBoundingClientRect();
    });
  }

  applyTranslation(item: TransitionGroupItemDirective) {
    item.moved = false;
    const dx = item.prevPos.left - item.newPos.left;
    const dy = item.prevPos.top - item.newPos.top;
    if (dx || dy) {
      item.moved = true;
      let style: any = item.el.style;
      style.transform = style.WebkitTransform = 'translate(' + dx + 'px,' + dy + 'px)';
      style.transitionDuration = '0s';
    }
  }
}

当按下按钮时,我怎样才能让它动画?Stackblitz 在这里使用 Angular8:https ://stackblitz.com/edit/angular-so-1-t81c8l?file=src/app/app.component.css

Angular 2 中的工作版本位于此 plunkr: https ://next.plnkr.co/edit/i2hRcrTHLxTKA7mk

angular8 和 angular2 版本之间的唯一区别是 app-transition-group/transition-group 是 angular2 中的 @Component 而不是 angular8 中的 @Directive。如果有更好的方法可以做到这一点,我愿意接受建议。

标签: cssangular

解决方案


Angular 没有看到变化,QueryList<TransitionGroupItemDirective>因为您忘记添加TransitionGroupItemDirective到 NgModule 的声明数组中

import { TransitionGroupItemDirective } from './transition-group/transition-group.component';

@NgModule({
  ...
  declarations: [ ...TransitionGroupComponent, TransitionGroupItemDirective ],
})
export class AppModule { }

分叉的 Stackblitz


推荐阅读