JavaScript事件模拟元素拖动
一、前言:
最近要实现一个元素拖放效果,鼠标拖动元素并且定位元素,首先想到的是HTML5中的拖放,在HTML5中,有一个draggable属性,且有dragstart, dragover, drop等事件,主要是通过event.dataTransfer对象方法,在dragstart事件中设置数据event.dataTransfer.setData(); 在drop事件中获取数据event.dataTransfer.getData();但是它并不能实现元素的实时拖放效果,因此还是需要用鼠标事件来模拟元素的拖放。
二、实例示图

三、实现原理:
1、思路:鼠标依次触发mousedown, mousemove, mouseup事件,在mousemove事件中实时计算元素新位置并且定位元素,
在mouseup事件中注销mousemove,mouseup事件。
2、重点:如果所有事件都绑定在拖动元素上,当鼠标移动速度很快,以至于离开了拖动的元素,那么就不会执行mousemove,
mouseup事件处理程序,因此要想让mousemove,mouseup事件处理实时执行,必须将它们绑定到document元素上;
四、插件源码:
$.fn.extend({
/**
*
* 扩展jQuery原型,实现鼠标事件模拟元素拖动
* drag中的回调函数this指向被拖动元素
* @ method: drag
* @ use: $( selector ).drag( dragStart, dragMove, dragEnd )
* @ param { function } 第一个参数,准备拖动处理函数
* @ param { function } 第二个参数,拖动中处理函数
* @ param { function } 第三个参数,拖动结束处理函数
* @ reutrn { jQuery( selector ) }
*
*/
drag: function( dragStart, dragMove, dragEnd ) {
function drag( dragElem, event ) {
var offsetX, offsetY, beforePageX, beforePageY;
if ( $.isFunction(dragStart) ) {
dragStart.apply(dragElem, arguments);
}
// 移动前或移动中的元素位置
offsetX = parseInt( $(dragElem).css('left'), 10 );
offsetY = parseInt( $(dragElem).css('top'), 10 );
// 移动前或移动中的鼠标位置
beforePageX = event.clientX;
beforePageY = event.clientY;
if ( document.addEventListener ) {
document.addEventListener('mousemove', moveHandle, false);
document.addEventListener('mouseup', upHandle, false);
}
else if ( document.attachEvent ) {
dragElem.setCapture(); // 将dragElem鼠标事件继承到文档进行捕获
dragElem.attachEvent('onmousemove', moveHandle);
dragElem.attachEvent('onmouseup', upHandle);
dragElem.attachEvent('onlosecapture', upHandle);
}
// 鼠标移动事件处理
function moveHandle (event) {
var event = event || window.event;
// 更新移动中或移动终止后的元素位置
var x = offsetX + event.clientX - beforePageX;
var y = offsetY + event.clientY - beforePageY;
$(dragElem).css({
left: x + 'px',
top: y + 'px'
});
// 阻止事件传播
if ( event.stopPropagation ){
event.stopPropagation();
}
else if ( event.cancleBubble ) {
event.cancleBubble = true;
}
if ( $.isFunction(dragMove) ) {
dragMove.apply(dragElem, arguments);
}
}
// 鼠标弹起事件处理
function upHandle (event) {
if ( document.addEventListener ) {
document.removeEventListener('mousemove', moveHandle, false);
document.removeEventListener('mouseup', upHandle, false);
}
else if ( document.detachEvent ) {
dragElem.detachEvent('onlosecapture', upHandle);
dragElem.detachEvent('onmouseup', upHandle);
dragElem.detachEvent('onmousemove', moveHandle);
dragElem.releaseCapture();
}
if ( event.stopPropagation ){
event.stopPropagation();
}
else if ( event.cancleBubble ) {
event.cancleBubble = true;
}
if ( $.isFunction(dragEnd) ) {
dragEnd.apply(dragElem, arguments);
}
}
}
$(this).each(function(){
$(this).bind('mousedown', function(e){
var dragElem = this,
event = e;
drag(dragElem, event);
});
});
return this;
}
});
五、调用实例:
(function(){
var dragEnd = false;
$('.drag-elem').drag(
function(){
$(this).text('准备拖动').css({ zIndex: 2 }).siblings().css({ zIndex: 1 });
},
function(){
var offset = $(this).offset();
dragEnd = true;
$(this).text('拖动中(' + offset.left + ',' + offset.top + ')' );
},
function(){
if (dragEnd) {
$(this).text('拖动结束');
dragEnd = false;
}
}
);
}());
六、完整实例代码
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>jQuery drag</title>
<script src="http://code.jquery.com/jquery-1.10.1.js"></script>
<style>
.drag-elem {
position: absolute;
left: 10px;
top: 20px;
z-index: 999;
width: 200px;
height: 50px;
cursor: move;
background-color: #ccc;
border: 5px solid green;
font-size: 24px;
line-height: 50px;
text-align: center;
}
</style>
</head> <body> <div class="drag-elem"></div> <script>
$.fn.extend({
/**
*
* 扩展jQuery原型,实现鼠标事件模拟元素拖动
* drag中的回调函数this指向被拖动元素
* @ method: drag
* @ use: $( selector ).drag( dragStart, dragMove, dragEnd )
* @ param { function } 第一个参数,准备拖动处理函数
* @ param { function } 第二个参数,拖动中处理函数
* @ param { function } 第三个参数,拖动结束处理函数
* @ reutrn { jQuery( selector ) }
*
*/
drag: function( dragStart, dragMove, dragEnd ) {
function drag( dragElem, event ) {
var offsetX, offsetY, beforePageX, beforePageY; if ( $.isFunction(dragStart) ) {
dragStart.apply(dragElem, arguments);
} // 移动前或移动中的元素位置
offsetX = parseInt( $(dragElem).css('left'), 10 );
offsetY = parseInt( $(dragElem).css('top'), 10 ); // 移动前或移动中的鼠标位置
beforePageX = event.clientX;
beforePageY = event.clientY; if ( document.addEventListener ) {
document.addEventListener('mousemove', moveHandle, false);
document.addEventListener('mouseup', upHandle, false);
}
else if ( document.attachEvent ) {
dragElem.setCapture(); // 将dragElem鼠标事件继承到文档进行捕获
dragElem.attachEvent('onmousemove', moveHandle);
dragElem.attachEvent('onmouseup', upHandle);
dragElem.attachEvent('onlosecapture', upHandle);
} // 鼠标移动事件处理
function moveHandle (event) {
var event = event || window.event; // 更新移动中或移动终止后的元素位置
var x = offsetX + event.clientX - beforePageX;
var y = offsetY + event.clientY - beforePageY; $(dragElem).css({
left: x + 'px',
top: y + 'px'
}); // 阻止事件传播
if ( event.stopPropagation ){
event.stopPropagation();
}
else if ( event.cancleBubble ) {
event.cancleBubble = true;
} if ( $.isFunction(dragMove) ) {
dragMove.apply(dragElem, arguments);
}
} // 鼠标弹起事件处理
function upHandle (event) {
if ( document.addEventListener ) {
document.removeEventListener('mousemove', moveHandle, false);
document.removeEventListener('mouseup', upHandle, false);
}
else if ( document.detachEvent ) {
dragElem.detachEvent('onlosecapture', upHandle);
dragElem.detachEvent('onmouseup', upHandle);
dragElem.detachEvent('onmousemove', moveHandle);
dragElem.releaseCapture();
}
if ( event.stopPropagation ){
event.stopPropagation();
}
else if ( event.cancleBubble ) {
event.cancleBubble = true;
} if ( $.isFunction(dragEnd) ) {
dragEnd.apply(dragElem, arguments);
}
}
}
$(this).each(function(){
$(this).bind('mousedown', function(e){
var dragElem = this,
event = e;
drag(dragElem, event);
});
});
return this;
}
});
</script> <script>
(function(){
var dragEnd = false;
$('.drag-elem').drag(
function(){
$(this).text('准备拖动').css({ zIndex: 2 }).siblings().css({ zIndex: 1 });
},
function(){
var offset = $(this).offset();
dragEnd = true;
$(this).text('拖动中(' + offset.left + ',' + offset.top + ')' );
},
function(){
if (dragEnd) {
$(this).text('拖动结束');
dragEnd = false;
}
}
);
}());
</script>
</body>
</html>
源码更新 2014/02/19
$.fn.extend({
/**
*
* 扩展jQuery原型,实现鼠标事件模拟元素拖动
* drag中的回调函数this指向被拖动元素
* @ method: drag
* @ use: $( selector ).drag( dragStartFn, dragMoveFn, dragEndFn )
* @ param { function } 第一个参数,准备拖动处理函数
* @ param { function } 第二个参数,拖动中处理函数
* @ param { function } 第三个参数,拖动结束处理函数
* @ reutrn { jQuery( selector ) }
*
*/
drag: function( dragStartFn, dragMoveFn, dragEndFn ) {
function drag( target, e ) {
var offsetX, offsetY, beforePageX, beforePageY;
if ( $.isFunction(dragStartFn) ) {
dragStartFn.apply(target, arguments);
}
// 移动前或移动中的元素位置
offsetX = parseInt( $(target).css('left'), 10 ) || 0;
offsetY = parseInt( $(target).css('top'), 10 ) || 0;
// 移动前或移动中的鼠标位置
beforePageX = e.clientX;
beforePageY = e.clientY;
$(document).bind('mousemove', moveHandle)
.bind('mouseup', upHandle);
// 鼠标移动事件处理
function moveHandle (e) {
// 更新移动中或移动终止后的元素位置
var x = offsetX + e.clientX - beforePageX;
var y = offsetY + e.clientY - beforePageY;
$(target).css({
left: x + 'px',
top: y + 'px'
});
if ( $.isFunction(dragMoveFn) ) {
dragMoveFn.apply(target, arguments);
}
// 阻止浏览器默认行为(鼠标在拖动图片一小段距离,会出现一个禁止的小提示,即:图片不能再拖动)
e.preventDefault();
}
// 鼠标弹起事件处理
function upHandle (e) {
$(document).unbind('mousemove', moveHandle)
.unbind('mouseup', upHandle);
if ( $.isFunction(dragEndFn) ) {
dragEndFn.apply(target, arguments);
}
}
}
$(this).each(function(){
$(this).bind('mousedown', function(e){
drag(this, e);
});
});
return this;
}
});
// 调用实例
(function(){
var dragEnd = false;
$('div').drag(
function(){
$(this).html('<span>准备拖动</span>').css({ zIndex: 2 }).siblings().css({ zIndex: 1 });
},
function(){
var offset = $(this).offset();
$(this).html('<span>拖动中(' + offset.left + ',' + offset.top + ')</span>' );
},
function(){
$(this).html('<span>拖动结束</span>')
}
);
$('img').drag();
}());
JavaScript事件模拟元素拖动的更多相关文章
- 浅谈Javascript事件模拟
事件是用来描述网页中某一特定有趣时刻的,众所周知事件通常是在由用户和浏览器进行交互时触发,其实不然,通过Javascript可以在任何时间触发特定的事件,并且这些事件与浏览器创建的事件是相同的.这就意 ...
- JavaScript 事件——“模拟事件”的注意要点
DOM中的事件模拟 三个步骤: 首先通过document.createEvent()方法创建event对象,接收一个参数,即表示要创建的事件类型的字符串: UIEvents(DOM3中的UIEvent ...
- 浅谈JavaScript的事件(事件模拟)
事件经常由操作或者通过浏览器功能触发,通过JavaScript也可以触发元素的事件.通过JavaScript触发事件,也称为事件的模拟. DOM中事件模拟 可以document的createEvent ...
- javaScript事件机制深入学习(事件冒泡,事件捕获,事件绑定方式,移除事件方式,阻止浏览器默认行为,事件委托,模拟浏览器事件,自定义事件)
前言 JavaScript与HTML之间的交互是通过事件实现的.事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间.可以使用侦听器(或处理程序)来预订事件,以便事件发生时执行相应的代码.这种在传统软 ...
- JavaScript实现元素拖动性能优化
前言:前几天没事干写了个小网站,打算用原生的javascript实现元素的拖动,但是事情并没有想象的那么顺利,首先是实现了拖动的元素卡的不能再卡,简直不能够,上图~~ 看见没?这就是效果,简直让人欲哭 ...
- javascript和jquery 获取触发事件的元素
一个很简单的问题,却因为大意,经常忘了处理,导致程序运行出错. <!DOCTYPE html> <html> <head> <meta charset=&qu ...
- Javascript事件模型(二):Javascript事件的父元素和子元素
DOM事件标准定义了两种事件流,分别是捕获和冒泡.默认情况下,事件使用冒泡事件流,不使用捕获事件流.你可以指定使用捕获事件流,方法是在注册事件时传入useCapture参数,将这个参数设为true. ...
- Javascript高级编程学习笔记(72)—— 模拟事件(2)IE事件模拟
IE中的事件模拟 低版本的IE浏览器作为前端开发的一股清流,想避过都不行 虽然低版本IE正在逐步被市场淘汰,不得不承认IE8以下的浏览器依然占了不小的份额 所以这里大概介绍IE8以下的低版本IE中的事 ...
- Javascript高级编程学习笔记(71)—— 模拟事件(1)DOM事件模拟
事件,指的是网页中某个特定的交互时刻 一般来说事件由浏览器厂商负责提供,一般由用户操作或者其它浏览器功能来触发 但是有一类特殊的事件,那就是由我们开发人员通过JS触发的事件 这些事件和浏览器创建的事件 ...
随机推荐
- Docker原理探究
问题思考:-------------------------------------Docker浅显原理理解-------------------------------------P1. ubunt ...
- c++ Arx二次开发创建椭圆和样条曲线
一.本节课程 c++ Arx二次开发创建椭圆和样条曲线 二.本节要讲解的知识点 1.如何应用C++ ARX二次开发创建椭圆(对AcDbEllipse类的构造函数的直接封装和根据外接矩形来创建椭圆) 2 ...
- MVC模式简单的Xml文档解析加Vue渲染
前端代码: <script src="~/Js/jquery-3.3.1.min.js"></script> <script src="~/ ...
- Daily Scrumming* 2015.12.16(Day 8)
一.团队scrum meeting照片 二.成员工作总结 姓名 任务ID 迁入记录 江昊 任务1036 https://github.com/buaaclubs-team/temp-front/com ...
- Beta阶段冲刺-5
一. 每日会议 1. 照片 2. 昨日完成工作 3. 今日完成工作 4. 工作中遇到的困难 杨晨露:现在我过的某种意义上挺滋润的,没啥事了都.......咳,困难就是前端每天都在想砸电脑,我要怎么阻止 ...
- Ubuntu安装jdk,正确配置环境变量
作为一个Linux新手,在写这篇博客之前,装了几次jdk,好多次都是环境变量配置错误,导致无法登录系统.经过几天的研究,今天新装系统,从头来完整配置一遍 系统版本:Ubuntu 16.04 JDK版本 ...
- Postgresql迁移数据文件存放位置
1. POSTGRESQL的安装 centos7 里面默认的pgsql的版本是 如果想用更高的版本需要执行以下如下的命令 rpm -ivh https://download.postgresql.or ...
- laravel 处理自定错误页面,如404,500,501,502,503,504等等
laravel 5.0 版本下,修改pp/Exceptions/Handler.phppublic function render($request, Exception $e) { if ($e i ...
- 基于SSM的Java Web应用开发原理初探
SSM开发Web的框架已经很成熟了,成熟得以至于有点落后了.虽然如今是SOA架构大行其道,微服务铺天盖地的时代,不过因为仍有大量的企业开发依赖于SSM,本文简单对基于SSM的Java开发做一快速入门, ...
- Spring之配置文件中引入其它配置文件
<beans> ... <!--引入其它配置文件--> <import resource="classpath:com/helloworld/beans.xml ...