zoukankan      html  css  js  c++  java
  • 通过 JS 实现简单的拖拽功能并且可以在特定元素上禁止拖拽

    前言

    关于讲解 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 拖拽功能的简单实现。仍然是之前的老话,实现一个功能并不困难,但是如果要把这个功能做好,我们需要考虑很多的细节,或许很多时候我们都把时间花费在调整细节上了。

  • 相关阅读:
    poj1087最大流拆点
    3月15上午的函数练习
    3月15
    3月13上午
    3月13
    3月12
    break语句
    3月11
    3月10号
    3月9号
  • 原文地址:https://www.cnblogs.com/nzbin/p/8158440.html
Copyright © 2011-2022 走看看