Nav*_*med 9 typescript angular2-directives angular2-template angular
我最近构建了以下Angular 2 Read More组件.该组件所做的是使用"Read more"和"Read less"链接折叠和扩展长文本块.不是基于字符数,而是基于指定的最大高度.
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用如下:
<read-more [text]="details" [maxHeight]="250"></read-more>
Run Code Online (Sandbox Code Playgroud)
该组件运作良好.现在我需要向组件添加一些向上/向下滑动动画,以便在单击Read More链接时向下滑动内容,单击Read less时,内容将向上滑动到指定的最大高度.
任何人都可以指导如何实现这一目标?
Jul*_*ien 14
自动属性计算
具有自动高度计算的动画
有时您在运行时之前不知道维度样式属性的值.例如,元素通常具有取决于其内容和屏幕大小的宽度和高度.使用CSS动画这些属性通常很棘手.
在这些情况下,您可以使用特殊的*属性值,以便在运行时计算属性的值,然后将其插入到动画中.
在此示例中,离开动画采用元素离开之前所具有的任何高度,并将该高度的动画设置为零:
Run Code Online (Sandbox Code Playgroud)animations: [ trigger('shrinkOut', [ state('in', style({height: '*'})), transition('* => void', [ style({height: '*'}), animate(250, style({height: 0})) ]) ]) ]
来自Angular官方文档:https://angular.io/guide/animations#automatic-property-calculation
Fel*_*lix 14
我的解决方案:enter,:leave和*ngIf:
@Component({
selector: 'accordion',
templateUrl: './accordion.component.html',
animations: [
trigger('slideInOut', [
state('in', style({height: '*', opacity: 0})),
transition(':leave', [
style({height: '*', opacity: 1}),
group([
animate(300, style({height: 0})),
animate('200ms ease-in-out', style({'opacity': '0'}))
])
]),
transition(':enter', [
style({height: '0', opacity: 0}),
group([
animate(300, style({height: '*'})),
animate('400ms ease-in-out', style({'opacity': '1'}))
])
])
])
]
})
...
Run Code Online (Sandbox Code Playgroud)
模板:
<div *ngIf="shown" [@slideInOut] >
// ...content
</div>
Run Code Online (Sandbox Code Playgroud)
不幸的是我还必须加入这个修复程序(对于slideOut):https: //github.com/angular/angular/issues/15798
This is what I use in Angular 8.1.2. The beauty of the code is that it supports unlimited height of the div that needs to be shown/collapsed and also makes smooth transitions.
TS FILE:
import {Component, OnInit} from '@angular/core';
import {trigger, transition, animate, style, state} from '@angular/animations';
@Component({
selector: 'app-all-data',
templateUrl: './all-data.page.html',
styleUrls: ['./all-data.page.scss'],
animations: [
trigger('openClose', [
state('open', style({
height: '*',
opacity: 1,
})),
state('closed', style({
height: '0',
opacity: 0
})),
transition('open => closed', [
animate('0.35s')
]),
transition('closed => open', [
animate('0.35s')
]),
]),
]
})
export class AllDataPage implements OnInit {
showCardBody = false;
constructor() {
}
ngOnInit() {
}
/**
* Toggle details on click
*/
showDetails() {
this.showCardBody = !this.showCardBody;
}
}
Run Code Online (Sandbox Code Playgroud)
HTML FILE:
<button type="button" (click)="showDetails()">
Toggle Details
</button>
<div class="card-body" [@openClose]="showCardBody ? 'open' : 'closed'">
<p>This is some content</p>
<p>This is some content</p>
<p>This is some content</p>
<p>This is some content</p>
<p>This is some content</p>
</div>
Run Code Online (Sandbox Code Playgroud)
小智 2
Threeve 的答案是正确的 - 唯一的问题是 CSS 过渡不适用于“自动”。因此,您需要在 ngAfterViewInit 函数中捕获自动高度并将其存储为字符串。另请注意,使用 setTimeout 函数来阻止可能发生的“单向数据流违规错误”。
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;
}
}
);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
25689 次 |
| 最近记录: |