#angular #animation #angular2-changedetection #angular2-hostbinding
Вопрос:
Я пытаюсь реализовать анимацию в библиотеке/помощнике прокрутки на основе этой идеи Wizdm Genesys
У меня есть служба, которая выдает IntersectionInfo
объект (IsIntersecting, Направление, направление и т. Д.), Когда элемент пересекается с окном просмотра.
Я подписываюсь на него, и если элемент входит в окно просмотра, я запускаю анимацию ввода.
Это работает нормально, если я не использую 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>
В Aoscomponent я использую selector: '[myAos]'
, чтобы его можно было использовать как директиву.
Вот компонент AOS
@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.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 here: My Stackblitz
Any ideas???