您可以在jQuery中检测“拖动”吗?


109

我有一个用户单击链接时会出现的异常现象。

问题是可以单击并拖动相同的链接来重新排列。在这种情况下,我不需要出现跳动者。仅当它实际上等待去某个地方时才需要出现。

我如何使用jQuery创建一个事件侦听器,该事件侦听器仅在单击链接时显示跳动,而不是单击并拖动才能出现


也许是OOT?我已经尝试了多种使用jQuery UI拖放的方法,包括jQuery UI,我自己的代码包含mousedown,mouseup,mousemove事件,而效果最好的方法是github.com/haberman/jdragdrop
拉斐尔·维加

这是另一个没有任何繁重框架的简单解决方案。blog.blakesimpson.co.uk/read/…–
化学程序员

Answers:


224

在mousedown上,开始设置状态,如果触发了mousemove事件,则将其记录下来,最后在mouseup上,检查鼠标是否移动。如果它移动了,我们一直在拖。如果我们没有移动,那就单击一下。

var isDragging = false;
$("a")
.mousedown(function() {
    isDragging = false;
})
.mousemove(function() {
    isDragging = true;
 })
.mouseup(function() {
    var wasDragging = isDragging;
    isDragging = false;
    if (!wasDragging) {
        $("#throbble").toggle();
    }
});

这是一个演示:http : //jsfiddle.net/W7tvD/1399/



2
您可能要添加一个拖动阈值,以使您的点击次数不会被解释为“ a”元素上的拖动。只需在x和y mousemove事件中查找一定量的变化即可。
灰蓝色

太棒了,在风解除绑定mousemove之后,我将我的代码一经检测到开始拖动就立即执行。谢谢!
Valamas 2014年

3
我发现在某些情况下和/或浏览器中,mousemove即使没有任何移动,它仍然会至少触发一次,因此我对其进行了更改,以增加移动时的变量,然后在mouseup jsfiddle.net/W7tvD/1649中检查某个阈值 现在对我来说就像魅力一样,谢谢!
Halfbit

27

由于某种原因,上述解决方案对我不起作用。我进行以下操作:

$('#container').on('mousedown', function(e) {
    $(this).data('p0', { x: e.pageX, y: e.pageY });
}).on('mouseup', function(e) {
    var p0 = $(this).data('p0'),
        p1 = { x: e.pageX, y: e.pageY },
        d = Math.sqrt(Math.pow(p1.x - p0.x, 2) + Math.pow(p1.y - p0.y, 2));

    if (d < 4) {
        alert('clicked');
    }
})

您可以将距离限制调整为任意值,甚至可以一直调整为零。


最佳答案,对我有很大帮助。只是想一想:Math.sqrt并不是真正必需的,可以更好地处理平方距离(sqrt很慢,可能会影响UX)。
布鲁诺·费雷拉

1
sqrt不会慢,并且不会影响UX,即使您执行了数百次也不会。
NateS

是的,您担心物理引擎的内循环中不必要的平方根,而不是您的jquery单击处理程序...
PeterT

19

使用jQuery UI即可!

$( "#draggable" ).draggable({
  start: function() {

  },
  drag: function() {

  },
  stop: function() {

  }
});

6
您需要jquery-ui,但这是最简单的方法。
Ortomala Lokni '16

5
$(".draggable")
.mousedown(function(e){
    $(this).on("mousemove",function(e){
        var p1 = { x: e.pageX, y: e.pageY };
        var p0 = $(this).data("p0") || p1;
        console.log("dragging from x:" + p0.x + " y:" + p0.y + "to x:" + p1.x + " y:" + p1.y);
        $(this).data("p0", p1);
    });
})
.mouseup(function(){
    $(this).off("mousemove");
});

此解决方案使用“ on”和“ off”功能来绑定取消绑定的mousemove事件(不建议使用bind和unbind)。您还可以检测到两个mousemove事件之间鼠标x和y位置的变化。


3

尝试以下操作:它显示何时处于“拖动”状态。;) 小提琴链接

$(function() {
    var isDragging = false;
    $("#status").html("status:");
    $("a")
    .mousedown(function() {
        $("#status").html("status: DRAGGED");        
    })
    .mouseup(function() {
        $("#status").html("status: dropped");   
    });

    $("ul").sortable();
});

2

我从接受的答案中分支出来,仅在单击并拖动单击时才运行

当我不按住鼠标时,函数正在运行。如果您还需要此功能,请参见以下更新的代码:

var isDragging = false;
var mouseDown = false;

$('.test_area')
    .mousedown(function() {
        isDragging = false;
        mouseDown = true;
    })
    .mousemove(function(e) {
        isDragging = true;

        if (isDragging === true && mouseDown === true) {
            my_special_function(e);
        }
     })
    .mouseup(function(e) {

        var wasDragging = isDragging;

        isDragging = false;
        mouseDown = false;

        if ( ! wasDragging ) {
            my_special_function(e);
        }

    }
);

1

最简单的方法是触摸开始,触摸移动和触摸结束。可以在PC和触摸设备上使用,只需在jquery文档中进行检查,并希望这对您来说是最佳的解决方案。祝好运


1

基于Simen Echholt答案的jQuery插件。我称它为“单击”。

