简易的拖拽功能实现

思路整理

要实现拖拽,顾名思义,就是鼠标移动时dom跟着移动;

那就要拿到鼠标的点击(mousedown)移动(mousemove)和抬起(mouseup)的动作,并在这三个动作上面增加一些操作逻辑;

点击(mousedown):获取鼠标当前的位置以及目标dom的位置,得到这两个的初始移动值;

移动(mousemove):鼠标移动时,获取当前的位置得到鼠标移动的差值,也是目标dom的移动距离;即:

         鼠标移动后的位置  –  鼠标开始的位置 = 目标dom移动后的位置 – 目标dom初始的位置

所以计算出鼠标移动后的差值,减去目标dom的值就等于目标dom移动后的位置;

代码实现

既然要移动,那我们不得不使用translate平移,如果要使用此属性的话,需要验证浏览器支持哪种transform的写法;

// 获取transform兼容的写法
 const getTransform = () => {
    let transform = '';
    const divStyle = document.createElement('div').style,
          _transforms = ['transform', 'webkitTransform', 'MozTransform', 'msTansform',
 'OTransform'],

           len = _transforms.length;
    for(let i = 0; i < len; i++) {
        if(_transforms[i] in divStyle) {
            return transform = _transforms[i]
        }
    }
    return transform
 }
复制代码

如果浏览器不支持的话,就用定位left/top去移动,这次就不考虑这个了;

考虑有些小伙伴还在用IE,虽然马上退市了(偷笑),但是还是做了兼容;

// currentStyle是IE中获取style的属性
const getStyle = (elem, property) => {
      return window.getComputedStyle ? window.getComputedStyle(elem, false)[property] :
             elem.currentStyle[property]
}
复制代码

有了上面两个方法,接下来就可以开始正式的代码了

首先设置默认的元素值

  let startX = 0 鼠标开始的位置
  let startY = 0  鼠标结束的位置
  let isDrop = false  获取是否开始移动
  let sourceX = 0  目标开始的位置
  let sourceY = 0  目标结束的位置

// 获取元素的初始位置  
const getTargetPos = elem => {
      let pos = { x: 10, y: 0 }
      const transform = getTransform()
      if(transform) {
          const transformValue = getStyle(elem, transform)
          if(transformValue === 'none') {
              elem.style[transform] = 'translate(0, 0)'
              return pos
          } else {
              const temp = transformValue.match(/-?\d+/g)
              return pos = {
                  x: parseInt(temp[4].trim()),
                  y: parseInt(temp[5].trim()),
              }
          }
      } else {
          if(getStyle(elem, 'position') == 'static') {
              elem.style.position = 'relative'
              return pos
          } else {
              const x = parseInt(getStyle(elem, 'left') ? getStyle(elem, 'left') : 0)
              const y = parseInt(getStyle(elem, 'top') ? getStyle(elem, 'top') : 0)
              return pos = {
                  x: x,
                  y: y 
             }
          }
      }
 }
复制代码

设置元素的位置

  const setTargetPos = (elem, pos) => {
    const transform = getTransform()
    if(transform) {
      elem.style[transform] = 'translate('+pos.x + 'px, '+ pos.y +'px)'
    } else {
      elem.style.left = pos.x + 'px'
      elem.style.top = pos.y + 'px'
    }
    return elem
 }
复制代码

鼠标点击时

  const start = event => {
    console.log('start')
  const autumn = document.querySelector('.autumn')
    startX = event.pageX
    startY = event.pageY
    const pos = getTargetPos(autumn)
    sourceX = pos.x
    sourceY = pos.y
    isDrop = true
  }
复制代码

鼠标移动时

  const move = event => {
    console.log('move')
    if (isDrop) {
      const autumn = document.querySelector('.autumn')
      const currentX = event.pageX 
     const currentY = event.pageY 
       const distanceX = currentX - startX
      const distanceY = currentY - startY 
     setTargetPos(autumn, {
        x: (sourceX + distanceX).toFixed(),
        y: (sourceY + distanceY).toFixed(),
        })
    } else {
      return
    }
  }
复制代码

鼠标抬起结束时

  const end = () => {
    document.removeEventListener('mousemove', move)
    document.removeEventListener('mouseup', end)
    isDrop = false
    //可以写自己的任务代码的逻辑
  }
复制代码

本次用的hooks

  useEffect(() => {
  const autumn = document.querySelector('.autumn')
    autumn.addEventListener('mousedown', start, false)
    document.onmousemove = move
    autumn.addEventListener('mouseup', end, false)
  }, [])  
复制代码

页面元素

  return (
    <div className="autumn"
         style={{ width: '30px', height: '20px', backgroundColor: 'pink' }}
    >
        {props.button()}
    </div>
  )
复制代码

为了不写样式文件,此次都写的行内,不喜勿喷哦

文章借鉴自: 《JavaScript核心技术开发解密》

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享