关于讲解 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 拖拽功能的简单实现。仍然是之前的老话,实现一个功能并不困难,但是如果要把这个功能做好,我们需要考虑很多的细节,或许很多时候我们都把时间花费在调整细节上了。
感谢您的阅读,如果您对我的文章感兴趣,可以关注我的博客,我是叙帝利,下篇文章再见!
开发低代码平台的必备拖拽库 https://github.com/ng-dnd/ng-dnd
基于 Angular Material 的中后台管理框架 https://github.com/ng-matero/ng-matero
Angular Material Extensions 扩展组件库 https://github.com/ng-matero/extensions
仿 Windows 照片查看器插件 https://github.com/nzbin/photoviewer
仿 Windows 照片查看器插件 jQuery 版 https://github.com/nzbin/magnify
完美替代 jQuery 的模块化 DOM 库 https://github.com/nzbin/domq
简化类名的轻量级 CSS 框架 https://github.com/nzbin/snack
与任意 UI 框架搭配使用的通用辅助类 https://github.com/nzbin/snack-helper
单元素纯 CSS 加载动画 https://github.com/nzbin/three-dots
有趣的 jQuery 卡片抽奖插件 https://github.com/nzbin/CardShow
悬疑科幻电影推荐 https://github.com/nzbin/movie-gallery
锻炼记忆力的小程序 https://github.com/nzbin/memory-stake