通过js实现简单的拖拽功能并且可以在特定元素上禁止拖拽

放荡不羁爱自由      2022-02-16     592

关键词:

前言

关于讲解 JS 的拖拽功能的文章数不胜数,我确实没有必要大费周章再写一篇重复的文章来吸引眼球。本文的重点是讲解如何在某些特定的元素上禁止拖拽。这是我在编写插件时遇到的问题,其实很多插件的拖拽功能并没有处理这些细节,经过翻阅 jquery ui 的源码才找到答案。

拖拽实现

关于拖拽功能不再啰嗦,直接贴代码

/**
 * draggable 拖拽方法
 * @param  {type} modal - 移动元素
 * @param  {type} handle - 可拖拽区域
 */
var draggable = function(modal, handle) {

  var isDragging = false;

  var startX = 0,
    startY = 0,

    left = 0,
    top = 0;

  var dragStart = function(e) {

    var e = e || window.event;

    e.preventDefault();

    isDragging = true;

    startX = e.clientX;
    startY = e.clientY;

    left = $(modal).offset().left;
    top = $(modal).offset().top;

  }

  var dragMove = function(e) {

    var e = e || window.event;

    e.preventDefault();

    if (isDragging) {

      var endX = e.clientX,
        endY = e.clientY,

        relativeX = endX - startX,
        relativeY = endY - startY;

      $(modal).css({
        left: relativeX + left + 'px',
        top: relativeY + top + 'px'
      });

    }

    return false;

  }

  var dragEnd = function(e) {

    isDragging = false;

  }

  $(handle).on('mousedown', dragStart);

  $(document).on('mousemove', dragMove);

  $(document).on('mouseup', dragEnd);
}

使用方法

演示 Demo HTML

<div class="modal" id="modal">
  <div class="modal-header">
    <button class="btn-close"><i class="fa fa-times"></i></button>
  </div>
  <div class="modal-body"></div>
</div>

演示 Demo CSS

.modal {
  position: fixed;
  top: 100px;
  left: 100px;
  width: 300px;
  border: 1px solid #aaa;
  padding: 3px;
  border-radius: 5px;
}

.modal-header {
  height: 24px;
  line-height: 24px;
  background-color: #ddd;
  color: #222;
  padding: 5px;
  border-radius: 3px;
}

.modal-body {
  height: 100px;
}

.btn-close {
  width: 24px;
  height: 24px;
  float: right;
  padding: 3px;
}

演示 Demo JS

draggable('#modal', '#modal .modal-header');

 我们可以通过第二个参数指定不同的拖拽元素,比如可以指定整个 modal 为拖拽元素

draggable('#modal','#modal');

拖拽问题

整个拖拽功能并没有太大的问题,但是如果我们拖拽关闭按钮,仍然可以拖拽整个 modal,看起来不太和谐而且在某些情况下会影响功能,所以我们需要排除掉关闭按钮。

排除特定元素的方法

关于如何排除特定元素的方法,很多人会推荐阻止冒泡的方法,但是我试了很多次,这种方法是不行的,因为拖拽事件绑定在了 document 对象上。解决的方法就是在拖拽开始时添加限制条件,代码如下

...
  var dragStart = function(e) {

    var e = e || window.event;

    e.preventDefault();

    // 获取需要排除的元素
    var elemCancel = $(e.target).closest(element);
    // 如果拖拽的是排除元素,函数返回
    if (elemCancel.length) {
      return true;
    }

    isDragging = true;

    startX = e.clientX;
    startY = e.clientY;

    left = $(modal).offset().left;
    top = $(modal).offset().top;

  }
...

为什么使用 closest() 方法呢?因为我们在排除特定元素的同时也要排除它的子元素。如果使用原生 JS 的话,需要添加获取子元素的方法。以下是完整代码:

/**
 * draggable 拖拽方法
 * @param  {type} modal - 移动元素
 * @param  {type} handle - 可拖拽区域
 * @param  {type} cancle - 需要排除的元素
 */
var draggable = function(modal, handle, cancle) {

  var isDragging = false;

  var startX = 0,
    startY = 0,

    left = 0,
    top = 0;

  var dragStart = function(e) {

    var e = e || window.event;

    e.preventDefault();

    // 获取需要排除的元素
    var elemCancel = $(e.target).closest(cancle);
    // 如果拖拽的是排除元素,函数返回
    if (elemCancel.length) {
      return true;
    }

    isDragging = true;

    startX = e.clientX;
    startY = e.clientY;

    left = $(modal).offset().left;
    top = $(modal).offset().top;

  }

  var dragMove = function(e) {

    var e = e || window.event;

    e.preventDefault();

    if (isDragging) {

      var endX = e.clientX,
        endY = e.clientY,

        relativeX = endX - startX,
        relativeY = endY - startY;

      $(modal).css({
        left: relativeX + left + 'px',
        top: relativeY + top + 'px'
      });

    }

    return false;

  }

  var dragEnd = function(e) {

    isDragging = false;

  }

  $(handle).on('mousedown', dragStart);

  $(document).on('mousemove', dragMove);

  $(document).on('mouseup', dragEnd);
}
View Code

上面的案例的 JS 修改如下:

draggable('#modal','#modal .modal-header', '#modal .btn-close');

总结

其实这个拖拽案例算是 jquery ui 拖拽功能的简单实现。仍然是之前的老话,实现一个功能并不困难,但是如果要把这个功能做好,我们需要考虑很多的细节,或许很多时候我们都把时间花费在调整细节上了。

javascript实现最简单的拖拽效果

