Angular:ChangeDetection 干扰 HostBinding

时间:2021-07-04 19:16:41

标签: angular animation angular2-changedetection angular2-hostbinding

我正在尝试基于此想法实现 Animate On Scroll 库/帮助程序 Wizdm Genesys

我有一个服务,当元素与视口相交时,它会发出一个 IntersectionInfo(IsIntersecting、Direction、IsEntering 等)对象。

我订阅它,如果元素正在进入视口,我会触发进入动画。

它工作正常除非我在包含该元素或其任何父元素的任何组件上使用 ChangeDetection.OnPushdetectChanges() 没有修复它。

奇怪的是变量正在改变,我可以在开发人员工具中看到它,但它没有触发动画。

使用滚动动画库的组件(HelloComponent.html):

<button mat-button color="primary" (click)="_replay = !_replay" >Primary</button>


<ng-container *ngFor="let item of items; let idx = index">

  <div class="item-container" myAos [animate]="_replay">
    <div class="item">
      {{item}}
    </div>
  </div>

</ng-container>

在 AosComponnent 中,我使用 selector: '[myAos]',因此它可以像指令一样使用。

这是 AosComponent

@Component({
  selector: '[myAos]',
  template: `
    <!-- H5 is just for testing info -->
    <h5>{{ trigger | json }}</h5>
    <ng-content></ng-content>
  `,
  styleUrls: ['./aos.component.scss'],
  animations: [
    trigger('aosAnimate', [
      state('idle-bumpIn', style({ opacity: 0 })),

      transition(
        '* => bumpIn',
        [
          style({ transform: 'scale(0.5)', opacity: 0 }),

          animate(
            '{{timing}} {{delay}} cubic-bezier(.8, -0.6, 0.2, 1.5)',

            style({ transform: 'scale(1)', opacity: 1 })
          )
        ],
        { params: { timing: '500ms', delay: '' } }
      ),
      // None
      state('none', style('*')),
      state('idle-none', style('*'))
    ])
  ]
})
export class AosComponent implements OnInit {
  @Input('debounce') _debounce = 0;
  @Input('rootMargin') _rootMargin = '0px';
  @Input('root') _root: HTMLElement | undefined = undefined;
  @Input('threshold') _threshold: number = 0;
  @Input('delaySecs') _delay: number = 0.25;
  @Input('durationSecs') _duration: number = 0.5;
  private destroy$ = new Subject();

  @HostBinding('@aosAnimate')
  public trigger: any = 'none';


  @Input()
  set animate(trgr: boolean) {
    this.trigger = !trgr
      ? 'idle-bumpIn'
      : {
          value: 'bumpIn',
          params: {
            timing: `${this._duration}s`,
            delay: `${this._delay}s`
          }
        };
    this._cd.detectChanges();

    console.log('animate Input', trgr, this.trigger);
  }

  //-----------------------------------------------------//

  constructor(
    private _element: ElementRef,
    private renderer: Renderer2,
    private _scroll: IntersectionService,
    private _cd: ChangeDetectorRef
  ) {} //ctor

  //-----------------------------------------------------//

  ngOnInit(): void {
    // const me = this

    this._scroll
      .observeIntersection(
        this._element,
        this._threshold,
        this._root,
        this._rootMargin
      )
      .pipe(takeUntil(this.destroy$))
      .subscribe(info => {
        this.animate = info.isEntering;
        console.log('observeIntersection', info.isEntering);
        this._cd.detectChanges();
      });
  } //ngOnInit

  //-----------------------------------------------------//

  ngOnDestroy() {
    this.destroy$.next();
  } //ngOnDestroy

  //-----------------------------------------------------//
  
} //Cls

如果我从 @Input() animate 内部将 HelloComponent 设置为 true,它始终有效。 如果我将 @Input() animatesubscribe 设置为 true,它仅在我从 changeDetection: ChangeDetectionStrategy.OnPush

中删除 HelloComponent 时才有效

HelloComponent.ts

@Component({
  selector: 'hello',
  templateUrl: './hello.component.html',
  styleUrls: ['./hello.component.scss']
  // changeDetection: ChangeDetectionStrategy.OnPush  <--- this is the problem
})
export class HelloComponent {
  _replay = false;
  items = ['item 1', 'item 2', 'item 3', 'item 4', 'item 5'];
}

此处为 StackBlitz:My Stackblitz

有什么想法吗???

0 个答案:

没有答案