基于Vue 撸一个指令完成拖拽功能

发布时间: 2019-10-09 13:31:35 来源: 互联网 栏目: JavaScript 点击:

这篇文章重要简介了Vue 指令完成拖拽功能,完成道理很简单,文中经过过程实例代码给大年夜家简介的异常详细,具有必定的参考自创价值,须要的同伙可以参考下

之前撸了一个copy 指令,此次再撸一个拖拽指令。。

详细是个甚么蛇皮玩艺儿呢,大年夜概就像介样:

 

emmm。。没错,看起来就是如此的鸡肋,然则莫得办法,大年夜佬爱好啊。

由于我们项目中用的是 element-ui ,一切这个指令只针对 element-ui 的对话框组件哈,假设你们用的其他 ui 库也有这个需求的,涂涂改改应当也能用。。

其实这个拖拽的道理照样很简单的:

1.起首鼠标按下( onmousedown )

  • 记录目标元素以后的 left 和 top 值

2.鼠标移动( onmousemove )

  • 计算每次移动的横向间隔 ( disX ) 和纵向间隔 ( disY )
  • 并改变元素的 left ( left = left + disX )和 top ( top = top + disY )值

3.鼠标松开( onmouseup )

完成一次拖拽,做一些扫尾任务

  • left 和 top 值轻易获得,关键是 disX 和 disY 怎样计算呢?

容我先普及一哈:

  • clientX :表示鼠标以后的 X 坐标
  • clientY :表示鼠标以后的 Y 坐标

那么伪代码就是:

  • disX = 鼠标按下时的 clientX - 鼠标松开时的 clientX
  • disY = 鼠标按下时的 clientY - 鼠标松开时的 clientY

就这么简单,好了,下面就开端撸代码了。

// 这个助手办法下面会用到,用来获得 css 相干属性值
const getAttr = (obj, key) => (
  obj.currentStyle
  ? obj.currentStyle[key]
  : window.getComputedStyle(obj, false)[key]
);
const vDrag = {
  inserted(el) {
   /**
    * 这里是跟据 dialog 组件的 dom 构造来写的
    * target: dialog 组件的容器元素
    * header:dialog 组件的头部区域,也是就是拖拽的区域
    */
    const target = el.children[0];
    const header = target.children[0];
    // 鼠标手型
    header.style.cursor = 'move';
    header.onmousedown = (e) => {
      // 记录按下时鼠标的坐标和目标元素的 left、top 值
      const currentX = e.clientX;
      const currentY = e.clientY
      const left = parseInt(getAttr(target, 'left'));
      const top = parseInt(getAttr(target, 'top'));
      document.onmousemove = (event) => {
        // 鼠标移动时计算每次移动的间隔,并改变拖拽元素的定位
        const disX = event.clientX - currentX;
        const disY = event.clientY - currentY;
        target.style.left = `${left + disX}px`;
        target.style.top = `${top + disY}px`;
        // 阻拦事宜的默许行动,可以处理选中文本的时辰拖不动
        return false;
      }
      // 鼠标松开时,拖拽停止
      document.onmouseup = () => {
        document.onmousemove = null;
        document.onmouseup = null;
      };
    }
  },
  // 每次重新翻开 dialog 时,要将其复原
  update(el) {
    const target = el.children[0];
    target.style.left = '';
    target.style.top = '';
  },
  // 最后卸载时,清除事宜绑定
  unbind(el) {
    const header = el.children[0].children[0];
    header.onmousedown = null;
  },
};
export default vDrap;

如许就完成了 最简单 的拖拽了,如许就 ok 了吗? 固然不是,如许会有甚么成绩呢?就是假设用力过猛把全部弹框都拖到可视区域以外了,那就抠不出来了。

所以还得完美一下,断定四个偏向的界线,假设逾越界线值就不动了。界线值实际上就是在屏幕上能拖动的最大年夜间隔也就是 disX 和 disY 的最大年夜值

  • 上界线: target.offsetTop
  • offsetTop :这里可以表示目标元素( target )上边框间隔页面顶部的间隔
  • 下界线: body.height - target.offsetTop - header.height
  • header.height :预留高度,表示往下可以拖到只留下可拖拽区域在外面
  • 左界线: target.offsetLeft + target.width - 50
  • offsetLeft :这里可以表示目标元素左边框间隔页面左边的间隔
  • 50 :表示预留的宽度,可以本身随便定只需大年夜于 0 便可,表示往左再怎样拖也会留下 50px 的宽度在外面
  • 右界线: body.width - target.offsetLeft - 50

这里 50 同上,表示往左再怎样拖也会留下 50px 的宽度在外面

这里计算界线值的办法有多种,大年夜家可以去测验测验本身的想法主意。然后我粗略的画了一个图,赞助懂得,固然感到只要我本身看得懂。哈哈。。。

 

下面用代码完成界线断定就 ok了

// ...
// 以上代码省略
header.onmousedown = (e) => {
  // ...
  // 以上代码省略
  // 分别计算四个偏向的界线值
  const minLeft = target.offsetLeft + parseInt(getAttr(target, 'width')) - 50;
  const maxLeft = parseInt(getAttr(document.body, 'width')) - target.offsetLeft - 50;
  const minTop = target.offsetTop;
  const maxTop = parseInt(getAttr(document.body, 'height'))
   - target.offsetTop - parseInt(getAttr(header, 'height'));
  document.onmousemove = (event) => {
    // 鼠标移动时计算每次移动的间隔,并改变拖拽元素的定位
    const disX = event.clientX - currentX;
    const disY = event.clientY - currentY;
    // 断定左、右界线
    if (disX < 0 && disX <= -minLeft) {
     target.style.left = `${left - minLeft)}px`;
    } else if (disX > 0 && disX >= maxLeft) {
     target.style.left = `${left + maxLeft}px`;
    } else {
     target.style.left = `${left + disX}px`;
    }
    // 断定上、下界线
    if (disY < 0 && disY <= -minTop) {
     target.style.top = `${top - minTop)}px`;
    } else if (disY > 0 && disY >= maxTop) {
     target.style.top = `${top + maxTop}px`;
    } else {
     target.style.top = `${top + disY}px`;
    }
    return false;
  };
}

如许注册以后便可以应用了:

<el-dialog v-drag title="对话框" :visible.sync="dialogVisible"></el-dialog>

总结

以上所述是小编给大年夜家简介的Vue 指令完成拖拽功能,欲望对大年夜家有所赞助,假设大年夜家有任何疑问请给我留言,小编会及时答复大年夜家的。在此也异常感激大年夜家对我们网站的支撑!
假设你认为本文对你有赞助,迎接转载,烦请注明出处,感谢!

本文标题: 基于Vue 撸一个指令完成拖拽功能
本文地址: http://yourctp.com/wangluo/javascript/278096.html

假设认为本文对您有所赞助请赞助本站

付出宝扫一扫赞助微信扫一扫赞助

  • 付出宝扫一扫赞助
  • 微信扫一扫赞助
  • 付出宝先领红包再赞助
    声明:凡注明"本站原创"的一切文字图片等材料,版权均属编程客栈一切,迎接转载,但务请注明出处。
    处理Vue静态加载本地图片成绩将RGB值转换为灰度值的简单算法
    Top