一、一些无关痛痒的唠叨拖拽还是挺不错的一个页面效果,我个人认为,其生命力在于可以让用户自己做一些操作,所谓自定义。例如:①浏览器标签顺序的拖拽切换现在基本上所有的选项卡式的浏览器都有顺序拖拽切换的功能... 查看详情

简单实现svg的拖拽和缩放

...,来控制svg(正方形)刚好在父元素内,radio是缩放比例实现方式是<fontcolor=\'red\'>重绘</font>,所以元素太多会造成卡顿。一、拖拽我们来分析拖拽的过程,鼠标按下---->鼠标移动------>松开鼠标。对应的事件分别是mo... 查看详情

实现元素简单的拖拽

1.通过元素的offsetLeft,offsettop实现元素的拖拽1<!DOCTYPEhtml>2<html>34<head>5<metacharset="UTF-8">6<title></title>7<styletype="text/css">8.box{9width:100px;10height:100px 查看详情

three.js如何实现在x,y,z轴上的拖拽

...是如果我用THREE.js创建了一个模型,那该用什么代码才能实现像上述那样可以选取那个模型并且拖拽移动它呢参考技术A在three的源码里面有一个编辑器,里面实现了这个功能,目前没有研究明白,可以去看一下。这是目前我发现... 查看详情

04:js拖拽功能的实现

...的是绝对定位条件下的left以及top等等值。补充:也可以通过html5的拖放(Drag和drop)来实现 查看详情

oraclevmvirtualbox怎么实现虚拟机和主机之间文件的拖拽?

...ualBox是不能文件拖拽的,这是处于安全考虑的。不过可以通过分配数据空间,而后进行网络映射的方法来实现数据共享。当然你也可以通过网络的方式,如一楼说的HTTP、FTP方式。不过这个要有一定的基础,实现比较麻烦。你可... 查看详情

原生拖拽,拖放事件(draganddrop)

参考技术A拖拽,拖放事件可以通过拖拽实现数据传递,达到良好的交互效果,如:从操作系统拖拽文件实现文件选择,拖拽实现元素布局的修改.一个完整的draganddrop流程通常包含以下几个步骤:1.设置可拖拽目标.设置属性draggable="true"实... 查看详情

js实现登陆页面的拖拽功能

<!DOCTYPEhtml><html> <head> <metacharset="UTF-8"> <title>登陆页面的拖拽功能实现</title> </head> <styletype="text/css"> *{ margin:0; padding:0; } a{ text-d 查看详情

h5的拖放事件(拖拽删除)

...应用在被拖拽元素上2、dragend:当拖动操作结束时触发(通过释放鼠标按钮或者点击转义键),应用在被拖拽元素上3、dragenter:当一个被拖动的元素或者选中的文本进入一个有效的放置目标时触发,应用在目标元素上4、dragexit:... 查看详情

js实现鼠标的拖拽效果

拖拽效果在我们上网的过程中是很常见的,大家都应该在电脑上面登陆过qq吧,当这个qq的登陆框弹出来的时候,我们是可以进行拖动的。这就是一个拖拽效果这是我在慕课网上面看到的,我直接拿过来了,地址http://www.imooc.com/le... 查看详情

electron开发:electron应用中的拖拽操作

...多个文件给应用程序,这种行为称为拖拽操作。本节将会通过两个案例介绍如何实现Electron应用的拖拽操作。本节将通过一个简单的案例演示如何实现图像文件的拖放操作,本例的主要功能是将一个图像文件拖拽的程序的某个区... 查看详情

为啥使用html5的拖拽功能,在火狐中总会弹出一个新面页?

...上都很正常,但是在火狐浏览器下,虽然拖拽功能也已经实现,但是每次拖拽操作后,就会弹出一个新面页,例如拖拽的目标是一个图形,弹出的面页就显示这个图形。现在就差火狐拖拽有上述这个问题了。请问那位高手能给指... 查看详情

javascript实现网页元素的拖拽效果

以下的页面中放了两个div,能够通过鼠标拖拽这两个元素到任何位置。实现该效果的HTML页面代码例如以下所看到的:<!DOCTYPEhtml><html><headlang="en"><metacharset="UTF-8"><title></title><styletype="text/css">#xixi{wid 查看详情

draggabilly轻松实现拖放功能|插件下载|demo下载

 Draggabilly是一款功能强大的网页元素拖动拖拽插件。该元素拖拽插件可以和jQuery结合使用,也可以以纯js的方式使用。它提供了强大的拖拽元素的能力,并且可以支持IE8浏览器和移动触摸设备。官网:https://draggabilly.desandro.com... 查看详情

reactdnd实现横向和纵向拖拽排序

...级元素的scrollLeft和scrollRight属性。结合useDrop的hover事件来实现具体的行为。如此一来,横向和纵向的拖拽排序都解决了,明天可以来实现一个类似于teambition的看板功能了! 查看详情

如何使用jquerydraggable和droppable实现拖拽功能

...如下图所示  主要功能需求说明左侧的元素结构最后会通过Ajaxcall服务器的数据来生成能支持多级元素父节点可以折叠起来  用户可以通过拖放的操作将元素从左侧拖放到右侧如果是拖的父节点元素那么需要把它子节点的元... 查看详情

原生js实现弹出窗口的拖拽(直接copy可用)

  上一篇说了一下弹出窗口功能的实现思路,一般情况下紧接着就会需要做到弹窗的移动,当然现在有很插件、库比如hammer可以使用,效率也非常好。但我觉得还是有必要了解一下原生JS的实现思路及方式,如下:  思路:... 查看详情

jq实现登陆页面的拖拽功能

<!DOCTYPEhtml><html> <head> <metacharset="UTF-8"> <scriptsrc="js/jquery-1.9.1.min.js"type="text/javascript"charset="utf-8"></script> <title></title> 查看详情