0

我正在尝试基于这个想法Wizdm Genesys实现 Animate On Scroll 库/助手

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

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

除非ChangeDetection.OnPush在包含该元素的任何组件或其任何父级上 使用它,否则它工作正常。detectChanges()不修复它。

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

使用滚动动画库 (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>

在我使用的 AosComponnentselector: '[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从内部设置为 true,HelloComponent它总是有效的。如果我设置@Input() animate为 true ,则它仅在我从中subscribe删除时才有效changeDetection: ChangeDetectionStrategy.OnPushHelloComponent

你好组件.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 在这里:我的 Stackblitz

有任何想法吗???

4

0 回答 0