93 lines
2.2 KiB
TypeScript
93 lines
2.2 KiB
TypeScript
import { AfterViewInit, Directive, ElementRef, Input, NgZone, OnChanges, OnDestroy } from '@angular/core';
|
|
import { BooleanInput, InputBoolean } from '@delon/util';
|
|
import { fromEvent, Subscription } from 'rxjs';
|
|
import { debounceTime } from 'rxjs/operators';
|
|
|
|
declare var Masonry: any;
|
|
|
|
@Directive({
|
|
selector: '[masonry]',
|
|
exportAs: 'masonryComp'
|
|
})
|
|
export class MasonryDirective implements AfterViewInit, OnChanges, OnDestroy {
|
|
static ngAcceptInputType_disabled: BooleanInput;
|
|
|
|
private masonry: any;
|
|
private observer?: MutationObserver;
|
|
private resize$: Subscription | null = null;
|
|
|
|
@Input('masonry') options: any;
|
|
@Input() @InputBoolean() disabled = false;
|
|
|
|
constructor(private el: ElementRef, private zone: NgZone) {}
|
|
|
|
private outsideRender(cb: () => void): void {
|
|
this.zone.runOutsideAngular(() => cb());
|
|
}
|
|
|
|
init(): void {
|
|
this.destroy();
|
|
this.outsideRender(() => {
|
|
this.masonry = new Masonry(this.el.nativeElement, {
|
|
originLeft: true,
|
|
transitionDuration: '0.3s',
|
|
itemSelector: '.masonry__thm',
|
|
columnWidth: '.masonry__sizer',
|
|
...this.options
|
|
});
|
|
});
|
|
}
|
|
|
|
reload(): void {
|
|
this.outsideRender(() => {
|
|
if (this.disabled) {
|
|
return;
|
|
}
|
|
this.masonry.reloadItems();
|
|
this.masonry.layout();
|
|
});
|
|
}
|
|
|
|
private destroy(): void {
|
|
this.zone.runOutsideAngular(() => {
|
|
if (this.masonry) {
|
|
this.masonry.destroy();
|
|
}
|
|
});
|
|
}
|
|
|
|
private initElChange(): void {
|
|
if (this.observer || typeof MutationObserver === 'undefined') {
|
|
return;
|
|
}
|
|
this.zone.runOutsideAngular(() => {
|
|
this.observer = new MutationObserver(() => this.reload());
|
|
this.observer.observe(this.el.nativeElement, {
|
|
childList: true,
|
|
subtree: true
|
|
});
|
|
});
|
|
}
|
|
|
|
ngAfterViewInit(): void {
|
|
this.initElChange();
|
|
this.resize$ = fromEvent(window, 'resize')
|
|
.pipe(debounceTime(50))
|
|
.subscribe(() => this.reload());
|
|
}
|
|
|
|
ngOnChanges(): void {
|
|
this.init();
|
|
}
|
|
|
|
ngOnDestroy(): void {
|
|
this.destroy();
|
|
if (this.observer) {
|
|
this.observer.disconnect();
|
|
}
|
|
if (this.resize$) {
|
|
this.resize$.unsubscribe();
|
|
}
|
|
}
|
|
}
|