豫ICP备2024044691号-1
powered by emlog
元素拖拽的实现原理
Mins 2024-3-23 01:08 JavaScript

元素拖拽,这个小逻辑看起来简单,差点把我脑子干烧了。。。

首先说一下 touch 事件中的两个属性:clientX clientY 和 pageX pageY:

  • client 指的是点击区域相对当前可视区域的坐标。
  • page 指的是点击区域相对当前页面的坐标,注意:页面是可能有滚动条的


    综上所述,拖拽事件用的是 clientX 值,现在来梳理一下 X 轴的拖拽过程:

    首先明确一件事

    拖拽元素,一定是有一个父容器的,拖拽的本质是计算元素相对父容器的坐标。
    也就是说,拖拽的元素一定是有 position 属性的,可以是 absolute 或 fixed

其次定义三个变量:

  • clientX: 触发事件的 x 坐标
  • innerX: 触发事件的 x 坐标,相对于子元素的左边的距离
  • x: 元素相对父容器的偏移量,也就是 left 值

拖拽过程

  • 按住屏幕:触发 touchstart 事件,此时 innerX = clientX - x
  • 拖动元素:触发 touchmove 事件,此时 x = clientX - innerX
  • 松开屏幕:触发 touchend 事件,不做任何处理,保留 x 值下一次事件使用

代码示例

// 代码示例是 vue3 的写法,其中 e.touches[0].clientX 就是前面说的 clientX
let innerX = 0;
let innerY = 0;
let x = ref(100);
let y = ref(50);

const touchStart = (e) => {
    innerX = e.touches[0].clientX - x.value;
    innerY = e.touches[0].clientY - y.value;
}
const touchMove = (e) => {
    x.value = e.touches[0].clientX - innerX;
    y.value = e.touches[0].clientY - innerY;
}

以上,Y轴同理。实际业务中记得给 touchmove 事件做节流。