JavaScript特效:通过拖拽移动网页元素

本文由尤慕译自这里,转载请保留此条信息。

试着拖动下面任意一个Item:


Item 1 is <div>
Item 2 is <div>
drag image
NON-draggable element clicked

(上面的无效,你应该访问Here或原文)

介绍


关于用JavaScript实现拖拽,我没有找到一篇简洁又易懂的文章。因此我自己写了一篇,如下。

可拖动元素


首先把元素属性标记为class="drag".  只需要 css 为:

.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 上的相关事件: onMouseDownonMouseMove, and onMouseUp.  企图在元素上使用 onMouseMove 事件完成拖拽操作会产生问题,因为当鼠标移动过快时焦点容易跳出元素范围;除非鼠标重回到元素,onMouseMove 事件将会停止触发。显然这不是我们想要的,所以我们把onMouseMove 事件把绑定在document上。

首先初始化onmousedown和onmouseup这两个事件:

InitDragDrop();

function InitDragDrop()
{
    document.onmousedown = OnMouseDown;
    document.onmouseup = OnMouseUp;
}

再来看看 onMouseDown:

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;
    }
}

注释解释得很清楚,注意在拖动元素时文本被选中的情况。

一旦 OnMouseMove 绑定好, 它便会捕获鼠标移动事件:

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 + ')';   
}

鼠标释放后, 移除事件监听器 并且重置 _dragElement:

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);
}

需要考虑的


本文只涉及到拖拽操作的表面,要深入请参考其它。

<iframe />


还没有测试在iframe下的情况,但很显然,应该用 event.screenX 和 event.screenY 代替 clientX 和 clientY ,如果你用的是iframes.

鼠标按钮


因为浏览器制造商爱搞不兼容, event.button 的值也是随浏览器的不同而不同; 如下:

BrowserLeft ClickMiddle ClickRight Click
Firefox012
Internet Explorer142

浏览器兼容性


在 IE6&7, Firefox 3.0.5, Opera 9.2+, and Chrome 2.0测试通过。

支持一下


如果喜欢就转走吧.  If you really want to show your appreciation... :-)


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值