UNPKG

ng-cw-v12

Version:

Angular UI component library

77 lines 13.4 kB
import { Component, Input, ViewChild } from '@angular/core'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; export class VirtualScrollComponent { constructor(ngZone) { this.ngZone = ngZone; this.ncItems = []; this.ncBufferCount = 2; //缓冲item数量,前后各2项 this.visibleItems = []; //显示items this.totalPadding = 0; //总填充高度 this.topPadding = 0; this.scrollTop = 0; //已滚动高度 this.itemHeight = 1; //若设为0,下方代码获取不到this.templateContainer this.viewportHeight = 0; //视窗可视高度 } ngAfterViewInit() { const element = this.templateContainer.nativeElement.firstChild; const styles = getComputedStyle(element); this.itemHeight = element.offsetHeight + parseFloat(styles.marginTop) + parseFloat(styles.marginBottom); //先获取item高度 this.viewportHeight = this.viewport.nativeElement.clientHeight; //视窗可视高度 this.updateVisibleItems(); this.updateTotalPadding(); } ngOnChanges(changes) { if (changes['ncItems']) { this.updateTotalPadding(); this.updateVisibleItems(); } } onScroll() { this.ngZone.run(() => { this.scrollTop = this.viewport.nativeElement.scrollTop; this.updateVisibleItems(); }); } updateVisibleItems() { const firstVisibleIndex = Math.floor(this.scrollTop / this.itemHeight); const startIndex = Math.max(0, firstVisibleIndex - this.ncBufferCount); const visibleItemsCount = Math.ceil(this.viewportHeight / this.itemHeight); const endIndex = Math.min(firstVisibleIndex + visibleItemsCount + this.ncBufferCount, this.ncItems.length - 1); this.visibleItems = []; for (let i = startIndex; i <= endIndex; i++) { this.visibleItems.push({ index: i, data: this.ncItems[i] }); } this.topPadding = startIndex * this.itemHeight; } updateTotalPadding() { this.totalPadding = this.ncItems.length * this.itemHeight; } //采用trackBy提升性能,只渲染改变的dom trackByIndex(index, item) { return item.index; } } VirtualScrollComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: VirtualScrollComponent, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); VirtualScrollComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.1.5", type: VirtualScrollComponent, selector: "nc-virtual-scroll", inputs: { ncItems: "ncItems", ncItemTemplate: "ncItemTemplate", ncBufferCount: "ncBufferCount" }, viewQueries: [{ propertyName: "viewport", first: true, predicate: ["viewport"], descendants: true, static: true }, { propertyName: "templateContainer", first: true, predicate: ["templateContainer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"viewport\" #viewport (scroll)=\"onScroll()\">\r\n <div class=\"total-padding\" [style.height.px]=\"totalPadding\">\r\n <div class=\"item-container\" [style.transform]=\"'translateY(' + topPadding + 'px)'\">\r\n <div #templateContainer *ngFor=\"let item of visibleItems; trackBy: trackByIndex\">\r\n <ng-container [ngTemplateOutlet]=\"ncItemTemplate\" #templateContainer \r\n [ngTemplateOutletContext]=\"{$implicit: item.data, index: item.index}\"></ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: [".viewport{width:100%;height:100%;overflow-y:auto;position:relative}.viewport::-webkit-scrollbar{width:6px;height:6px}.viewport::-webkit-scrollbar-thumb{background-color:#cdc9cf;border-radius:10px;-webkit-transition:background-color .3s ease;transition:background-color .3s ease}.viewport::-webkit-scrollbar-thumb:hover{background-color:#766d7b}.viewport::-webkit-scrollbar-track{background:#0000;cursor:pointer}\n"], directives: [{ type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: VirtualScrollComponent, decorators: [{ type: Component, args: [{ selector: 'nc-virtual-scroll', templateUrl: './virtual-scroll.component.html', styleUrls: ['./virtual-scroll.component.less'] }] }], ctorParameters: function () { return [{ type: i0.NgZone }]; }, propDecorators: { ncItems: [{ type: Input }], ncItemTemplate: [{ type: Input }], ncBufferCount: [{ type: Input }], viewport: [{ type: ViewChild, args: ['viewport', { static: true }] }], templateContainer: [{ type: ViewChild, args: ['templateContainer'] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlydHVhbC1zY3JvbGwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvY29tcG9uZW50cy92aXJ0dWFsLXNjcm9sbC92aXJ0dWFsLXNjcm9sbC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnRzL3ZpcnR1YWwtc2Nyb2xsL3ZpcnR1YWwtc2Nyb2xsLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUE2QixTQUFTLEVBQW9DLE1BQU0sZUFBZSxDQUFDOzs7QUFZekgsTUFBTSxPQUFPLHNCQUFzQjtJQWNqQyxZQUFvQixNQUFjO1FBQWQsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQWJ6QixZQUFPLEdBQVUsRUFBRSxDQUFDO1FBRXBCLGtCQUFhLEdBQVcsQ0FBQyxDQUFDLENBQUEsZ0JBQWdCO1FBSW5ELGlCQUFZLEdBQWtCLEVBQUUsQ0FBQyxDQUFBLFNBQVM7UUFDMUMsaUJBQVksR0FBVyxDQUFDLENBQUMsQ0FBQSxPQUFPO1FBQ2hDLGVBQVUsR0FBVyxDQUFDLENBQUM7UUFDdkIsY0FBUyxHQUFXLENBQUMsQ0FBQyxDQUFBLE9BQU87UUFDN0IsZUFBVSxHQUFXLENBQUMsQ0FBQyxDQUFBLHFDQUFxQztRQUM1RCxtQkFBYyxHQUFXLENBQUMsQ0FBQyxDQUFBLFFBQVE7SUFFRyxDQUFDO0lBRXZDLGVBQWU7UUFDYixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsYUFBYSxDQUFDLFVBQVUsQ0FBQztRQUNoRSxNQUFNLE1BQU0sR0FBRyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN6QyxJQUFJLENBQUMsVUFBVSxHQUFHLE9BQU8sQ0FBQyxZQUFZLEdBQUcsVUFBVSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUEsV0FBVztRQUNuSCxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLFlBQVksQ0FBQyxDQUFBLFFBQVE7UUFDdkUsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFDMUIsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7SUFDNUIsQ0FBQztJQUVELFdBQVcsQ0FBQyxPQUFzQjtRQUNoQyxJQUFJLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRTtZQUN0QixJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztZQUMxQixJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztTQUMzQjtJQUNILENBQUM7SUFFRCxRQUFRO1FBQ04sSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFO1lBQ25CLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDO1lBQ3ZELElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1FBQzVCLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELGtCQUFrQjtRQUNoQixNQUFNLGlCQUFpQixHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDdkUsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsaUJBQWlCLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQ3ZFLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUMzRSxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLGlCQUFpQixHQUFHLGlCQUFpQixHQUFHLElBQUksQ0FBQyxhQUFhLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFFL0csSUFBSSxDQUFDLFlBQVksR0FBRyxFQUFFLENBQUM7UUFDdkIsS0FBSyxJQUFJLENBQUMsR0FBRyxVQUFVLEVBQUUsQ0FBQyxJQUFJLFFBQVEsRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUMzQyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1NBQzdEO1FBRUQsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQztJQUNqRCxDQUFDO0lBRUQsa0JBQWtCO1FBQ2hCLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQztJQUM1RCxDQUFDO0lBRUQseUJBQXlCO0lBQ3pCLFlBQVksQ0FBQyxLQUFhLEVBQUUsSUFBaUI7UUFDM0MsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDO0lBQ3BCLENBQUM7O21IQTVEVSxzQkFBc0I7dUdBQXRCLHNCQUFzQiw2WUNabkMsb2xCQVNNOzJGREdPLHNCQUFzQjtrQkFMbEMsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsbUJBQW1CO29CQUM3QixXQUFXLEVBQUUsaUNBQWlDO29CQUM5QyxTQUFTLEVBQUUsQ0FBQyxpQ0FBaUMsQ0FBQztpQkFDL0M7NkZBRVUsT0FBTztzQkFBZixLQUFLO2dCQUNHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBQ0csYUFBYTtzQkFBckIsS0FBSztnQkFDbUMsUUFBUTtzQkFBaEQsU0FBUzt1QkFBQyxVQUFVLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUNQLGlCQUFpQjtzQkFBaEQsU0FBUzt1QkFBQyxtQkFBbUIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIElucHV0LCBBZnRlclZpZXdJbml0LCBFbGVtZW50UmVmLCBWaWV3Q2hpbGQsIE5nWm9uZSwgT25DaGFuZ2VzLCBTaW1wbGVDaGFuZ2VzIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcblxyXG5pbnRlcmZhY2UgVmlydHVhbEl0ZW0ge1xyXG4gIGluZGV4OiBudW1iZXI7XHJcbiAgZGF0YTogYW55O1xyXG59XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ25jLXZpcnR1YWwtc2Nyb2xsJyxcclxuICB0ZW1wbGF0ZVVybDogJy4vdmlydHVhbC1zY3JvbGwuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL3ZpcnR1YWwtc2Nyb2xsLmNvbXBvbmVudC5sZXNzJ11cclxufSlcclxuZXhwb3J0IGNsYXNzIFZpcnR1YWxTY3JvbGxDb21wb25lbnQgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkNoYW5nZXMge1xyXG4gIEBJbnB1dCgpIG5jSXRlbXM6IGFueVtdID0gW107XHJcbiAgQElucHV0KCkgbmNJdGVtVGVtcGxhdGU6IGFueTsvL+S8oOWFpeeahGl0ZW3mqKHmnb9cclxuICBASW5wdXQoKSBuY0J1ZmZlckNvdW50OiBudW1iZXIgPSAyOy8v57yT5YayaXRlbeaVsOmHj++8jOWJjeWQjuWQhDLpoblcclxuICBAVmlld0NoaWxkKCd2aWV3cG9ydCcsIHsgc3RhdGljOiB0cnVlIH0pIHZpZXdwb3J0ITogRWxlbWVudFJlZjsvL+inhueql1xyXG4gIEBWaWV3Q2hpbGQoJ3RlbXBsYXRlQ29udGFpbmVyJykgdGVtcGxhdGVDb250YWluZXIhOiBFbGVtZW50UmVmOy8v55So5LqO6I635Y+W5Lyg5YWl55qEaXRlbemrmOW6pu+8jOiuvue9rml0ZW1IZWlnaHTlgLxcclxuXHJcbiAgdmlzaWJsZUl0ZW1zOiBWaXJ0dWFsSXRlbVtdID0gW107Ly/mmL7npLppdGVtc1xyXG4gIHRvdGFsUGFkZGluZzogbnVtYmVyID0gMDsvL+aAu+Whq+WFhemrmOW6plxyXG4gIHRvcFBhZGRpbmc6IG51bWJlciA9IDA7XHJcbiAgc2Nyb2xsVG9wOiBudW1iZXIgPSAwOy8v5bey5rua5Yqo6auY5bqmXHJcbiAgaXRlbUhlaWdodDogbnVtYmVyID0gMTsvL+iLpeiuvuS4ujDvvIzkuIvmlrnku6PnoIHojrflj5bkuI3liLB0aGlzLnRlbXBsYXRlQ29udGFpbmVyXHJcbiAgdmlld3BvcnRIZWlnaHQ6IG51bWJlciA9IDA7Ly/op4bnqpflj6/op4bpq5jluqZcclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBuZ1pvbmU6IE5nWm9uZSkgeyB9XHJcblxyXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcclxuICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLnRlbXBsYXRlQ29udGFpbmVyLm5hdGl2ZUVsZW1lbnQuZmlyc3RDaGlsZDtcclxuICAgIGNvbnN0IHN0eWxlcyA9IGdldENvbXB1dGVkU3R5bGUoZWxlbWVudCk7XHJcbiAgICB0aGlzLml0ZW1IZWlnaHQgPSBlbGVtZW50Lm9mZnNldEhlaWdodCArIHBhcnNlRmxvYXQoc3R5bGVzLm1hcmdpblRvcCkgKyBwYXJzZUZsb2F0KHN0eWxlcy5tYXJnaW5Cb3R0b20pOy8v5YWI6I635Y+WaXRlbemrmOW6plxyXG4gICAgdGhpcy52aWV3cG9ydEhlaWdodCA9IHRoaXMudmlld3BvcnQubmF0aXZlRWxlbWVudC5jbGllbnRIZWlnaHQ7Ly/op4bnqpflj6/op4bpq5jluqZcclxuICAgIHRoaXMudXBkYXRlVmlzaWJsZUl0ZW1zKCk7XHJcbiAgICB0aGlzLnVwZGF0ZVRvdGFsUGFkZGluZygpO1xyXG4gIH1cclxuXHJcbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcykge1xyXG4gICAgaWYgKGNoYW5nZXNbJ25jSXRlbXMnXSkge1xyXG4gICAgICB0aGlzLnVwZGF0ZVRvdGFsUGFkZGluZygpO1xyXG4gICAgICB0aGlzLnVwZGF0ZVZpc2libGVJdGVtcygpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgb25TY3JvbGwoKSB7XHJcbiAgICB0aGlzLm5nWm9uZS5ydW4oKCkgPT4ge1xyXG4gICAgICB0aGlzLnNjcm9sbFRvcCA9IHRoaXMudmlld3BvcnQubmF0aXZlRWxlbWVudC5zY3JvbGxUb3A7XHJcbiAgICAgIHRoaXMudXBkYXRlVmlzaWJsZUl0ZW1zKCk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHVwZGF0ZVZpc2libGVJdGVtcygpIHtcclxuICAgIGNvbnN0IGZpcnN0VmlzaWJsZUluZGV4ID0gTWF0aC5mbG9vcih0aGlzLnNjcm9sbFRvcCAvIHRoaXMuaXRlbUhlaWdodCk7XHJcbiAgICBjb25zdCBzdGFydEluZGV4ID0gTWF0aC5tYXgoMCwgZmlyc3RWaXNpYmxlSW5kZXggLSB0aGlzLm5jQnVmZmVyQ291bnQpO1xyXG4gICAgY29uc3QgdmlzaWJsZUl0ZW1zQ291bnQgPSBNYXRoLmNlaWwodGhpcy52aWV3cG9ydEhlaWdodCAvIHRoaXMuaXRlbUhlaWdodCk7XHJcbiAgICBjb25zdCBlbmRJbmRleCA9IE1hdGgubWluKGZpcnN0VmlzaWJsZUluZGV4ICsgdmlzaWJsZUl0ZW1zQ291bnQgKyB0aGlzLm5jQnVmZmVyQ291bnQsIHRoaXMubmNJdGVtcy5sZW5ndGggLSAxKTtcclxuXHJcbiAgICB0aGlzLnZpc2libGVJdGVtcyA9IFtdO1xyXG4gICAgZm9yIChsZXQgaSA9IHN0YXJ0SW5kZXg7IGkgPD0gZW5kSW5kZXg7IGkrKykge1xyXG4gICAgICB0aGlzLnZpc2libGVJdGVtcy5wdXNoKHsgaW5kZXg6IGksIGRhdGE6IHRoaXMubmNJdGVtc1tpXSB9KTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLnRvcFBhZGRpbmcgPSBzdGFydEluZGV4ICogdGhpcy5pdGVtSGVpZ2h0O1xyXG4gIH1cclxuXHJcbiAgdXBkYXRlVG90YWxQYWRkaW5nKCkge1xyXG4gICAgdGhpcy50b3RhbFBhZGRpbmcgPSB0aGlzLm5jSXRlbXMubGVuZ3RoICogdGhpcy5pdGVtSGVpZ2h0O1xyXG4gIH1cclxuXHJcbiAgLy/ph4fnlKh0cmFja0J55o+Q5Y2H5oCn6IO977yM5Y+q5riy5p+T5pS55Y+Y55qEZG9tXHJcbiAgdHJhY2tCeUluZGV4KGluZGV4OiBudW1iZXIsIGl0ZW06IFZpcnR1YWxJdGVtKTogbnVtYmVyIHtcclxuICAgIHJldHVybiBpdGVtLmluZGV4O1xyXG4gIH1cclxufVxyXG4iLCI8ZGl2IGNsYXNzPVwidmlld3BvcnRcIiAjdmlld3BvcnQgKHNjcm9sbCk9XCJvblNjcm9sbCgpXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwidG90YWwtcGFkZGluZ1wiIFtzdHlsZS5oZWlnaHQucHhdPVwidG90YWxQYWRkaW5nXCI+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cIml0ZW0tY29udGFpbmVyXCIgW3N0eWxlLnRyYW5zZm9ybV09XCIndHJhbnNsYXRlWSgnICsgdG9wUGFkZGluZyArICdweCknXCI+XHJcbiAgICAgICAgICAgIDxkaXYgI3RlbXBsYXRlQ29udGFpbmVyICpuZ0Zvcj1cImxldCBpdGVtIG9mIHZpc2libGVJdGVtczsgdHJhY2tCeTogdHJhY2tCeUluZGV4XCI+XHJcbiAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyIFtuZ1RlbXBsYXRlT3V0bGV0XT1cIm5jSXRlbVRlbXBsYXRlXCIgI3RlbXBsYXRlQ29udGFpbmVyIFxyXG4gICAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7JGltcGxpY2l0OiBpdGVtLmRhdGEsIGluZGV4OiBpdGVtLmluZGV4fVwiPjwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG48L2Rpdj4iXX0=