UNPKG

ng-devui

Version:

DevUI components based on Angular

248 lines (243 loc) 15.4 kB
import * as i1 from '@angular/common'; import { DOCUMENT, CommonModule } from '@angular/common'; import * as i0 from '@angular/core'; import { EventEmitter, Component, ChangeDetectionStrategy, Inject, Input, Output, HostListener, NgModule } from '@angular/core'; import { Subscription, fromEvent } from 'rxjs'; import { debounceTime } from 'rxjs/operators'; class BackTopComponent { constructor(cdr, el, doc) { this.cdr = cdr; this.el = el; this.doc = doc; this.visibleHeight = 300; this.bottom = '50px'; this.right = '30px'; this.draggable = false; this.backTopEvent = new EventEmitter(); this.dragEvent = new EventEmitter(); this.currScrollTop = 0; this.duration = 0; this.moveCursor = false; this.moveToggle = false; this.isVisible = false; this.subs = new Subscription(); this.SCROLL_REFRESH_INTERVAL = 100; this.MOUSEDOWN_DELAY = 180; this.RESIZE_DELAY = 300; this.document = this.doc; } ngOnChanges(changes) { if (changes.scrollTarget) { if (this.subs) { this.subs.unsubscribe(); } this.subs = new Subscription(); this.addScrollEvent(); } } ngOnInit() { this.addScrollEvent(); this.showButton(); } ngAfterViewInit() { if (this.draggable) { // 窗口大小改变时,如缩放比例或组件超出显示范围重置到默认位置 this.subs.add(fromEvent(window, 'resize') .pipe(debounceTime(this.RESIZE_DELAY)) .subscribe(() => { const dom = this.dragBoundary?.dom || this.el.nativeElement.querySelector('div.devui-backtop'); if (dom) { // 不显示时无法获取getBoundingClientRect,使用style获取 const style = getComputedStyle(dom); const left = parseInt(style.left, 10) || 0; const top = parseInt(style.top, 10) || 0; if (window.devicePixelRatio !== 1 || left > window.innerWidth || top > window.innerHeight) { this.onMouseUp(); this.duration = 0; dom.style.left = 'unset'; dom.style.top = 'unset'; } } })); } } ngOnDestroy() { if (this.subs) { this.subs.unsubscribe(); } } addScrollEvent() { this.subs.add(fromEvent(this.getScrollTarget(), 'scroll') .pipe(debounceTime(this.SCROLL_REFRESH_INTERVAL)) .subscribe(() => { this.showButton(); this.cdr.detectChanges(); })); } getScrollTarget() { if (this.scrollTarget) { this.el.nativeElement.querySelector('.devui-backtop').style.position = 'absolute'; this.scrollTarget.parentElement.style.position = 'relative'; } this.target = this.scrollTarget || window; return this.target; } showButton() { this.currScrollTop = this.target === window ? window.pageYOffset || this.document.documentElement.scrollTop || this.document.body.scrollTop : this.scrollTarget.scrollTop; if (this.isVisible !== this.currScrollTop >= this.visibleHeight) { this.isVisible = !this.isVisible; } } goTop() { if (this.draggable && this.duration > this.MOUSEDOWN_DELAY) { this.duration = 0; return; } if (this.target === window) { this.document.documentElement.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'nearest' }); this.document.body.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'nearest' }); } else { this.scrollTarget.style.scrollBehavior = 'smooth'; this.scrollTarget.scrollTop = 0; } this.duration = 0; this.backTopEvent.emit(true); } setDragBoundary() { const dom = this.el.nativeElement.querySelector('div.devui-backtop'); let boxRect; let minLeft; let minTop; let maxLeft; let maxTop; if (dom) { const { width, height } = dom.getBoundingClientRect(); if (this.scrollTarget) { boxRect = this.scrollTarget.getBoundingClientRect(); minLeft = -1 * boxRect.x; minTop = -1 * boxRect.y; maxLeft = window.innerWidth - boxRect.x - width; maxTop = window.innerHeight - boxRect.y - height; } else { boxRect = { x: 0, y: 0 }; minLeft = 0; minTop = 0; maxLeft = window.innerWidth - width; maxTop = window.innerHeight - height; } this.dragBoundary = { dom, boxRect, minLeft, minTop, maxLeft, maxTop }; } } // mousedown mouseup click 按顺序触发且前一个结束触发下一个 mousedownEvent(event) { if (this.draggable) { event.preventDefault(); this.setDragBoundary(); this.duration = new Date().getTime(); this.moveToggle = true; this.cursorTimer = setTimeout(() => { this.moveCursor = true; this.dragEvent.emit(true); }, this.MOUSEDOWN_DELAY); } } mouseleaveEvent() { if (this.draggable && this.cursorTimer) { clearTimeout(this.cursorTimer); } } onMouseUp() { if (this.draggable) { if (this.cursorTimer) { clearTimeout(this.cursorTimer); } if (this.moveToggle) { this.moveToggle = false; this.moveCursor = false; this.dragEvent.emit(false); } this.duration = this.duration && new Date().getTime() - this.duration; } } onMouseMove(event) { if (this.draggable && this.moveToggle && this.dragBoundary) { // 先判断再执行阻止默认事件,否则可能影响鼠标拖选功能 event.preventDefault(); this.moveCursor = true; const posX = event.movementX; const posY = event.movementY; const rect = this.dragBoundary.dom.getBoundingClientRect(); const left = rect.x - this.dragBoundary.boxRect.x + posX; const top = rect.y - this.dragBoundary.boxRect.y + posY; const isLeft = left < this.dragBoundary.minLeft; const isRight = left > this.dragBoundary.maxLeft; const isTop = top < this.dragBoundary.minTop; const isBottom = top > this.dragBoundary.maxTop; const leftResult = isLeft ? this.dragBoundary.minLeft : left; const topResult = isTop ? this.dragBoundary.minTop : top; this.dragBoundary.dom.style.left = `${isRight ? this.dragBoundary.maxLeft : leftResult}px`; this.dragBoundary.dom.style.top = `${isBottom ? this.dragBoundary.maxTop : topResult}px`; // 如到达边界释放拖拽动作,避免鼠标偏移较大距离后返回主视窗仍可拖拽 if ([isLeft, isRight, isTop, isBottom].includes(true)) { this.onMouseUp(); this.duration = 0; } } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BackTopComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: BackTopComponent, selector: "d-back-top", inputs: { customTemplate: "customTemplate", visibleHeight: "visibleHeight", bottom: "bottom", right: "right", scrollTarget: "scrollTarget", draggable: "draggable" }, outputs: { backTopEvent: "backTopEvent", dragEvent: "dragEvent" }, host: { listeners: { "document:mouseup": "onMouseUp()", "document:mousemove": "onMouseMove($event)" } }, usesOnChanges: true, ngImport: i0, template: "<div\n class=\"devui-backtop\"\n [ngStyle]=\"{\n display: isVisible ? 'block' : 'none',\n bottom: bottom,\n right: right,\n cursor: moveCursor && draggable ? 'move' : 'pointer'\n }\"\n (click)=\"goTop()\"\n>\n <div class=\"devui-backtop-drag-handle\" (mousedown)=\"mousedownEvent($event)\" (mouseleave)=\"mouseleaveEvent()\">\n <ng-template [ngTemplateOutlet]=\"customTemplate ? customTemplate : default\"></ng-template>\n <ng-template #default>\n <div class=\"devui-backtop-content\">\n <svg\n width=\"16px\"\n height=\"16px\"\n viewBox=\"0 0 16 16\"\n version=\"1.1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n >\n <g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <path\n d=\"M8.71335931,15.2865297 C8.61179683,16.2090609 7.32293758,16.1267953 7.27304695,15.2865297 C7.27175008,14.6475142 7.27175008,5.26479636 7.27175008,5.26479636 L2.83675052,9.54548344 C2.14185995,10.1440615 1.3143288,9.18731159 1.83135998,8.55773353 C3.79557855,6.65310872 7.3202657,3.24515592 7.40179694,3.16632781 C7.72696878,2.81306222 8.23887498,2.79476534 8.58495308,3.16632781 C9.23193739,3.7919215 14.0334057,8.42146792 14.1791557,8.58804603 C14.66614,9.19338972 13.8787807,10.0892021 13.2066089,9.58451469 C13.0329683,9.43717095 8.71468744,5.26462448 8.71468744,5.26462448 L8.71335931,15.2865297 Z M1.81868811,-8.54871729e-14 L14.1075619,-8.54871729e-14 L14.1075619,1.39509361 L1.81868811,1.39509361 L1.81868811,-8.54871729e-14 Z\"\n fill=\"#FFFFFF\"\n fill-rule=\"nonzero\"\n ></path>\n </g>\n </svg>\n </div>\n </ng-template>\n </div>\n</div>\n", styles: [".devui-backtop{width:40px;height:40px;position:fixed;z-index:1}.devui-backtop .devui-backtop-drag-handle{cursor:unset!important}.devui-backtop-content{width:40px;height:40px;background-color:var(--devui-text-weak, #333333);opacity:.4;border-radius:50%;display:flex;align-items:center;justify-content:center}.devui-backtop-content:hover{opacity:1}\n"], dependencies: [{ kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BackTopComponent, decorators: [{ type: Component, args: [{ selector: 'd-back-top', changeDetection: ChangeDetectionStrategy.OnPush, preserveWhitespaces: false, template: "<div\n class=\"devui-backtop\"\n [ngStyle]=\"{\n display: isVisible ? 'block' : 'none',\n bottom: bottom,\n right: right,\n cursor: moveCursor && draggable ? 'move' : 'pointer'\n }\"\n (click)=\"goTop()\"\n>\n <div class=\"devui-backtop-drag-handle\" (mousedown)=\"mousedownEvent($event)\" (mouseleave)=\"mouseleaveEvent()\">\n <ng-template [ngTemplateOutlet]=\"customTemplate ? customTemplate : default\"></ng-template>\n <ng-template #default>\n <div class=\"devui-backtop-content\">\n <svg\n width=\"16px\"\n height=\"16px\"\n viewBox=\"0 0 16 16\"\n version=\"1.1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n >\n <g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <path\n d=\"M8.71335931,15.2865297 C8.61179683,16.2090609 7.32293758,16.1267953 7.27304695,15.2865297 C7.27175008,14.6475142 7.27175008,5.26479636 7.27175008,5.26479636 L2.83675052,9.54548344 C2.14185995,10.1440615 1.3143288,9.18731159 1.83135998,8.55773353 C3.79557855,6.65310872 7.3202657,3.24515592 7.40179694,3.16632781 C7.72696878,2.81306222 8.23887498,2.79476534 8.58495308,3.16632781 C9.23193739,3.7919215 14.0334057,8.42146792 14.1791557,8.58804603 C14.66614,9.19338972 13.8787807,10.0892021 13.2066089,9.58451469 C13.0329683,9.43717095 8.71468744,5.26462448 8.71468744,5.26462448 L8.71335931,15.2865297 Z M1.81868811,-8.54871729e-14 L14.1075619,-8.54871729e-14 L14.1075619,1.39509361 L1.81868811,1.39509361 L1.81868811,-8.54871729e-14 Z\"\n fill=\"#FFFFFF\"\n fill-rule=\"nonzero\"\n ></path>\n </g>\n </svg>\n </div>\n </ng-template>\n </div>\n</div>\n", styles: [".devui-backtop{width:40px;height:40px;position:fixed;z-index:1}.devui-backtop .devui-backtop-drag-handle{cursor:unset!important}.devui-backtop-content{width:40px;height:40px;background-color:var(--devui-text-weak, #333333);opacity:.4;border-radius:50%;display:flex;align-items:center;justify-content:center}.devui-backtop-content:hover{opacity:1}\n"] }] }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT] }] }], propDecorators: { customTemplate: [{ type: Input }], visibleHeight: [{ type: Input }], bottom: [{ type: Input }], right: [{ type: Input }], scrollTarget: [{ type: Input }], draggable: [{ type: Input }], backTopEvent: [{ type: Output }], dragEvent: [{ type: Output }], onMouseUp: [{ type: HostListener, args: ['document:mouseup', []] }], onMouseMove: [{ type: HostListener, args: ['document:mousemove', ['$event']] }] } }); class BackTopModule { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BackTopModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: BackTopModule, declarations: [BackTopComponent], imports: [CommonModule], exports: [BackTopComponent] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BackTopModule, imports: [CommonModule] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BackTopModule, decorators: [{ type: NgModule, args: [{ imports: [ CommonModule ], exports: [BackTopComponent], declarations: [BackTopComponent] }] }] }); /** * Generated bundle index. Do not edit. */ export { BackTopComponent, BackTopModule }; //# sourceMappingURL=ng-devui-back-top.mjs.map