试着拖动下面任意一个Item:
Item 1 is <div>
Item 2 is <div>
![drag image](http://luke.breuer.com/tutorial/drag_image.png)
NON-draggable element clicked
(上面的无效,你应该访问Here或原文)
介绍
关于用JavaScript实现拖拽,我没有找到一篇简洁又易懂的文章。因此我自己写了一篇,如下。
可拖动元素
. 只需要 css 为:
.drag { position: relative; }
.drag { position: relative; }
全局变量
要使代码可行,我们还需要一些全局变量:
var _startX = 0; // 鼠标开始的位置
var _startY = 0;
var _offsetX = 0; // 当前元素的位置
var _offsetY = 0;
var _dragElement; // 需要从 OnMouseDown 传递给 OnMouseMove
var _oldZIndex = 0; // 拖拽的时候增加z-index的值
var _debug = $('debug'); // 调试信息
JavaScript 事件
绑定到 document 上的相关事件: 事件完成拖拽操作会产生问题,因为当鼠标移动过快时焦点容易跳出元素范围;除非鼠标重回到元素, 事件将会停止触发。显然这不是我们想要的,所以我们把 事件把绑定在document上。
, , and . 企图在元素上使用首先初始化onmousedown和onmouseup这两个事件:
InitDragDrop();
function InitDragDrop()
{
document.onmousedown = OnMouseDown;
document.onmouseup = OnMouseUp;
}
再来看看 :
function OnMouseDown(e)
{
// IE 有点弱智,不会传递event对象
if (e == null)
e = window.event;
// IE 使用 srcElement, 其它浏览器使用 target
var target = e.target != null ? e.target : e.srcElement;
_debug.innerHTML = target.className == 'drag'
? 'draggable element clicked'
: 'NON-draggable element clicked';
// IE中left click == 1
// Firefox中left click == 0
if ((e.button == 1 && window.event != null ||
e.button == 0) &&
target.className == 'drag')
{
// 获取鼠标位置
_startX = e.clientX;
_startY = e.clientY;
// 获取元素位置
_offsetX = ExtractNumber(target.style.left);
_offsetY = ExtractNumber(target.style.top);
// 当拖拽时将元素放到前端
_oldZIndex = target.style.zIndex;
target.style.zIndex = 10000;
// OnMouseMove中需要用到
_dragElement = target;
// 记元素跟着鼠标移动
document.onmousemove = OnMouseMove;
// 阻止鼠标移动过程中选中文本
document.body.focus();
// 阻止IE的文本选中
document.onselectstart = function () { return false; };
// 阻止IE的图像移动
target.ondragstart = function() { return false; };
// 阻止其它浏览器的文本选中
return false;
}
}
注释解释得很清楚,注意在拖动元素时文本被选中的情况。
一旦
绑定好, 它便会捕获鼠标移动事件:
function OnMouseMove(e)
{
if (e == null)
var e = window.event;
// 元素“拖动”的代码
_dragElement.style.left = (_offsetX + e.clientX - _startX) + 'px';
_dragElement.style.top = (_offsetY + e.clientY - _startY) + 'px';
_debug.innerHTML = '(' + _dragElement.style.left + ', ' +
_dragElement.style.top + ')';
}
鼠标释放后, 移除事件监听器 并且重置
:
function OnMouseUp(e)
{
if (_dragElement != null)
{
_dragElement.style.zIndex = _oldZIndex;
// 在下一次 OnMouseDown,重置这些变量
document.onmousemove = null;
document.onselectstart = null;
_dragElement.ondragstart = null;
// 通过它判断是否在进行拖动操作
_dragElement = null;
_debug.innerHTML = 'mouse up';
}
}
工具函数
function ExtractNumber(value)
{
var n = parseInt(value);
return n == null || isNaN(n) ? 0 : n;
}
// 简化获取元素的操作
function $(id)
{
return document.getElementById(id);
}
function ExtractNumber(value)
{
var n = parseInt(value);
return n == null || isNaN(n) ? 0 : n;
}
// 简化获取元素的操作
function $(id)
{
return document.getElementById(id);
}
需要考虑的
本文只涉及到拖拽操作的表面,要深入请参考其它。
<iframe />
还没有测试在iframe下的情况,但很显然,应该用
和 代替 和 ,如果你用的是 .鼠标按钮
因为浏览器制造商爱搞不兼容,
的值也是随浏览器的不同而不同; 如下:Browser | Left Click | Middle Click | Right Click |
---|---|---|---|
Firefox | 0 | 1 | 2 |
Internet Explorer | 1 | 4 | 2 |
浏览器兼容性
在 IE6&7, Firefox 3.0.5, Opera 9.2+, and Chrome 2.0测试通过。
支持一下
如果喜欢就转走吧. If you really want to show your appreciation... :-)