前言

关于讲解 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. 第一章:关于Ehcache

    PDF官方文档:http://www.ehcache.org/generated/2.10.4/pdf/About_Ehcache.pdf 1.什么是Ehcache? Ehcache是一种开源的基于标 ...

  2. iOS面试题最全梳理

    OC的理解与特性 OC作为一门面向对象的语言,自然具有面向对象的语言特性:封装.继承.多态.它既具有静态语言的特性(如C++),又有动态语言的效率(动态绑定.动态加载等).总体来讲,OC确实是一门不错 ...

  3. JS弹窗带遮蔽的功能

    很不错的JS原生自定义弹窗,很实用! function myAlert(str,click,useCancel){ var overflow=""; var $hidder=nul ...

  4. C语言之scanf

    #include<stdio.h>int main(){int num;int a,b,c,result,d,result1;scanf("int%d",&nu ...

  5. 《Linux命令行与shell脚本编程大全》第二十五章 创建与数据库、web及电子邮件相关的脚本

    25.1 MySQL数据库 /* 但是我在虚拟机上安装的时候居然不提示输入密码. 这个可以参考http://blog.csdn.net/sinat_21302587/article/details/7 ...

  6. Nginx 搭建rtmp直播服务器

    1.到nginx源码目录新建个rtmp目录 ,进入  git clone https://github.com/arut/nginx-rtmp-module.git   2.重编译nginx 代码如下 ...

  7. nginx使用ssl模块配置支持HTTPS访问【解决ssl错误】

    默认情况下ssl模块并未被安装,如果要使用该模块则需要在编译nginx时指定–with-http_ssl_module参数. 需求:做一个网站域名为 www.localhost.cn 要求通过http ...

  8. MyEclipse 使用图文详解

    引言 某天在群里看到有小伙伴问MyEclipse/Eclipse的一些使用问题,虽然在我看来,问的问题很简单,但是如果对于刚刚学习的人来说,可能使用就不那么友好了.毕竟我在开始使用MyEclipse/ ...

  9. Android IntentService使用介绍以及源码解析

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.IntentService概述及使用举例 IntentService内部实现机制用到了HandlerThread,如果对HandlerThrea ...

  10. Sagit.Framework For IOS 开发框架入门开发教程2:一行代码实现引导页

    前言: 开篇比较简单:Sagit.Framework For IOS 开发框架入门开发教程1:框架下载与环境配置 第二篇教程之前写了一半,感觉不太好写,而且内容单纯介绍API,要说的很多,又枯燥乏味. ...