1. 程式人生 > >通過 JS 實現簡單的拖拽功能並且可以在特定元素上禁止拖拽

通過 JS 實現簡單的拖拽功能並且可以在特定元素上禁止拖拽

如何 alt targe 但是 mes 並且 mod closed demo

前言

關於講解 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 拖拽功能的簡單實現。仍然是之前的老話,實現一個功能並不困難,但是如果要把這個功能做好,我們需要考慮很多的細節,或許很多時候我們都把時間花費在調整細節上了。

相關項目推薦:功能強大的 jQuery 圖片查看器

通過 JS 實現簡單的拖拽功能並且可以在特定元素上禁止拖拽