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