2016-06-15 37 views
7

Di recente ho sviluppato il seguente componente Angular 2 Read More. Ciò che fa questo componente è collassare ed espandere lunghi blocchi di testo con i collegamenti "Leggi di più" e "Leggi di meno". Non sulla base del numero di caratteri ma sulla base dell'altezza massima specificata.Angolare 2 Animazione slide up e down

import { Component, Input, ElementRef, AfterViewInit } from '@angular/core'; 

@Component({ 
    selector: 'read-more', 
    template: ` 
     <div [innerHTML]="text" [class.collapsed]="isCollapsed" [style.height]="isCollapsed ? maxHeight+'px' : 'auto'"> 
     </div> 
      <a *ngIf="isCollapsable" (click)="isCollapsed =! isCollapsed">Read {{isCollapsed? 'more':'less'}}</a> 
    `, 
    styles: [` 
     div.collapsed { 
      overflow: hidden; 
     } 
    `] 
}) 
export class ReadMoreComponent implements AfterViewInit { 

    //the text that need to be put in the container 
    @Input() text: string; 

    //maximum height of the container 
    @Input() maxHeight: number = 100; 

    //set these to false to get the height of the expended container 
    public isCollapsed: boolean = false; 
    public isCollapsable: boolean = false; 

    constructor(private elementRef: ElementRef) { 
    } 

    ngAfterViewInit() { 
     let currentHeight = this.elementRef.nativeElement.getElementsByTagName('div')[0].offsetHeight; 
     //collapsable only if the contents make container exceed the max height 
     if (currentHeight > this.maxHeight) { 
      this.isCollapsed = true; 
      this.isCollapsable = true; 
     } 
    } 
} 

e utilizzato come:

<read-more [text]="details" [maxHeight]="250"></read-more> 

Il componente funziona bene. Ora ho bisogno di aggiungere alcune animazioni slide up/down al componente in modo che quando si fa clic sul link Leggi altro, i contenuti scorrono verso il basso e quando si fa clic su Leggi di meno, i contenuti scorrono all'altezza massima specificata.

Qualcuno può guidare come ottenere ciò?

+0

[Vedi il mio rispondi qui] (http://stackoverflow.com/a/37843393/1375316). L'esempio è praticamente esattamente quello che stai cercando di fare. – threeve

+0

Grazie mille, in realtà ho provato ad aggiungere le seguenti informazioni di stile al mio componente precedente, ma questo non sembra funzionare. stili: [' div.collapsed { overflow: nascosto; } ', ' div { transizione: altezza 500ms facilità; } '] –

+0

Se funziona per te, puoi validare la mia soluzione per favore? – Julien

risposta

2

La risposta di tre è corretta: l'unico problema è che la transizione CSS non funziona con "auto". Quindi è necessario acquisire l'altezza automatica nella funzione ngAfterViewInit e memorizzarla come stringa. Si noti inoltre l'uso della funzione setTimeout per arrestare l''errore di violazione del flusso di dati-unidirezionale' che può verificarsi.

import { Component, Input, ElementRef, AfterViewInit } from '@angular/core'; 

@Component({ 
selector: 'read-more', 
template: ` 
    <div [style.height]="isCollapsed ? maxHeight+'px' : autoHeight"> 
     <ng-content></ng-content> 
    </div> 

    <span *ngIf="isCollapsable" class="btn-link cpointer" (click)="isCollapsed =! isCollapsed">Read {{isCollapsed? 'more':'less'}} ...</span> 

    `, 
styles: [` div { overflow-y: hidden; 
      -moz-transition: height .5s; 
      -ms-transition: height .5s; 
      -o-transition: height .5s; 
      -webkit-transition: height .5s; 
      transition: height .5s; ease;} 
     .cpointer {cursor:pointer; } 
     `] 
}) 
export class ReadMoreComponent implements AfterViewInit { 

@Input() 
maxHeight: number = 40; //two lines 

////set these to false to get the height of the expended container 
isCollapsed: boolean = false; 
isCollapsable: boolean = false; 
autoHeight: string= "auto"; 

constructor(private elementRef: ElementRef) {} 

ngAfterViewInit() { 
    // Inportant !! 
    // wait a tick to avoid one-time devMode 
    // unidirectional-data-flow-violation error 
    setTimeout(_ => { 
      let currentHeight = this.elementRef.nativeElement.getElementsByTagName('div')[0].offsetHeight; 

      this.autoHeight = currentHeight + "px"; 
      //collapsable only if the contents make container exceed the max height 
      if (currentHeight >= this.maxHeight) { 
       this.isCollapsed = true; 
       this.isCollapsable = true; 
      } 
     } 
    ); 
} 

} 
10

proprietà Calcolo automatico

Animazione con calcolo automatico altezza

A volte non si conosce il valore di una proprietà in stile tridimensionale fino al runtime. Ad esempio, gli elementi hanno spesso larghezze e altezze che dipendono dal loro contenuto e dalle dimensioni dello schermo. Queste proprietà sono spesso difficili da animare con i CSS.

In questi casi, è possibile utilizzare uno speciale valore di proprietà * in modo che il valore della proprietà sia calcolato in fase di esecuzione e quindi inserito nell'animazione .

In questo esempio, l'animazione congedo prende qualsiasi altezza dell'elemento ha prima di lasciare e anima da quell'altezza a zero:

animations: [ 
    trigger('shrinkOut', [ 
    state('in', style({height: '*'})), 
    transition('* => void', [ 
     style({height: '*'}), 
     animate(250, style({height: 0})) 
    ]) 
    ]) 
] 

da Angular documentazione ufficiale: https://angular.io/guide/animations#automatic-property-calculation

+0

Fantastico! Questo è il modo migliore per farlo! +1 – shramee

+0

provato questo, ma il testo all'interno dell'elemento non è animato, ma quando ho messo un po 'di colore di sfondo ha funzionato in qualche modo per il contenitore, è importante sapere perché? –