逻辑修改
This commit is contained in:
@@ -51,8 +51,8 @@ interface IDraggableResizableOptions {
|
||||
target: HTMLElement;
|
||||
/** 拖拽句柄 */
|
||||
handle?: HTMLElement;
|
||||
/** 拖拽边界或容器元素 */
|
||||
boundary?: IBoundaryRect | HTMLElement;
|
||||
/** 拖拽边界容器元素 */
|
||||
boundaryElement?: HTMLElement;
|
||||
/** 移动步进(网格吸附) */
|
||||
snapGrid?: number;
|
||||
/** 关键点吸附阈值 */
|
||||
@@ -110,7 +110,7 @@ interface IBoundaryRect {
|
||||
export class DraggableResizableWindow {
|
||||
private handle?: HTMLElement;
|
||||
private target: HTMLElement;
|
||||
private boundary?: HTMLElement | IBoundaryRect;
|
||||
private boundaryElement: HTMLElement;
|
||||
private snapGrid: number;
|
||||
private snapThreshold: number;
|
||||
private snapAnimation: boolean;
|
||||
@@ -153,7 +153,7 @@ export class DraggableResizableWindow {
|
||||
private maxWidth: number;
|
||||
private maxHeight: number;
|
||||
|
||||
private containerRect?: DOMRect;
|
||||
private containerRect: DOMRect;
|
||||
private resizeObserver?: ResizeObserver;
|
||||
private mutationObserver: MutationObserver;
|
||||
private animationFrame?: number;
|
||||
@@ -174,7 +174,7 @@ export class DraggableResizableWindow {
|
||||
constructor(options: IDraggableResizableOptions) {
|
||||
this.handle = options.handle;
|
||||
this.target = options.target;
|
||||
this.boundary = options.boundary;
|
||||
this.boundaryElement = options.boundaryElement ?? document.body;
|
||||
this.snapGrid = options.snapGrid ?? 1;
|
||||
this.snapThreshold = options.snapThreshold ?? 0;
|
||||
this.snapAnimation = options.snapAnimation ?? false;
|
||||
@@ -193,15 +193,6 @@ export class DraggableResizableWindow {
|
||||
this.onResizeEnd = options.onResizeEnd;
|
||||
this.onWindowStateChange = options.onWindowStateChange;
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
this.targetBounds = {
|
||||
width: this.target.offsetWidth,
|
||||
height: this.target.offsetHeight,
|
||||
top: this.target.offsetTop,
|
||||
left: this.target.offsetLeft,
|
||||
};
|
||||
});
|
||||
|
||||
this.taskbarElementId = options.taskbarElementId;
|
||||
|
||||
this.target.style.position = "absolute";
|
||||
@@ -210,6 +201,19 @@ export class DraggableResizableWindow {
|
||||
this.target.style.transform = "translate(0px, 0px)";
|
||||
|
||||
this.init();
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
this.targetBounds = {
|
||||
width: this.target.offsetWidth,
|
||||
height: this.target.offsetHeight,
|
||||
top: this.target.offsetTop,
|
||||
left: this.target.offsetLeft,
|
||||
};
|
||||
this.containerRect = this.boundaryElement.getBoundingClientRect();
|
||||
const x = this.containerRect.width / 2 - this.target.offsetWidth / 2;
|
||||
const y = this.containerRect.height / 2 - this.target.offsetHeight / 2;
|
||||
this.target.style.transform = `translate(${x}px, ${y}px)`;
|
||||
});
|
||||
}
|
||||
|
||||
private init() {
|
||||
@@ -220,7 +224,7 @@ export class DraggableResizableWindow {
|
||||
this.target.addEventListener('mouseleave', this.onMouseLeave);
|
||||
document.addEventListener('mousemove', this.onDocumentMouseMoveCursor);
|
||||
|
||||
if (this.boundary instanceof HTMLElement) this.observeResize(this.boundary);
|
||||
this.observeResize(this.boundaryElement);
|
||||
|
||||
this.mutationObserver = new MutationObserver(mutations => {
|
||||
for (const mutation of mutations) {
|
||||
@@ -382,19 +386,12 @@ export class DraggableResizableWindow {
|
||||
}
|
||||
|
||||
private applyBoundary() {
|
||||
if (!this.boundary || this.allowOverflow) return;
|
||||
if (this.allowOverflow) return;
|
||||
let { x, y } = { x: this.currentX, y: this.currentY };
|
||||
|
||||
if (this.boundary instanceof HTMLElement && this.containerRect) {
|
||||
const rect = this.target.getBoundingClientRect();
|
||||
x = Math.min(Math.max(x, 0), this.containerRect.width - rect.width);
|
||||
y = Math.min(Math.max(y, 0), this.containerRect.height - rect.height);
|
||||
} else if (!(this.boundary instanceof HTMLElement) && this.boundary) {
|
||||
if (this.boundary.minX !== undefined) x = Math.max(x, this.boundary.minX);
|
||||
if (this.boundary.maxX !== undefined) x = Math.min(x, this.boundary.maxX);
|
||||
if (this.boundary.minY !== undefined) y = Math.max(y, this.boundary.minY);
|
||||
if (this.boundary.maxY !== undefined) y = Math.min(y, this.boundary.maxY);
|
||||
}
|
||||
|
||||
this.currentX = x;
|
||||
this.currentY = y;
|
||||
@@ -413,16 +410,9 @@ export class DraggableResizableWindow {
|
||||
|
||||
private getSnapPoints() {
|
||||
const snapPoints = { x: [] as number[], y: [] as number[] };
|
||||
if (this.boundary instanceof HTMLElement && this.containerRect) {
|
||||
const rect = this.target.getBoundingClientRect();
|
||||
snapPoints.x = [0, this.containerRect.width - rect.width];
|
||||
snapPoints.y = [0, this.containerRect.height - rect.height];
|
||||
} else if (this.boundary && !(this.boundary instanceof HTMLElement)) {
|
||||
if (this.boundary.minX !== undefined) snapPoints.x.push(this.boundary.minX);
|
||||
if (this.boundary.maxX !== undefined) snapPoints.x.push(this.boundary.maxX);
|
||||
if (this.boundary.minY !== undefined) snapPoints.y.push(this.boundary.minY);
|
||||
if (this.boundary.maxY !== undefined) snapPoints.y.push(this.boundary.maxY);
|
||||
}
|
||||
return snapPoints;
|
||||
}
|
||||
|
||||
@@ -517,7 +507,7 @@ export class DraggableResizableWindow {
|
||||
newHeight = Math.max(this.minHeight, Math.min(this.maxHeight, newHeight));
|
||||
|
||||
// 边界限制
|
||||
if (!this.boundary || this.allowOverflow) {
|
||||
if (this.allowOverflow) {
|
||||
this.currentX = newX;
|
||||
this.currentY = newY;
|
||||
this.target.style.width = `${newWidth}px`;
|
||||
@@ -526,15 +516,8 @@ export class DraggableResizableWindow {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.boundary instanceof HTMLElement && this.containerRect) {
|
||||
newX = Math.min(Math.max(0, newX), this.containerRect.width - newWidth);
|
||||
newY = Math.min(Math.max(0, newY), this.containerRect.height - newHeight);
|
||||
} else if (!(this.boundary instanceof HTMLElement) && this.boundary) {
|
||||
if (this.boundary.minX !== undefined) newX = Math.max(newX, this.boundary.minX);
|
||||
if (this.boundary.maxX !== undefined) newX = Math.min(newX, this.boundary.maxX);
|
||||
if (this.boundary.minY !== undefined) newY = Math.max(newY, this.boundary.minY);
|
||||
if (this.boundary.maxY !== undefined) newY = Math.min(newY, this.boundary.maxY);
|
||||
}
|
||||
|
||||
this.currentX = newX;
|
||||
this.currentY = newY;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
$titleBarHeight: 40px;
|
||||
|
||||
/* 窗体容器 */
|
||||
.window {
|
||||
width: 100%;
|
||||
@@ -15,6 +17,8 @@
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
user-select: none;
|
||||
width: 100%;
|
||||
height: $titleBarHeight;
|
||||
|
||||
.title {
|
||||
display: block;
|
||||
@@ -24,6 +28,7 @@
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 18px;
|
||||
line-height: $titleBarHeight;
|
||||
}
|
||||
|
||||
.window-controls {
|
||||
@@ -52,6 +57,7 @@
|
||||
|
||||
/* 窗体内容 */
|
||||
.window-content {
|
||||
padding: 15px;
|
||||
width: 100%;
|
||||
height: calc(100% - #{$titleBarHeight});
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
@@ -53,7 +53,7 @@ export default class WindowFormImpl implements IWindowForm {
|
||||
handle: header,
|
||||
snapAnimation: true,
|
||||
snapThreshold: 20,
|
||||
boundary: document.body,
|
||||
boundaryElement: document.body,
|
||||
taskbarElementId: '#taskbar',
|
||||
onWindowStateChange: (state) => {
|
||||
if (state === 'maximized') {
|
||||
|
||||
Reference in New Issue
Block a user