完美实现按下鼠标移动元素功能
1 const handleChangePosition = () => { 2 const element = canvasBox.value as HTMLDivElement; 3 let startX = 0, startY = 0, initialX = 0, initialY = 0; 4 5 element.onmousedown = function (e) { 6 // 获取当前的transform值 7 const transform = window.getComputedStyle(element).transform; 8 if (transform !== 'none') { 9 const matrix = new DOMMatrixReadOnly(transform); 10 initialX = matrix.m41; 11 initialY = matrix.m42; 12 } 13 14 // 记录起始位置 15 startX = e.clientX; 16 startY = e.clientY; 17 18 // 添加鼠标移动事件监听器 19 document.onmousemove = function (em) { 20 requestAnimationFrame(() => { 21 const dx = em.clientX - startX + initialX; 22 const dy = em.clientY - startY + initialY; 23 element.style.transform = `translate(${dx}px, ${dy}px)`; 24 }); 25 }; 26 }; 27 28 document.onmouseup = function () { 29 // 移除鼠标移动事件监听器 30 document.onmousemove = null; 31 }; 32 };
为什么要减去 startX
和 startY
这里的 startX
和 startY
代表了鼠标按下时的初始位置。在鼠标移动过程中,我们需要计算从这个起始点到当前鼠标位置的相对移动距离。这样做的目的是为了确定鼠标移动了多远,然后将这个距离应用到元素的平移上。
当鼠标移动时,em.clientX
和 em.clientY
表示鼠标当前的位置。通过从当前位置减去初始位置(startX
和 startY
),我们得到了鼠标相对于按下时的移动距离。然后,这个移动距离加上元素的初始位置(initialX
和 initialY
)得到了元素的新位置。
如果不加上initialX
和initialY,鼠标点击和第一次移动时,
startX
和startY总是与clientX和clientY相等,这样会导致元素每次移动都会先回到(0,0)的位置。
window.getComputedStyle(element).transform
和 DOMMatrixReadOnly
window.getComputedStyle(element).transform
: 这行代码的作用是获取元素当前的样式,包括由CSS或之前的JavaScript操作所应用的所有样式。在这里,我们关心的是transform
属性,它包含了元素的变换信息,比如它是如何被平移或旋转的。
-
DOMMatrixReadOnly
对象: 当transform
属性返回的不是none
时,表示元素有一些变换。transform
属性的值通常是一个矩阵或一个矩阵的字符串表示(比如matrix(1, 0, 0, 1, 100, 50)
)。为了更容易地读取这些值,我们使用DOMMatrixReadOnly
来解析这个矩阵。这是一个专门用来处理二维和三维变换矩阵的Web API。下面是控制台打印的值 -
matrix.m41
和matrix.m42
: 在一个2D变换矩阵中,m41
和m42
分别代表矩阵在X轴和Y轴的平移距离。通过读取这些值,我们可以得到元素当前的平移位置。
有其他方法欢迎留言讨论