通过 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 拖拽功能的简单实现。仍然是之前的老话,实现一个功能并不困难,但是如果要把这个功能做好,我们需要考虑很多的细节,或许很多时候我们都把时间花费在调整细节上了。
相关项目推荐:功能强大的 jQuery 图片查看器
相关推荐
runner 2020-09-01
梦的天空 2020-08-25
移动开发与培训 2020-08-16
ReunionIsland 2020-08-16
lyqdanang 2020-08-16
MyNameIsXiaoLai 2020-07-08
星辰的笔记 2020-07-04
csstpeixun 2020-06-28
letheashura 2020-06-26
liaoxuewu 2020-06-26
sunzhihaofuture 2020-06-21
FEvivi 2020-06-16
坚持着执着 2020-06-16
waterv 2020-06-14
xiaoge00 2020-06-14
firejq 2020-06-14
firstboy0 2020-06-14
e度空间 2020-06-12
zhongweinan 2020-06-10