ng-zorro-antd-mobile
Version:
An enterprise-class mobile UI components based on Ant Design and Angular
356 lines (351 loc) • 19 kB
JavaScript
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