拖拽

字数 501阅读 42

JavaScript拖拽实现

背景

在学习开发了签名板之后,为了更加一步学习和理解事件的位置坐标这一块的知识点,自己用原生的js实现了一个可以拖拽的div框。

功能分析

首先,需要有一个可拖拽的对象,如图,一个比较简陋的拖拽框:

拖拽.png

在这个框中。我们只能在标题栏部分才可以进行拖拽,拖拽分为三步骤:

1、鼠标在标题栏部分按下后可以进行拖拽

2、移动按下的鼠标,拖拽框也会跟着移动

3、鼠标松开,拖拽结束。

功能实现

通过上述的功能分析,可以将功能分为mousedown,mousemove,mouseup三个部分。下面一步一步对拖拽功能进行分解。

变量初始化

下面代码为这个功能需要声明的对象和变量等

    var flag = false;  // flag用来标志鼠标是否在标题栏部分按下去
    var wrap = document.getElementById('wrap'); // 获取到整个拖拽框对象
    var head = document.getElementById('tzHead'); // 获取到拖拽框中标题栏对象

    var now = {
        x:'',
        y:''
    }; // 当前的鼠标位置

    var last = {
        x:'',
        y:''
    }; // 鼠标按下的时候的鼠标位置

    var initPosition = {
        x:'',
        y:''
    }; // 鼠标按下时的拖拽框相对偏移的位置
事件绑定
  head.addEventListener('mousedown',beginDrag,false);

  head.addEventListener('mousemove',drag,false);

  head.addEventListener('mouseup',endDrag,false);
方法实现

1、开始拖拽方法:

  function beginDrag(e) {
        flag = true;
        last.x = e.pageX;
        last.y = e.pageY;
        initPosition = {
            x: wrap.offsetLeft,
            y: wrap.offsetTop
        };
    }

2、拖拽方法:

function drag(e) {
        if (flag) {
            now = {
                x: e.pageX,
                y: e.pageY
            };
            wrap.style.left = parseInt(now.x) - parseInt(last.x) + parseInt(initPosition.x) + 'px';
            wrap.style.top = parseInt(now.y) - parseInt(last.y) + parseInt(initPosition.y) + 'px';
            return false;
        }
    }

3、结束拖拽

function endDrag(e) {
        flag = false;
}
问题

现在已经实现了最基本的拖拽功能。可是这时候会有一个问题,就是如果我们鼠标滑动的很快,就很容易鼠标从head区域出来,然后出来后松开鼠标,下次在head区域内不用点击就可以移动拖拽框,这样非常不友好。

优化

针对上面这种情况,在好好看了看代码后发现。下面这段代码是有问题的:

  head.addEventListener('mousedown',beginDrag,false);

  head.addEventListener('mousemove',drag,false);

  head.addEventListener('mouseup',endDrag,false);

对于鼠标按下事件,必须要绑定在head区域。可是拖拽事件和鼠标松开事件应该针对于整个文档。于是改为

  head.addEventListener('mousedown',beginDrag,false);

  document.addEventListener('mousemove',drag,false);

  document.addEventListener('mouseup',endDrag,false);

上述问题不存在了。

后续优化

对于代码功能而言已经完成了功能,但是代码质量需要很大程度的优化。

推荐阅读更多精彩内容