ng-bootstrap collapse: How to apply animations?

后端 未结 4 1088
猫巷女王i
猫巷女王i 2021-02-19 09:39

I\'m using Collapse: https://ng-bootstrap.github.io/#/components/collapse

However, it does not animate; even not on the demo site. How should I implement this??

4条回答
  •  甜味超标
    2021-02-19 09:48

    I've created a directive using only bootstrap classes that performs the same original bootstrap effect using only angular-animation, check it out!

    Live example

    Directive code

    import {Directive, ElementRef, HostBinding, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core';
    import {animate, AnimationBuilder, AnimationPlayer, keyframes, style} from '@angular/animations';
    
    @Directive({
      selector: '[appCollapseAnimated]'
    })
    export class CollapseAnimatedDirective implements OnChanges, OnInit {
      private static readonly SHOW_STYLE = 'show';
      private static readonly COLLAPSING = 'collapsing';
    
      @Input('appCollapseAnimated')
      collapsed = true;
    
      @Input()
      skipClosingAnimation = false;
    
      @HostBinding('class.collapse')
      private readonly addCollapseClass = true;
    
      private currentEffect: AnimationPlayer;
      private _closeEffect: AnimationPlayer;
      private _openEffect: AnimationPlayer;
    
      constructor(private el: ElementRef,
                  private builder: AnimationBuilder) {
    
      }
    
      ngOnInit(): void {
        if (!this.collapsed) {
          this.getClassList().add(CollapseAnimatedDirective.SHOW_STYLE);
        }
      }
    
      private get openEffect(): AnimationPlayer {
        if (!this._openEffect) {
          this._openEffect = this.builder.build(animate('500ms', keyframes([
            style({height: '0'}),
            style({height: '*'}),
          ]))).create(this.el.nativeElement);
        }
        this._openEffect.onDone(() => this.effectDone());
        return this._openEffect;
      }
    
    
      private get closeEffect(): AnimationPlayer {
        if (!this._closeEffect) {
          this._closeEffect = this.builder.build(animate('500ms', keyframes([
            style({height: '*'}),
            style({height: '0'}),
          ]))).create(this.el.nativeElement);
        }
        this._closeEffect.onDone(() => this.effectDone());
        return this._closeEffect;
      }
    
      private effectDone() {
        if (this.collapsed) {
          this.getClassList().remove(CollapseAnimatedDirective.SHOW_STYLE);
        }
        this.getClassList().remove(CollapseAnimatedDirective.COLLAPSING);
        if (this.currentEffect) {
          this.currentEffect.reset();
          this.currentEffect = null;
        }
      }
    
      ngOnChanges(changes: SimpleChanges): void {
        if (changes.collapsed && !changes.collapsed.firstChange) {
          if (changes.collapsed.previousValue === true && changes.collapsed.currentValue === false) {
            this.startOpening();
          }
          if (changes.collapsed.previousValue === false && changes.collapsed.currentValue === true) {
            this.startClosing();
          }
        }
      }
    
      private startOpening(): void {
        this.getClassList().add(CollapseAnimatedDirective.SHOW_STYLE);
        const effect = this.openEffect;
        this.playEffect(effect);
      }
    
      private getClassList() {
        const nativeElement = this.el.nativeElement as HTMLElement;
        return nativeElement.classList;
      }
    
      private startClosing(): void {
        const effect = this.closeEffect;
        if (this.skipClosingAnimation) {
          this.effectDone();
        } else {
          this.playEffect(effect);
        }
      }
    
      private playEffect(effect: AnimationPlayer) {
        if (!this.currentEffect) {
          this.getClassList().add(CollapseAnimatedDirective.COLLAPSING);
          this.currentEffect = effect;
          this.currentEffect.play();
        }
      }
    }
    

    Use it in your template:

    
    
    this should collapse with the default bootstrap behaviour

提交回复
热议问题