封装一个PC与H5使用的拖拽函数,并解决点击事件问题

14 阅读1分钟

所有代码

/**
 * 允许元素拖拽到任意位置(自动判断移动端和PC端,PC移动端互相切换时需刷新或再次执行该函数)
 *
 * @param {Element} element 被拖拽元素
 * @param {Function} clickFn 点击要执行的函数(因点击与拖拽冲突)
 * @example
 * <div id="dragElement"></div>
 *
 * <style>
 *   #dragElement {
 *     width: 100px;
 *     height: 100px;
 *     background-color: red;
 *     left: 0;
 *     top: 0;
 *   }
 * </style>
 *
 * <script>
 *   elementDrag(document.getElementById("dragElement"), () => alert("我被点击了!"))
 * </script>
 */
function elementDrag(element, clickFn) {
  if (element) return console.error("元素拖拽需要传入元素!");

  const maxX = window.innerWidth - element.offsetWidth;
  const maxY = window.innerHeight - element.offsetHeight;
  let startX,
    startY,
    offsetX,
    offsetY,
    isMoved = false;

  /**
   * 开始拖拽
   * @param {Event} e
   */
  function startDrag(e) {
    e.preventDefault();
    offsetX = element.offsetLeft;
    offsetY = element.offsetTop;
    if (e.type === "mousedown") {
      startX = e.clientX;
      startY = e.clientY;
      document.addEventListener("mousemove", drag, { passive: false });
      document.addEventListener("mouseup", stopDrag);
    }
    if (e.type === "touchstart") {
      startX = e.touches[0].clientX;
      startY = e.touches[0].clientY;
      document.addEventListener("touchmove", drag, { passive: false });
      document.addEventListener("touchend", stopDrag);
    }
  }

  /**
   * 拖拽
   * @param {Event} e
   */
  function drag(e) {
    e.preventDefault();
    let x, y, distanceX, distanceY;
    if (e.type === "mousemove") {
      distanceX = e.clientX - startX;
      distanceY = e.clientY - startY;
    }
    if (e.type === "touchmove") {
      distanceX = e.touches[0].clientX - startX;
      distanceY = e.touches[0].clientY - startY;
    }
    x = offsetX + distanceX;
    y = offsetY + distanceY;
    if (Math.abs(distanceX) > 0 || Math.abs(distanceY) > 0) {
      isMoved = true;
      x = Math.min(Math.max(x, 0), maxX);
      y = Math.min(Math.max(y, 0), maxY);
      element.style.left = x + "px";
      element.style.top = y + "px";
    }
  }

  /**
   * 结束拖拽
   */
  function stopDrag() {
    if (!isMoved) {
      clickFn && clickFn();
    }
    isMoved = false;

    if (window.innerWidth <= 1024) {
      document.removeEventListener("touchmove", drag);
      document.removeEventListener("touchend", stopDrag);
    } else {
      document.removeEventListener("mousemove", drag);
      document.removeEventListener("mouseup", stopDrag);
    }
  }

  // 是否是移动端
  const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);

  // 样式
  element.style.cursor = "move";
  element.style.position = "fixed";

  element.addEventListener(isMobile ? "touchstart" : "mousedown", startDrag);
}

使用方法

<template>
  <div id="dragElement"></div>  
</template>
  
<style>  
#dragElement {  
  width: 100px;  
  height: 100px;  
  background-color: red;  
  left: 0;  
  top: 0;  
}  
</style>  
  
<script>  
elementDrag(document.getElementById("dragElement"), () => alert("我被点击了!"))  
</script>