/**
 * jQuery plugin: Configure mouse click that is triggered only when no mouse move was detected in the action.
 * 
 * @param callback
 */
jQuery.fn.singleclick = function(callback) {
    return $(this).each(function() {
        var singleClickIsDragging = false;
        var element = $(this);

        // Configure mouse down listener.
        element.mousedown(function() {
            $(window).mousemove(function() {
                singleClickIsDragging = true;
                $(window).unbind('mousemove');
            });
        });

        // Configure mouse up listener.
        element.mouseup(function(event) {
            var wasDragging = singleClickIsDragging;
            singleClickIsDragging = false;
            $(window).unbind('mousemove');
            if(wasDragging) {
                return;
            }

            // Since no mouse move was detected then call callback function.
            callback.call(element, event);
        });
    });
};

正在使用:

element.singleclick(function(event) {
    alert('Single/simple click!');
});

^^


1

确保将元素的draggable属性设置为false,以便在监听mouseup事件时没有副作用:

<div class="thing" draggable="false">text</div>

然后,您可以使用jQuery:

$(function() {
  var pressed, pressX, pressY,
      dragged,
      offset = 3; // helps detect when the user really meant to drag

  $(document)
  .on('mousedown', '.thing', function(e) {
    pressX = e.pageX;
    pressY = e.pageY;
    pressed = true;
  })
  .on('mousemove', '.thing', function(e) {
    if (!pressed) return;
    dragged = Math.abs(e.pageX - pressX) > offset ||
              Math.abs(e.pageY - pressY) > offset;
  })
  .on('mouseup', function() {
    dragged && console.log('Thing dragged');
    pressed = dragged = false;
  });
});


0

如果您使用的是jQueryUI,则存在onDrag事件。如果不是,则将侦听器附加到mouseup(),而不是click()。


1
mouseup如何区分拖动和点击?
旅行

嗯-是的,我想我认为还不够。也许您可以在mousedown上附加一个侦听器,以记录鼠标的坐标。然后,如果mouseup上的鼠标坐标是相同的(或真的很接近),则将其视为单击。
Quasipickle 2010年


答案也是4岁-考虑一下。
Quasipickle 2014年

0
// here is how you can detect dragging in all four directions
var isDragging = false;
$("some DOM element").mousedown(function(e) {
    var previous_x_position = e.pageX;
    var previous_y_position = e.pageY;

    $(window).mousemove(function(event) {
        isDragging = true;
        var x_position = event.pageX;
        var y_position = event.pageY;

        if (previous_x_position < x_position) {
            alert('moving right');
        } else {
            alert('moving left');
        }
        if (previous_y_position < y_position) {
            alert('moving down');
        } else {
            alert('moving up');
        }
        $(window).unbind("mousemove");
    });
}).mouseup(function() {
    var wasDragging = isDragging;
    isDragging = false;
    $(window).unbind("mousemove");
});

0

您不必设置变量,只需设置它是否在数据属性中移动

$youtubeSlider.find('a')
    .on('mousedown', function (e) {
        $(this).data('moving', false);
    })
    .on('mousemove', function (e) {
        $(this).data('moving', true);
    })
    .on('mouseup', function (e) {
        if (!$(this).data('moving')) {
            // Open link
        }
    });

0

我需要一个始终跟踪鼠标位置并检测向左,向右,向上,向下拖动的功能。它也不会触发点击,但至少需要移动15像素

/**
 * Check for drag when moved minimum 15px
 * Same time keep track of mouse position while dragging
 */
// Variables to be accessed outside in other functions
var dragMouseX;
var dragMouseY;
var myDragging = false; // true or false
var dragDirectionX = false; // left or right
var dragDirectionY = false; // top or bottom

$(document).on("mousedown", function(e) {
    // Reset some variables on mousedown
    var lastDirectionCheck = e.timeStamp;
    var dragStartX = e.pageX;
    var dragStartY = e.pageY;
    dragMouseX = e.pageX;
    dragMouseY = e.pageY;
    myDragging = false;
    dragDirectionX = false;
    dragDirectionY = false;

    // On the move
    $(document).on("mousemove", function(e) {
        dragMouseX = e.pageX;
        dragMouseY = e.pageY;

        // Recalculate drag direction every 200ms in case user changes his mind
        if (e.timeStamp > (lastDirectionCheck + 200)) {
            dragStartX = dragMouseX;
            dragStartY = dragMouseY;
            lastDirectionCheck = e.timeStamp;
        }

        // Check for drag when moved minimum 15px in any direction
        if (!myDragging && Math.abs(dragStartX - dragMouseX) > 15 || Math.abs(dragStartY - dragMouseY) > 15) {
            myDragging = true;
        }
        if (myDragging) {
            // Check drag direction X
            if (dragStartX > dragMouseX) dragDirectionX = 'left';
            if (dragStartX < dragMouseX) dragDirectionX = 'right';

            // Check drag direction Y
            if (dragStartY > dragMouseY) dragDirectionY = 'top';
            if (dragStartY < dragMouseY) dragDirectionY = 'bottom';

            // console.log(dragDirectionX + ' ' + dragDirectionY);
        }
    });
});

// Reset some variables again on mouseup
$(document).on("mouseup", function() {
    $(document).off("mousemove");
    myDragging = false;
    dragDirectionX = false;
    dragDirectionY = false;
});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.