保存一下
This commit is contained in:
@@ -292,6 +292,106 @@ export class DraggableResizableWindow {
|
|||||||
if (isFinal) this.applyBoundary();
|
if (isFinal) this.applyBoundary();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private animateTo(targetX: number, targetY: number, duration: number, onComplete?: () => void) {
|
||||||
|
if (this.animationFrame) cancelAnimationFrame(this.animationFrame);
|
||||||
|
|
||||||
|
const startX = this.currentX;
|
||||||
|
const startY = this.currentY;
|
||||||
|
const deltaX = targetX - startX;
|
||||||
|
const deltaY = targetY - startY;
|
||||||
|
const startTime = performance.now();
|
||||||
|
|
||||||
|
const step = (now: number) => {
|
||||||
|
const elapsed = now - startTime;
|
||||||
|
const progress = Math.min(elapsed / duration, 1);
|
||||||
|
const ease = 1 - Math.pow(1 - progress, 3);
|
||||||
|
|
||||||
|
const x = startX + deltaX * ease;
|
||||||
|
const y = startY + deltaY * ease;
|
||||||
|
|
||||||
|
this.applyPosition(x, y, false);
|
||||||
|
this.onDragMove?.(x, y);
|
||||||
|
|
||||||
|
if (progress < 1) {
|
||||||
|
this.animationFrame = requestAnimationFrame(step);
|
||||||
|
} else {
|
||||||
|
this.applyPosition(targetX, targetY, true);
|
||||||
|
this.onDragMove?.(targetX, targetY);
|
||||||
|
onComplete?.();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.animationFrame = requestAnimationFrame(step);
|
||||||
|
}
|
||||||
|
|
||||||
|
private applyBoundary() {
|
||||||
|
if (!this.boundary || this.allowOverflow) return;
|
||||||
|
|
||||||
|
let { x, y } = { x: this.currentX, y: this.currentY };
|
||||||
|
|
||||||
|
if (this.boundary instanceof HTMLElement && this.containerRect) {
|
||||||
|
const rect = this.target.getBoundingClientRect();
|
||||||
|
const minX = 0;
|
||||||
|
const minY = 0;
|
||||||
|
const maxX = this.containerRect.width - rect.width;
|
||||||
|
const maxY = this.containerRect.height - rect.height;
|
||||||
|
|
||||||
|
x = Math.min(Math.max(x, minX), maxX);
|
||||||
|
y = Math.min(Math.max(y, minY), maxY);
|
||||||
|
} else if (!(this.boundary instanceof HTMLElement)) {
|
||||||
|
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;
|
||||||
|
this.applyPosition(x, y, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private applySnapping(x: number, y: number) {
|
||||||
|
let { x: snappedX, y: snappedY } = { x, y };
|
||||||
|
|
||||||
|
// 1. 容器吸附
|
||||||
|
const containerSnap = this.getSnapPoints();
|
||||||
|
if (this.snapThreshold > 0) {
|
||||||
|
for (const sx of containerSnap.x) {
|
||||||
|
if (Math.abs(x - sx) <= this.snapThreshold) {
|
||||||
|
snappedX = sx;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const sy of containerSnap.y) {
|
||||||
|
if (Math.abs(y - sy) <= this.snapThreshold) {
|
||||||
|
snappedY = sy;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 窗口吸附 TODO
|
||||||
|
|
||||||
|
return { x: snappedX, y: snappedY };
|
||||||
|
}
|
||||||
|
|
||||||
|
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 instanceof HTMLElement) && this.boundary) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
private onMouseDownResize = (e: MouseEvent) => {
|
private onMouseDownResize = (e: MouseEvent) => {
|
||||||
const dir = this.getResizeDirection(e);
|
const dir = this.getResizeDirection(e);
|
||||||
if (!dir) return;
|
if (!dir) return;
|
||||||
@@ -451,106 +551,6 @@ export class DraggableResizableWindow {
|
|||||||
if (!this.currentDirection && !this.isDragging) this.updateCursor(null);
|
if (!this.currentDirection && !this.isDragging) this.updateCursor(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
private animateTo(targetX: number, targetY: number, duration: number, onComplete?: () => void) {
|
|
||||||
if (this.animationFrame) cancelAnimationFrame(this.animationFrame);
|
|
||||||
|
|
||||||
const startX = this.currentX;
|
|
||||||
const startY = this.currentY;
|
|
||||||
const deltaX = targetX - startX;
|
|
||||||
const deltaY = targetY - startY;
|
|
||||||
const startTime = performance.now();
|
|
||||||
|
|
||||||
const step = (now: number) => {
|
|
||||||
const elapsed = now - startTime;
|
|
||||||
const progress = Math.min(elapsed / duration, 1);
|
|
||||||
const ease = 1 - Math.pow(1 - progress, 3);
|
|
||||||
|
|
||||||
const x = startX + deltaX * ease;
|
|
||||||
const y = startY + deltaY * ease;
|
|
||||||
|
|
||||||
this.applyPosition(x, y, false);
|
|
||||||
this.onDragMove?.(x, y);
|
|
||||||
|
|
||||||
if (progress < 1) {
|
|
||||||
this.animationFrame = requestAnimationFrame(step);
|
|
||||||
} else {
|
|
||||||
this.applyPosition(targetX, targetY, true);
|
|
||||||
this.onDragMove?.(targetX, targetY);
|
|
||||||
onComplete?.();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.animationFrame = requestAnimationFrame(step);
|
|
||||||
}
|
|
||||||
|
|
||||||
private applyBoundary() {
|
|
||||||
if (!this.boundary || this.allowOverflow) return;
|
|
||||||
|
|
||||||
let { x, y } = { x: this.currentX, y: this.currentY };
|
|
||||||
|
|
||||||
if (this.boundary instanceof HTMLElement && this.containerRect) {
|
|
||||||
const rect = this.target.getBoundingClientRect();
|
|
||||||
const minX = 0;
|
|
||||||
const minY = 0;
|
|
||||||
const maxX = this.containerRect.width - rect.width;
|
|
||||||
const maxY = this.containerRect.height - rect.height;
|
|
||||||
|
|
||||||
x = Math.min(Math.max(x, minX), maxX);
|
|
||||||
y = Math.min(Math.max(y, minY), maxY);
|
|
||||||
} else if (!(this.boundary instanceof HTMLElement)) {
|
|
||||||
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;
|
|
||||||
this.applyPosition(x, y, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private applySnapping(x: number, y: number) {
|
|
||||||
let { x: snappedX, y: snappedY } = { x, y };
|
|
||||||
|
|
||||||
// 1. 容器吸附
|
|
||||||
const containerSnap = this.getSnapPoints();
|
|
||||||
if (this.snapThreshold > 0) {
|
|
||||||
for (const sx of containerSnap.x) {
|
|
||||||
if (Math.abs(x - sx) <= this.snapThreshold) {
|
|
||||||
snappedX = sx;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const sy of containerSnap.y) {
|
|
||||||
if (Math.abs(y - sy) <= this.snapThreshold) {
|
|
||||||
snappedY = sy;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 窗口吸附 TODO
|
|
||||||
|
|
||||||
return { x: snappedX, y: snappedY };
|
|
||||||
}
|
|
||||||
|
|
||||||
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 instanceof HTMLElement) && this.boundary) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
private observeResize(container: HTMLElement) {
|
private observeResize(container: HTMLElement) {
|
||||||
if (this.resizeObserver) this.resizeObserver.disconnect();
|
if (this.resizeObserver) this.resizeObserver.disconnect();
|
||||||
this.resizeObserver = new ResizeObserver(() => {
|
this.resizeObserver = new ResizeObserver(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user