前言

关于讲解 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);
}

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

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

总结

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

通过 JS 实现简单的拖拽功能并且可以在特定元素上禁止拖拽的更多相关文章

  1. 非node环境下的vue.js 实现简单的购物车计算功能 样式请无视

    都说vue的双向数据绑定好用,自己用了下,感觉做购物车没想象中好用.自己的实现如下: <!DOCTYPE html> <html lang="en"> &l ...

  2. (Demo分享)利用JavaScript(JS)实现一个九宫格拖拽功能

    利用JavaScript(JS)实现一个九宫格拖拽功能   Demo实现了对任意方格进行拖拽,可以交换位置,其中Demo-1利用了勾股定理判断距离! Demo-1整体思路: 1.首先div实现自由移动 ...

  3. JQuery UI的拖拽功能

    JQuery UI是JQuery官方支持的WebUI 代码库,包含底层交互.动画.特效等API,并且封装了一些Web小部件(Widget).同时,JQuery UI继承了jquery的插件支持,有大量 ...

  4. JQuery UI的拖拽功能实现方法小结

    JQuery UI提供的API极大简化了拖拽功能的开发.只需要分别在拖拽源(source)和目标(target)上调用draggable和droppable两个函数即可. 拖拽原理 首先要明确几个概念 ...

  5. duilib中控件拖拽功能的实现方法(附源码)

    转载请说明原出处,谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/41144283 duilib库中原本没有显示的对控件增加拖拽的功能,而实际 ...

  6. Atitit。D&D drag&drop拖拽功能c#.net java swing的对比与实现总结

    Atitit.D&D drag&drop拖拽功能c#.net java swing的对比与实现总结 1. 实现一个D&D操作一般包括三个步骤: 1 2. .net黑头的拖曳机制 ...

  7. JS实现简单的运行代码 & 侧边广告

    /* JS实现简单的运行代码功能 */<!doctype html> <html> <head> <meta charset="utf-8" ...

  8. 关于 JS 拖拽功能的冲突问题及解决方法

    前言 我在之前写过关于 JS 拖拽的文章,实现方式和网上能搜到的方法大致相同,别无二致,但是在一次偶然的测试中发现,这种绑定事件的方式可能会和其它的拖拽事件产生冲突,由此产生了对于事件绑定的思考.本文 ...

  9. js进阶 12-17 jquery实现鼠标左键按下拖拽功能

    js进阶 12-17 jquery实现鼠标左键按下拖拽功能 一.总结 一句话总结:监听的对象必须是文档,鼠标按下运行mousemove事件,鼠标松开取消mousemove事件的绑定,div的偏移的话是 ...

随机推荐

  1. 高性能分布式执行框架——Ray

    Ray是UC Berkeley AMP实验室新推出的高性能分布式执行框架,它使用了和传统分布式计算系统不一样的架构和对分布式计算的抽象方式,具有比Spark更优异的计算性能. Ray目前还处于实验室阶 ...

  2. P2051 [AHOI2009]中国象棋

    题目描述 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法.大家肯定很清楚,在中国象棋中炮的行走方式是 ...

  3. Vue使用Echarts以及Echarts配置分享

    一.本篇文章将给大家分享如何在vue中使用echart以及echart各项配置,这些配置都是工作中比较常见以及常用到的,所以给大家分享下,希望对大家有用. 二.vue中使用echart. 1.首先下载 ...

  4. php 7.2 一些注意事项.

    <?php $b = array(); each($b); // Deprecated: The each() function is deprecated. This message will ...

  5. 初识NumPy库-基本操作

    ndarray(N-dimensional array)对象是整个numpy库的基础. 它有以下特点: 同质:数组元素的类型和大小相同 定量:数组元素数量是确定的 一.创建简单的数组: np.arra ...

  6. Java 三大特性

    一.Java第一大特性:封装   封装:将属性私有化,提供共有方法访问私有属性,实现细节隐藏,并且程序也更加容易维护. class Dish { private final String name; ...

  7. 欢迎大家关注我的微信公众号(nangongkuo)

    欢迎大家关注我的微信公众号,在这个公众号里面我会给大家分享我学习过程中分享给大家的一些技术性的东西,和一些生活经验的总结分享.

  8. Java学习之计算机基础(二)

    今天主要介绍原码.反码与补码的知识.了解原码.反码与补码的知识,可以帮助我们更好地理解在计算机内部是如何进行运算的,同时对于后面更好地学习和理解Java基本数据类型及其范围打下基础. 背景知识: 在计 ...

  9. Xamarin 使用极光推送 详细教程

    源码下载地址:http://download.csdn.net/download/kendocross/8677263  有兴趣的看以去看看 一.首先新建一个Xamarin.Android 项目,过程 ...

  10. 剑指Offer_4_二维数组中的查找

    题目描述       在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数.       ...