2016-06-15 13 views
7

Niedawno zbudowałem następujący komponent Angular 2 Read More. To, co robi ten komponent, to zwijanie i rozszerzanie długich bloków tekstu za pomocą linków "Czytaj więcej" i "Czytaj mniej". Nie na podstawie liczby znaków, ale na podstawie określonej maksymalnej wysokości.Angular 2 Slide Up and Down Animation

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; 
     } 
    } 
} 

i używane jak:

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

Komponent działa dobrze. Teraz muszę dodać animację przesuwania w górę/w dół do komponentu, aby po kliknięciu linku Czytaj więcej zawartość ześlizgnęła się w dół, a po kliknięciu opcji Czytaj mniej zawartość przesuwa się do określonej maksymalnej wysokości.

Czy ktokolwiek może wskazać, jak to osiągnąć?

+0

[Zobacz moje odpowiedź tutaj] (http://stackoverflow.com/a/37843393/1375316). Przykład jest dokładnie tym, co próbujesz zrobić. – threeve

+0

Dziękuję Trzech, faktycznie próbowałem dodając informacje o stylu poniżej do powyższego składnika, ale to nie wydaje się działać. style: [' div.collapsed { przepełnienie: ukryte; } ', ' div { przejście: wysokość 500ms łatwość; } '] –

+0

Jeśli to rozwiązanie działa prawidłowo, czy możesz uzasadnić moje rozwiązanie? – Julien

Odpowiedz

2

Odpowiedź Threeve jest poprawna - jedynym problemem jest to, że przejście CSS nie zadziała z "auto". Musisz więc uchwycić wysokość automatyczną w funkcji ngAfterViewInit i zapisać ją jako ciąg znaków. Zwróć także uwagę na użycie funkcji setTimeout, aby zatrzymać błąd "jednokierunkowej transmisji danych", który może wystąpić.

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

Automatyczne nieruchomość kalkulacja

animacji z obliczeń zautomatyzowany wysokości

Czasami nie znają wartość wymiarową kwatera aż do czasu wykonywania. Na przykład elementy często mają szerokość i wysokość zależą od ich zawartości i rozmiaru ekranu. Te właściwości są często trudne do animowania za pomocą CSS.

W takich przypadkach można użyć specjalnej wartości właściwości *, aby wartość właściwości została obliczona w czasie wykonywania, a następnie podłączona do animacji .

W tym przykładzie, animacja urlopu bierze cokolwiek wysokość element ma przed opuszczeniem i animuje z tej wysokości do zera:

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

z Kątowymi oficjalnej dokumentacji: https://angular.io/guide/animations#automatic-property-calculation

+0

Awesome! To najlepszy sposób na zrobienie tego! +1 – shramee

+0

próbowałem tego, ale tekst w elemencie nie jest animowany, ale kiedy dodam kolor tła, to działa jakoś na pojemnik, czy powiem dlaczego? –