Skip to content

Commit c09d2f8

Browse files
chore(release): release 16.1.0 (#326)
Co-authored-by: huaweidevcloud <devcloudmobile@huawei.com>
1 parent 8456cba commit c09d2f8

File tree

130 files changed

+1756
-1145
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

130 files changed

+1756
-1145
lines changed
Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,34 @@
1-
<div (click)="goTop()" class="devui-backtop" [ngStyle]="{ display: isVisible ? 'block' : 'none', bottom: bottom, right: right }">
2-
<ng-template [ngTemplateOutlet]="customTemplate ? customTemplate : default"></ng-template>
3-
<ng-template #default>
4-
<div class="devui-backtop-content">
5-
<svg
6-
width="16px"
7-
height="16px"
8-
viewBox="0 0 16 16"
9-
version="1.1"
10-
xmlns="http://www.w3.org/2000/svg"
11-
xmlns:xlink="http://www.w3.org/1999/xlink"
12-
>
13-
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
14-
<path
15-
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"
16-
fill="#FFFFFF"
17-
fill-rule="nonzero"
18-
></path>
19-
</g>
20-
</svg>
21-
</div>
22-
</ng-template>
1+
<div
2+
class="devui-backtop"
3+
[ngStyle]="{
4+
display: isVisible ? 'block' : 'none',
5+
bottom: bottom,
6+
right: right,
7+
cursor: moveCursor && draggable ? 'move' : 'pointer'
8+
}"
9+
(click)="goTop()"
10+
>
11+
<div class="devui-backtop-drag-handle" (mousedown)="mousedownEvent($event)" (mouseleave)="mouseleaveEvent()" (click)="clickEvent($event)">
12+
<ng-template [ngTemplateOutlet]="customTemplate ? customTemplate : default"></ng-template>
13+
<ng-template #default>
14+
<div class="devui-backtop-content">
15+
<svg
16+
width="16px"
17+
height="16px"
18+
viewBox="0 0 16 16"
19+
version="1.1"
20+
xmlns="http://www.w3.org/2000/svg"
21+
xmlns:xlink="http://www.w3.org/1999/xlink"
22+
>
23+
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
24+
<path
25+
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"
26+
fill="#FFFFFF"
27+
fill-rule="nonzero"
28+
></path>
29+
</g>
30+
</svg>
31+
</div>
32+
</ng-template>
33+
</div>
2334
</div>

devui/back-top/back-top.component.scss

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@
44
width: 40px;
55
height: 40px;
66
position: fixed;
7-
cursor: pointer;
87
z-index: 1;
98

