UNPKG

ng-zorro-antd-mobile

Version:

An enterprise-class mobile UI components based on Ant Design and Angular

356 lines (351 loc) 19 kB
import * as i0 from '@angular/core'; import { EventEmitter, TemplateRef, forwardRef, ViewContainerRef, Component, ViewEncapsulation, ViewChild, Input, Output, HostBinding, HostListener, NgModule } from '@angular/core'; import * as i1 from '@angular/common'; import { CommonModule } from '@angular/common'; import { NG_VALUE_ACCESSOR, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { IconModule } from 'ng-zorro-antd-mobile/icon'; class PullToRefreshComponent { get direction() { return this._direction; } set direction(value) { this._direction = value; this.refreshUp = this._direction === 'up' || this._direction === ''; this.refreshDown = this._direction === 'down' || this._direction === ''; } get headerIndicator() { return this._headerIndicator; } set headerIndicator(value) { Object.assign(this._headerIndicator, value); } get footerIndicator() { return this._footerIndicator; } set footerIndicator(value) { Object.assign(this._footerIndicator, value); } touchstart(e) { this._startTime = Date.now(); if (this._direction === 'down' || (this._direction === '' && !this._endReach)) { if (this.ele.nativeElement.scrollTop > 0) { this.startY = undefined; return; } this.startY = e && e.changedTouches && e.changedTouches[0] && e.changedTouches[0].clientY; this.state.drag = undefined; } else { this.startY = e && e.changedTouches && e.changedTouches[0] && e.changedTouches[0].clientY; this._clientHeight = this._pullToRefresh.element.nativeElement.clientHeight; this._currentContentHeight = this.ele.nativeElement.clientHeight; } this.transtionCls = ''; } touchmove(e) { if (this._direction === 'down' || (this._direction === '' && !this._endReach)) { if (this.ele.nativeElement.scrollTop > 0) { return; } let distanceY = e.changedTouches[0].clientY - this.startY; this.state.drag = distanceY >= 0; if (this.state.drag) { // 禁止滚动 if (e.cancelable) { e.preventDefault(); } } else { return; } if (distanceY > this.damping) { //当超过设定阈值是,缓慢增加 distanceY = (distanceY / (distanceY + this.damping)) * this.damping * 2; } else if (distanceY < 0) { distanceY = 0; } if (distanceY > this.distanceToRefresh) { this.state.currentState = 'activate'; if (this._ngModelOnChange) { this._ngModelOnChange(this.state); } } this.style = { '-webkit-transform': 'translate3d( 0, ' + distanceY + 'px, 0 )', transform: 'translate3d( 0, ' + distanceY + 'px, 0 )' }; } else { let distanceY = e.changedTouches[0].clientY - this.startY; //向上拉动的时候,如果当前窗口内容没有滚到最后,则不实现拖动的动作;向下滚动不实现拖动动作 if (Math.abs(this._lastContentOffset) < this._clientHeight - this._currentContentHeight - this.distanceToRefresh || distanceY > 0) { // 滚动 this.state.drag = false; } else { // 上拉 this.state.drag = true; } if (this.state.drag) { // 禁止滚动 if (e.cancelable) { e.preventDefault(); } } else { return; } //如果滑动到底部了,滑动距离随着拉动的距离增加缓慢增加 distanceY = -(distanceY / (distanceY - this.damping)) * this.damping; if (Math.abs(distanceY) > this.distanceToRefresh) { this.state.currentState = 'activate'; if (this._ngModelOnChange) { this._ngModelOnChange(this.state); } } this.style = { '-webkit-transform': 'translate3d( 0, ' + distanceY + 'px, 0 )', transform: 'translate3d( 0, ' + distanceY + 'px, 0 )' }; } } touchend(e) { if (!this.startY || this.state.drag === false) { return; } const distanceY = e.changedTouches[0].clientY - this.startY; if (Math.abs(distanceY) >= this.distanceToRefresh) { this.state.currentState = 'release'; if (this._direction === 'down' || (this._direction === '' && !this._endReach)) { this.translateY(this.distanceToRefresh + 1); } else { this.translateY(-this.distanceToRefresh - 1); } if (this._ngModelOnChange) { this._ngModelOnChange(this.state); } setTimeout(() => { this.state.currentState = 'finish'; if (this._ngModelOnChange) { this._ngModelOnChange(this.state); } if (this._direction === 'down' || (this._direction === '' && !this._endReach)) { this.onRefresh.emit('down'); } else { this.translateY(-this.distanceToRefresh - 1); this.onRefresh.emit('up'); } setTimeout(() => { this.state.currentState = 'deactivate'; if (this._ngModelOnChange) { this._ngModelOnChange(this.state); } this.translateY(0); }, 0); }, 500); } else { this.translateY(0); } } touchcancel() { this.translateY(0); } scroll(evt) { this._endTime = Date.now(); const contentOffset = evt.target.scrollTop; this._lastContentOffset = contentOffset; if (this._direction === '') { if (contentOffset > 0 && evt.target.scrollTop + this.ele.nativeElement.clientHeight === evt.target.scrollHeight) { setTimeout(() => { this._endReach = true; }, 100); } else { this._endReach = false; } } if (!this.endReachedRefresh || this._direction !== 'down') { return; } if (contentOffset > 0 && evt.target.scrollTop + this.ele.nativeElement.clientHeight > evt.target.scrollHeight - this.distanceToRefresh && this._endTime - this._startTime >= 100) { this._startTime = this._endTime; if (this.refreshing) { this.state.currentState = 'release'; if (this._ngModelOnChange) { this._ngModelOnChange(this.state); } } setTimeout(() => { if (this.endReachedRefresh) { this.onRefresh.emit('endReachedRefresh'); } if (this.refreshing) { this.state.currentState = 'finish'; if (this._ngModelOnChange) { this._ngModelOnChange(this.state); } } }, 500); } else { setTimeout(() => { if (this.refreshing) { this.state.currentState = 'finish'; if (this._ngModelOnChange) { this._ngModelOnChange(this.state); } } }, 500); } } constructor(ele) { this.ele = ele; this.transtionCls = {}; this.style = { '-webkit-transform': 'translate3d( 0, 0, 0 )', transform: 'translate3d( 0, 0, 0 )' }; this.state = { currentState: 'deactivate', drag: false }; this._headerIndicator = { activate: '松开立即刷新', deactivate: '下拉可以刷新', release: '刷新中。。。', finish: '完成刷新' }; this._footerIndicator = { activate: '松开立即刷新', deactivate: '上拉可以刷新', release: '刷新中。。。', finish: '完成刷新' }; this._startTime = 0; this._endTime = 0; this._endReach = false; this._direction = ''; this._clientHeight = 0; this._currentContentHeight = 0; this._lastContentOffset = 0; this.distanceToRefresh = 25; //触发刷新距离 this.damping = 100; // 下拉的最大距离 this.endReachedRefresh = false; this.refreshing = false; this.onRefresh = new EventEmitter(); this.refresh = true; this.container = true; this.refreshUp = this._direction === 'up' || this._direction === ''; this.refreshDown = this._direction === 'down' || this._direction === ''; } isTemplateRef(value) { return value instanceof TemplateRef; } translateY(distanceY) { this.transtionCls = 'am-pull-to-refresh-transition'; this.style = { '-webkit-transform': 'translate3d( 0, ' + distanceY + 'px, 0 )', transform: 'translate3d( 0, ' + distanceY + 'px, 0 )' }; } writeValue(value) { if (value !== null) { this.state = value; } } registerOnChange(fn) { this._ngModelOnChange = fn; } registerOnTouched(fn) { this._ngModelOnTouched = fn; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: PullToRefreshComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.8", type: PullToRefreshComponent, selector: "PullToRefresh, nzm-pull-to-refresh", inputs: { distanceToRefresh: "distanceToRefresh", damping: "damping", endReachedRefresh: "endReachedRefresh", refreshing: "refreshing", direction: "direction", headerIndicator: "headerIndicator", footerIndicator: "footerIndicator" }, outputs: { onRefresh: "onRefresh" }, host: { listeners: { "touchstart": "touchstart($event)", "touchmove": "touchmove($event)", "touchend": "touchend($event)", "touchcancel": "touchcancel()", "scroll": "scroll($event)" }, properties: { "class.am-pull-to-refresh": "this.refresh", "class.super-container": "this.container", "class.am-pull-to-refresh-up": "this.refreshUp", "class.am-pull-to-refresh-down": "this.refreshDown" } }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => PullToRefreshComponent), multi: true } ], viewQueries: [{ propertyName: "_pullToRefresh", first: true, predicate: ["pullToRefresh"], descendants: true, read: ViewContainerRef, static: true }], ngImport: i0, template: "<div class=\"am-pull-to-refresh-content-wrapper\">\n <div class=\"am-pull-to-refresh-content\" [ngClass]=\"transtionCls\" [ngStyle]=\"style\">\n <div *ngIf=\"refreshDown\" class=\"am-pull-to-refresh-indicator am-pull-to-refresh-header-indicator\">\n <ng-template\n *ngIf=\"isTemplateRef(headerIndicator[state.currentState])\"\n [ngTemplateOutlet]=\"headerIndicator[state.currentState]\"\n ></ng-template>\n <ng-container *ngIf=\"!isTemplateRef(headerIndicator[state.currentState])\">{{\n headerIndicator[state.currentState]\n }}</ng-container>\n </div>\n <div #pullToRefresh>\n <ng-content></ng-content>\n <div\n *ngIf=\"direction === 'down' && endReachedRefresh\"\n class=\"am-pull-to-refresh-indicator am-pull-to-refresh-footer-indicator\"\n >\n <ng-template\n *ngIf=\"isTemplateRef(footerIndicator[state.currentState])\"\n [ngTemplateOutlet]=\"footerIndicator[state.currentState]\"\n ></ng-template>\n <ng-container *ngIf=\"!isTemplateRef(footerIndicator[state.currentState])\">{{\n footerIndicator[state.currentState]\n }}</ng-container>\n </div>\n </div>\n <div *ngIf=\"refreshUp\" class=\"am-pull-to-refresh-indicator am-pull-to-refresh-footer-indicator\">\n <ng-template\n *ngIf=\"isTemplateRef(footerIndicator[state.currentState])\"\n [ngTemplateOutlet]=\"footerIndicator[state.currentState]\"\n ></ng-template>\n <ng-container *ngIf=\"!isTemplateRef(footerIndicator[state.currentState])\">{{\n footerIndicator[state.currentState]\n }}</ng-container>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: PullToRefreshComponent, decorators: [{ type: Component, args: [{ selector: 'PullToRefresh, nzm-pull-to-refresh', encapsulation: ViewEncapsulation.None, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => PullToRefreshComponent), multi: true } ], template: "<div class=\"am-pull-to-refresh-content-wrapper\">\n <div class=\"am-pull-to-refresh-content\" [ngClass]=\"transtionCls\" [ngStyle]=\"style\">\n <div *ngIf=\"refreshDown\" class=\"am-pull-to-refresh-indicator am-pull-to-refresh-header-indicator\">\n <ng-template\n *ngIf=\"isTemplateRef(headerIndicator[state.currentState])\"\n [ngTemplateOutlet]=\"headerIndicator[state.currentState]\"\n ></ng-template>\n <ng-container *ngIf=\"!isTemplateRef(headerIndicator[state.currentState])\">{{\n headerIndicator[state.currentState]\n }}</ng-container>\n </div>\n <div #pullToRefresh>\n <ng-content></ng-content>\n <div\n *ngIf=\"direction === 'down' && endReachedRefresh\"\n class=\"am-pull-to-refresh-indicator am-pull-to-refresh-footer-indicator\"\n >\n <ng-template\n *ngIf=\"isTemplateRef(footerIndicator[state.currentState])\"\n [ngTemplateOutlet]=\"footerIndicator[state.currentState]\"\n ></ng-template>\n <ng-container *ngIf=\"!isTemplateRef(footerIndicator[state.currentState])\">{{\n footerIndicator[state.currentState]\n }}</ng-container>\n </div>\n </div>\n <div *ngIf=\"refreshUp\" class=\"am-pull-to-refresh-indicator am-pull-to-refresh-footer-indicator\">\n <ng-template\n *ngIf=\"isTemplateRef(footerIndicator[state.currentState])\"\n [ngTemplateOutlet]=\"footerIndicator[state.currentState]\"\n ></ng-template>\n <ng-container *ngIf=\"!isTemplateRef(footerIndicator[state.currentState])\">{{\n footerIndicator[state.currentState]\n }}</ng-container>\n </div>\n </div>\n</div>\n" }] }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { _pullToRefresh: [{ type: ViewChild, args: ['pullToRefresh', { read: ViewContainerRef, static: true }] }], distanceToRefresh: [{ type: Input }], damping: [{ type: Input }], endReachedRefresh: [{ type: Input }], refreshing: [{ type: Input }], direction: [{ type: Input }], headerIndicator: [{ type: Input }], footerIndicator: [{ type: Input }], onRefresh: [{ type: Output }], refresh: [{ type: HostBinding, args: ['class.am-pull-to-refresh'] }], container: [{ type: HostBinding, args: ['class.super-container'] }], refreshUp: [{ type: HostBinding, args: ['class.am-pull-to-refresh-up'] }], refreshDown: [{ type: HostBinding, args: ['class.am-pull-to-refresh-down'] }], touchstart: [{ type: HostListener, args: ['touchstart', ['$event']] }], touchmove: [{ type: HostListener, args: ['touchmove', ['$event']] }], touchend: [{ type: HostListener, args: ['touchend', ['$event']] }], touchcancel: [{ type: HostListener, args: ['touchcancel'] }], scroll: [{ type: HostListener, args: ['scroll', ['$event']] }] } }); class PullToRefreshModule { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: PullToRefreshModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.0.8", ngImport: i0, type: PullToRefreshModule, declarations: [PullToRefreshComponent], imports: [CommonModule, IconModule, FormsModule, ReactiveFormsModule], exports: [PullToRefreshComponent] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: PullToRefreshModule, imports: [CommonModule, IconModule, FormsModule, ReactiveFormsModule] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: PullToRefreshModule, decorators: [{ type: NgModule, args: [{ imports: [CommonModule, IconModule, FormsModule, ReactiveFormsModule], exports: [PullToRefreshComponent], declarations: [PullToRefreshComponent] }] }] }); /** * Generated bundle index. Do not edit. */ export { PullToRefreshComponent, PullToRefreshModule }; //# sourceMappingURL=ng-zorro-antd-mobile-pull-to-refresh.mjs.map