Vanilla JS+Bootstrap实现的缩放div拖拽时偏离鼠标光标如何修复?
问题修复方案
根因分析
- 拖拽逻辑未累积历史偏移量:原有代码每次拖拽时,直接将鼠标移动的差值赋值给元素的
left/top属性,覆盖了上一次拖拽结束后的位置,导致每次拖拽都会重置计算起点,多次操作后自然会出现元素与鼠标错位的问题。 - 未适配缩放比例:元素添加
transform: scale缩放后,视觉坐标与元素实际布局坐标存在比例差,会导致鼠标移动距离与元素实际移动距离不匹配,放大偏移问题。
修复方法
CSS和HTML代码与原有代码一致无需修改,仅需调整JS中的拖拽逻辑即可,完整可运行代码如下:
const scaleDownBtn = document.getElementById('scaleDown') scaleDownBtn.addEventListener('click', scaleDown) function scaleDown(event) { const selfViewVideo = document.querySelector('.self-video-div') selfViewVideo.classList.add("resize-div") } const resetBtn = document.getElementById('reset') resetBtn.addEventListener('click', reset) function reset(event) { const selfViewVideo = document.querySelector('.self-video-div') selfViewVideo.classList.remove("resize-div") } const selfViewVideoDiv = document.querySelector('.self-video-div') selfViewVideoDiv.addEventListener('mousedown', dragDiv) function dragDiv(event) { window.addEventListener("mousemove", mouseMove) window.addEventListener("mouseup", mouseUp) const selfViewVideoDiv = this // 获取当前元素的缩放比例 const transformStyle = window.getComputedStyle(selfViewVideoDiv).transform const currentScale = transformStyle === 'none' ? 1 : parseFloat(transformStyle.split(',')[3]) // 记录拖拽开始时元素已有的偏移量、鼠标初始坐标 const initLeft = parseFloat(getComputedStyle(selfViewVideoDiv).left) || 0 const initTop = parseFloat(getComputedStyle(selfViewVideoDiv).top) || 0 const initMouseX = event.clientX const initMouseY = event.clientY function mouseMove(event) { // 计算鼠标移动差值,校正缩放影响后累加历史偏移量 const deltaX = event.clientX - initMouseX const deltaY = event.clientY - initMouseY selfViewVideoDiv.style.left = `${initLeft + deltaX / currentScale}px` selfViewVideoDiv.style.top = `${initTop + deltaY / currentScale}px` } function mouseUp() { window.removeEventListener("mousemove", mouseMove) window.removeEventListener("mouseup", mouseUp) } }
可选优化
如果希望缩放时元素不会因为transform-origin: bottom right的配置向左上方偏移,可以将transform-origin改为top left,或者在缩放的同时调整元素的left和top值抵消缩放带来的额外位移。
内容的提问来源于stack exchange,提问作者pastoreerrante
相关产品推荐
相关产品推荐

