如何在JavaScript中计算带scale的translate拖拽元素正确位置
拖拽库Redrop缩放(scale)时位置计算偏差问题
我正在开发名为Redrop的拖拽库,使用transform translate实现元素拖拽。核心逻辑是记录初始点击的clientX/Y,鼠标移动时用当前坐标减去初始坐标得到位移,再应用到元素的translate属性上。该功能在scale为1时正常运行,光标偏移功能也已实现,但当元素scale不为1时,元素尺寸和位置变化会导致当前位置计算失效。
程序流程
- 元素设为可拖拽时,绑定pointerdown事件触发dragStart;
- dragStart创建默认拖拽预览,设置初始位置与光标偏移;
- 拖拽时调用
#translateDragPreview方法设置元素位置。
负责位置处理的核心方法
#translateDragPreview方法
#translateDragPreview(x?: number, y?: number) { if (this.#draggedPreview.element === null) return; const cords = { x: x ?? this.#internalState.activeCords.x, y: y ?? this.#internalState.activeCords.y, }; const initialX = this.#initialPosition.x / this.#draggedPreview.scale; const initialY = this.#initialPosition.y / this.#draggedPreview.scale; this.#draggedPreview.element.style.transform = `translate( ${cords.x - initialX}px, ${cords.y - initialY}px) scale(${this.#draggedPreview.scale})`; }
#setCursorOffset方法
#setCursorOffset( dragElement: HTMLElement, event: PointerEvent, offset: BaseDraggableType["modifiers"]["cursor"]["offset"], ) { const cursorOffset = offset; const rect = dragElement.getBoundingClientRect(); const { scale } = this.#draggedPreview; const clickX = this.#internalState.initialCords.x - rect.left; const clickY = this.#internalState.initialCords.y - rect.top; const adjustRect: (value: number) => number = (value) => value + (value - value / scale); const adjustedRect = { left: rect.left / scale, right: adjustRect(rect.right), top: adjustRect(rect.top), bottom: adjustRect(rect.bottom), width: adjustRect(rect.width), height: adjustRect(rect.height), }; const presetOffset = { "top-left": { x: adjustedRect.left - cursorOffset.x, y: adjustedRect.top - cursorOffset.y, }, "top-right": { x: adjustedRect.right + cursorOffset.x, y: adjustedRect.top - cursorOffset.y, }, "bottom-left": { x: adjustedRect.left - cursorOffset.x, y: adjustedRect.bottom + cursorOffset.y, }, "bottom-right": { x: adjustedRect.right + cursorOffset.x, y: adjustedRect.bottom + cursorOffset.y, }, center: { x: adjustedRect.left + adjustedRect.width / 2 + cursorOffset.x - 4, y: adjustedRect.top + adjustedRect.height / 2 + cursorOffset.y - 2, }, auto: { x: adjustedRect.left + clickX + cursorOffset.x, y: adjustedRect.top + clickY + cursorOffset.y, }, }; this.#initialPosition = presetOffset[cursorOffset.preset]; }
补充信息
this.#internalState.activeCords:存储当前鼠标的clientX/Y;this.#internalState.initialCords:存储初始点击坐标(x,y);this.#initialPosition:存储应用偏移后的初始位置,尝试调整scale但未成功。
需求:推导带scale的translate拖拽元素的正确位置计算公式,解决缩放导致的位置偏差问题。
内容的提问来源于stack exchange,提问作者GokuNik
相关产品推荐
相关产品推荐