9+
.devui-backtop-drag-handle {
10+
cursor: unset !important;
11+
}
12+
1013
&-content {
1114
width: 40px;
1215
height: 40px;

devui/back-top/back-top.component.ts

Lines changed: 159 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,20 @@
11
import { DOCUMENT } from '@angular/common';
22
import {
3-
ChangeDetectionStrategy, ChangeDetectorRef, Component,
4-
ElementRef, EventEmitter, Inject, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, TemplateRef
3+
AfterViewInit,
4+
ChangeDetectionStrategy,
5+
ChangeDetectorRef,
6+
Component,
7+
ElementRef,
8+
EventEmitter,
9+
HostListener,
10+
Inject,
11+
Input,
12+
OnChanges,
13+
OnDestroy,
14+
OnInit,
15+
Output,
16+
SimpleChanges,
17+
TemplateRef
518
} from '@angular/core';
619
import { fromEvent, Subscription } from 'rxjs';
720
import { debounceTime } from 'rxjs/operators';
@@ -12,30 +25,35 @@ import { debounceTime } from 'rxjs/operators';
1225
styleUrls: ['./back-top.component.scss'],
1326
changeDetection: ChangeDetectionStrategy.OnPush,
1427
preserveWhitespaces: false,
15-
})
16-
export class BackTopComponent implements OnInit, OnChanges, OnDestroy {
28+
})
29+
export class BackTopComponent implements OnChanges, OnInit, OnDestroy, AfterViewInit {
1730
@Input() customTemplate: TemplateRef<any>;
1831
@Input() visibleHeight = 300;
1932
@Input() bottom = '50px';
2033
@Input() right = '30px';
2134
@Input() scrollTarget: HTMLElement;
22-
@Output() backTopEvent = new EventEmitter<boolean>();
35+
@Input() draggable = false;
36+
@Output() backTopEvent = new EventEmitter<boolean>();
37+
@Output() dragEvent = new EventEmitter<boolean>();
2338

2439
currScrollTop = 0;
40+
duration = 0;
41+
cursorTimer: any;
42+
dragBoundary: any;
43+
moveCursor = false;
2544
isVisible = false;
26-
SCROLL_REFRESH_INTERVAL = 100;
2745
target: HTMLElement | Window;
2846
subs: Subscription = new Subscription();
2947
document: Document;
48+
49+
SCROLL_REFRESH_INTERVAL = 100;
50+
MOUSEDOWN_DELAY = 180;
51+
RESIZE_DELAY = 300;
52+
3053
constructor(private cdr: ChangeDetectorRef, private el: ElementRef, @Inject(DOCUMENT) private doc: any) {
3154
this.document = this.doc;
3255
}
3356

34-
ngOnInit() {
35-
this.addScrollEvent();
36-
this.showButton();
37-
}
38-
3957
ngOnChanges(changes: SimpleChanges): void {
4058
if (changes['scrollTarget']) {
4159
if (this.subs) {
@@ -46,6 +64,42 @@ export class BackTopComponent implements OnInit, OnChanges, OnDestroy {
4664
}
4765
}
4866

67+
ngOnInit(): void {
68+
this.addScrollEvent();
69+
this.showButton();
70+
}
71+
72+
ngAfterViewInit(): void {
73+
if (this.draggable) {
74+
// 窗口大小改变时,如缩放比例或组件超出显示范围重置到默认位置
75+
this.subs.add(
76+
fromEvent(window, 'resize')
77+
.pipe(debounceTime(this.RESIZE_DELAY))
78+
.subscribe(() => {
79+
const dom = this.dragBoundary?.dom || this.el.nativeElement.querySelector('div.devui-backtop');
80+
if (dom) {
81+
// 不显示时无法获取getBoundingClientRect,使用style获取
82+
const style = getComputedStyle(dom);
83+
const left = parseInt(style.left, 10) || 0;
84+
const top = parseInt(style.top, 10) || 0;
85+
if (window.devicePixelRatio !== 1 || left > window.innerWidth || top > window.innerHeight) {
86+
this.onMouseUp();
87+
this.duration = 0;
88+
dom.style.left = 'unset';
89+
dom.style.top = 'unset';
90+
}
91+
}
92+
})
93+
);
94+
}
95+
}
96+
97+
ngOnDestroy(): void {
98+
if (this.subs) {
99+
this.subs.unsubscribe();
100+
}
101+
}
102+
49103
addScrollEvent() {
50104
this.subs.add(
51105
fromEvent(this.getScrollTarget(), 'scroll')
@@ -67,9 +121,11 @@ export class BackTopComponent implements OnInit, OnChanges, OnDestroy {
67121
}
68122

69123
showButton() {
70-
this.currScrollTop = this.target === window ?
71-
(window.pageYOffset || this.document.documentElement.scrollTop || this.document.body.scrollTop) : this.scrollTarget.scrollTop;
72-
if (this.isVisible !== (this.currScrollTop >= this.visibleHeight)) {
124+
this.currScrollTop =
125+
this.target === window
126+
? window.pageYOffset || this.document.documentElement.scrollTop || this.document.body.scrollTop
127+
: this.scrollTarget.scrollTop;
128+
if (this.isVisible !== this.currScrollTop >= this.visibleHeight) {
73129
this.isVisible = !this.isVisible;
74130
}
75131
}
@@ -85,9 +141,95 @@ export class BackTopComponent implements OnInit, OnChanges, OnDestroy {
85141
this.backTopEvent.emit(true);
86142
}
87143

88-
ngOnDestroy() {
89-
if (this.subs) {
90-
this.subs.unsubscribe();
144+
setDragBoundary() {
145+
const dom = this.el.nativeElement.querySelector('div.devui-backtop');
146+
let boxRect;
147+
let minLeft;
148+
let minTop;
149+
let maxLeft;
150+
let maxTop;
151+
if (dom) {
152+
const { width, height } = dom.getBoundingClientRect();
153+
if (this.scrollTarget) {
154+
boxRect = this.scrollTarget.getBoundingClientRect();
155+
minLeft = -1 * boxRect.x;
156+
minTop = -1 * boxRect.y;
157+
maxLeft = window.innerWidth - boxRect.x - width;
158+
maxTop = window.innerHeight - boxRect.y - height;
159+
} else {
160+
boxRect = { x: 0, y: 0 };
161+
minLeft = 0;
162+
minTop = 0;
163+
maxLeft = window.innerWidth - width;
164+
maxTop = window.innerHeight - height;
165+
}
166+
this.dragBoundary = { dom, boxRect, minLeft, minTop, maxLeft, maxTop };
167+
}
168+
}
169+
170+
// mousedown mouseup click 按顺序触发且前一个结束触发下一个
171+
mousedownEvent(event: MouseEvent) {
172+
if (this.draggable) {
173+
event.preventDefault();
174+
this.cursorTimer = setTimeout(() => {
175+
this.setDragBoundary();
176+
this.duration = new Date().getTime();
177+
this.moveCursor = true;
178+
this.cdr.markForCheck();
179+
this.dragEvent.emit(true);
180+
}, this.MOUSEDOWN_DELAY);
181+
}
182+
}
183+
184+
mouseleaveEvent() {
185+
if (this.draggable && this.cursorTimer) {
186+
clearTimeout(this.cursorTimer);
187+
}
188+
}
189+
190+
clickEvent(event: MouseEvent) {
191+
if (this.draggable && this.duration > this.MOUSEDOWN_DELAY) {
192+
event.stopPropagation();
193+
this.duration = 0;
194+
}
195+
}
196+
197+
@HostListener('document:mouseup', [])
198+
onMouseUp() {
199+
if (this.draggable) {
200+
if (this.cursorTimer) {
201+
clearTimeout(this.cursorTimer);
202+
}
203+
if (this.moveCursor) {
204+
this.moveCursor = false;
205+
this.cdr.markForCheck();
206+
this.dragEvent.emit(false);
207+
}
208+
this.duration = this.duration && new Date().getTime() - this.duration;
209+
}
210+
}
211+
212+
@HostListener('document:mousemove', ['$event'])
213+
onMouseMove(event: MouseEvent) {
214+
if (this.draggable && this.moveCursor && this.dragBoundary) {
215+
// 先判断再执行阻止默认事件,否则可能影响鼠标拖选功能
216+
event.preventDefault();
217+
const posX = event.movementX;
218+
const posY = event.movementY;
219+
const rect = this.dragBoundary.dom.getBoundingClientRect();
220+
const left = rect.x - this.dragBoundary.boxRect.x + posX;
221+
const top = rect.y - this.dragBoundary.boxRect.y + posY;
222+
const isLeft = left < this.dragBoundary.minLeft;
223+
const isRight = left > this.dragBoundary.maxLeft;
224+
const isTop = top < this.dragBoundary.minTop;
225+
const isBottom = top > this.dragBoundary.maxTop;
226+
this.dragBoundary.dom.style.left = `${isRight ? this.dragBoundary.maxLeft : isLeft ? this.dragBoundary.minLeft : left}px`;
227+
this.dragBoundary.dom.style.top = `${isBottom ? this.dragBoundary.maxTop : isTop ? this.dragBoundary.minTop : top}px`;
228+
// 如到达边界释放拖拽动作,避免鼠标偏移较大距离后返回主视窗仍可拖拽
229+
if ([isLeft, isRight, isTop, isBottom].includes(true)) {
230+
this.onMouseUp();
231+
this.duration = 0;
232+
}
91233
}
92234
}
93235
}

devui/back-top/demo/customize/customize.component.html

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
<div class="devui-backtop-custom">
22
<span class="icon-chevron-up"></span>
33
</div>
4-
<d-back-top (backTopEvent)="backTop($event)" [customTemplate]="customTemplate" [bottom]="'100px'" [visibleHeight]="200">
4+
<d-back-top
5+
[customTemplate]="customTemplate"
6+
[bottom]="'100px'"
7+
[visibleHeight]="200"
8+
[draggable]="true"
9+
(dragEvent)="toggleTooltip($event)"
10+
(backTopEvent)="backTop($event)"
11+
>
512
<ng-template #customTemplate>
6-
<div class="devui-backtop-custom" dTooltip [content]="'BackTop'" [position]="'left'">
13+
<div #tooltipItem class="devui-backtop-custom" dTooltip [content]="content" [position]="'left'">
714
<span class="icon-chevron-up"></span>
815
</div>
916
</ng-template>

devui/back-top/demo/customize/customize.component.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,25 @@
1-
import { Component } from '@angular/core';
1+
import { Component, ViewChild } from '@angular/core';
2+
import { TooltipDirective } from 'ng-devui/tooltip';
23

34
@Component({
45
selector: 'd-back-top-customize',
56
templateUrl: './customize.component.html',
6-
styleUrls: ['./customize.component.scss']
7-
})
8-
7+
styleUrls: ['./customize.component.scss'],
8+
})
99
export class CustomizeComponent {
10-
constructor() {}
10+
@ViewChild('tooltipItem', { read: TooltipDirective }) tooltipItem: TooltipDirective;
11+
content = 'Back to the top';
12+
13+
toggleTooltip(toggle) {
14+
if (this.tooltipItem) {
15+
if (toggle) {
16+
this.tooltipItem.content = '';
17+
this.tooltipItem.hide();
18+
} else {
19+
this.tooltipItem.content = this.content;
20+
}
21+
}
22+
}
1123

1224
backTop(event) {
1325
console.log(event);

devui/back-top/demo/scroll-container/scroll-container.component.html

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,11 @@
44
{{ index + 1 + '. ' + item }}
55
</li>
66
</ul>
7-
<d-back-top [scrollTarget]="scrollElement" [right]="'30px'" [bottom]="'10px'" (backTopEvent)="backTop($event)"></d-back-top>
7+
<d-back-top
8+
[draggable]="true"
9+
[scrollTarget]="scrollElement"
10+
[right]="'60px'"
11+
[bottom]="'30px'"
12+
(backTopEvent)="backTop($event)"
13+
></d-back-top>
814
</div>

0 commit comments

Comments
 (0)