【问题标题】:pure javascript draggable element纯javascript可拖动元素
【发布时间】:2015-06-24 13:22:00
【问题描述】:

我知道网上有这样做的例子,但每个例子都不一样,我自己的实现也是如此。我试图弄清楚我的实现出了什么问题,因为它没有按预期工作。

代码sn-p:

var mousePressX = -1;
var mousePressY = -1;

document.getElementById("contextMenu").addEventListener("mousedown", function(event) {
    mousePressX = event.clientX;
    mousePressY = event.clientY;
}, false);

document.getElementById("contextMenu").addEventListener("mouseup", function(event) {
    mousePressX = -1;
    mousePressY = -1;
}, false);

document.getElementById("contextMenu").addEventListener("mousemove", function(event) {
    if (mousePressX != -1 && mousePressY != -1) {
        repositionElement(event.target, event.clientX, event.clientY);
    }
}, false);

function repositionElement(element, currentMouseX, currentMouseY) {
    element.style.left = element.offsetLeft + (currentMouseX - mousePressX) + 'px';
    element.style.top = element.offsetTop + (currentMouseY - mousePressY) + 'px';
}

jsfiddle: http://jsfiddle.net/4rLctko8/

无法真正找出问题所在,但我注意到如果我更改以下几行:

element.style.left = element.offsetLeft + (currentMouseX - mousePressX) + 'px';
element.style.top = element.offsetTop + (currentMouseY - mousePressY) + 'px';

到:

element.style.left = currentMouseX - mousePressX + 'px';
element.style.top = currentMouseY - mousePressY + 'px';

只有当元素被拖动到正 x 轴(向右)和正 y 轴(到底部)时,元素才会被正确拖动,并且当触发 mouseup 时,它将定位在附近的某个地方最左上角区域(0,0左右)

【问题讨论】:

    标签: javascript draggable


    【解决方案1】:

    很有趣,到目前为止只用 jQuery 做过。稍微改写一下,并确保每个 mousemove 之后都删除了它的事件侦听器 - 这将是内存泄漏,否则您可能会开始注意到:

    http://jsfiddle.net/8wtq17L8/

    var contextmenu = document.getElementById('contextMenu');
    var initX, initY, mousePressX, mousePressY;
    
    contextmenu.addEventListener('mousedown', function(event) {
    
        initX = this.offsetLeft;
        initY = this.offsetTop;
        mousePressX = event.clientX;
        mousePressY = event.clientY;
    
        this.addEventListener('mousemove', repositionElement, false);
    
        window.addEventListener('mouseup', function() {
          contextmenu.removeEventListener('mousemove', repositionElement, false);
        }, false);
    
    }, false);
    
    function repositionElement(event) {
        this.style.left = initX + event.clientX - mousePressX + 'px';
        this.style.top = initY + event.clientY - mousePressY + 'px';
    }
    

    似乎运作良好。 :-)

    ++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++

    编辑 - 我想我也会添加一个支持触摸的版本(尽管较新的设备似乎可以模拟鼠标事件)。不像 Jquery,您可以选择多个事件侦听器,因此它主要是重复,仅使用触摸事件:

    http://codepen.io/Shikkediel/pen/VLZKor?editors=011

    var object = document.getElementById('element'),
    initX, initY, firstX, firstY;
    
    object.addEventListener('mousedown', function(e) {
    
        e.preventDefault();
        initX = this.offsetLeft;
        initY = this.offsetTop;
        firstX = e.pageX;
        firstY = e.pageY;
    
        this.addEventListener('mousemove', dragIt, false);
    
        window.addEventListener('mouseup', function() {
            object.removeEventListener('mousemove', dragIt, false);
        }, false);
    
    }, false);
    
    object.addEventListener('touchstart', function(e) {
    
        e.preventDefault();
        initX = this.offsetLeft;
        initY = this.offsetTop;
        var touch = e.touches;
        firstX = touch[0].pageX;
        firstY = touch[0].pageY;
    
        this.addEventListener('touchmove', swipeIt, false);
    
        window.addEventListener('touchend', function(e) {
            e.preventDefault();
            object.removeEventListener('touchmove', swipeIt, false);
        }, false);
    
    }, false);
    
    function dragIt(e) {
        this.style.left = initX+e.pageX-firstX + 'px';
        this.style.top = initY+e.pageY-firstY + 'px';
    }
    
    function swipeIt(e) {
        var contact = e.touches;
        this.style.left = initX+contact[0].pageX-firstX + 'px';
        this.style.top = initY+contact[0].pageY-firstY + 'px';
    }
    

    【讨论】:

    • 谢谢!我想问你有没有做 window.addEventListener('mouseup' ... 而不是 this.addEventListener('mouseup' ... 以避免你可以拖动 div 并在它离开 div 的地方释放鼠标的可能性所以不会调用release事件方法?
    • 那是因为那不是问题所在。那么它需要一个循环。
    • 我知道这是旧的,但我一直在寻找拖放解决方案,而我只是想要这个拖动功能(所以没有 dropEvents)。所以这正是我一直在寻找的......我遇到的唯一问题(你的 Fiddle/Codepen 也会发生)是当你移动太快并且你的鼠标在 div 之外,拖动停止......如何你阻止这个?
    • @Goowik 您只需要使用 dragIt 函数将“mousemove”更改为窗口而不是您正在拖动的元素,这样即使您快速移动鼠标并因此在元素。
    猜你喜欢
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-19
    相关资源
    最近更新 更多