Можете ли вы обнаружить «перетаскивание» в jQuery?

109

У меня есть пульсация, которая появляется, когда пользователь нажимает на ссылку.

Проблема в том, что ту же ссылку можно щелкнуть и перетащить, чтобы изменить порядок. В этом случае мне не нужно, чтобы пульсатор появлялся. Он должен появиться только в том случае, если он действительно ждет куда-нибудь.

Как я могу с помощью jQuery создать прослушиватель событий, который позволял бы показывать пульсирующее устройство только в том случае, если это щелчок по ссылке , а не щелчок и перетаскивание?

Поездка
источник
Возможно OOT? Я пробовал несколько подходов для перетаскивания с помощью jQuery, включая пользовательский интерфейс jQuery, мой собственный код с событиями mousedown, mouseup, mousemove, а лучше всего работал github.com/haberman/jdragdrop .
Рафаэль Вега,
Вот еще одно простое решение без тяжелого фреймворка. blog.blakesimpson.co.uk/read/…
Программист-химик

Ответы:

226

В 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/

Симен Эххольт
источник
1
эй .. вы можете помочь мне с этим stackoverflow.com/questions/19703617/…
ХИРА ТАКУР
2
Возможно, вы захотите добавить порог перетаскивания, чтобы ваши щелчки не интерпретировались как перетаскивание элемента «a». Просто посмотрите на определенное количество изменений в событии перемещения мыши по осям x и y.
Ash Blue
Круто, сразу после того, как ветер отвязал движение мыши, я заставил свой код действовать, как только было обнаружено начало перетаскивания. Спасибо вам!
Valamas
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() {

  }
});
GaidenFocus
источник
6
Вам нужен jquery-ui, но это самый простой способ.
Ортомала Локни
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 (привязка и отключение устарели). Вы также можете обнаружить изменение положения мыши по оси 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();
});
syC
источник
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

Самый простой способ - это коснуться начала, коснуться перемещения и коснуться конца. Это работает как для ПК, так и для сенсорных устройств, просто проверьте это в документации jquery и надеюсь, что это лучшее решение для вас. удачи

Anup
источник
1

Плагин 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!');
});

^^

ipfaffen
источник
1

Убедитесь, что вы установили перетаскиваемый элемент значение 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

Вам нужно установить таймер. Когда таймер истечет, запустите вибратор и зарегистрируйте щелчок. Когда происходит перетаскивание, очистите таймер, чтобы оно никогда не завершалось.

Диодей - Джеймс Макфарлейн
источник
1
.. очень умно, как определить сопротивление?
Поездка
1
когда вы настраиваете Draggable, должно быть событие onDrag. Подключи это там.
Диодеус - Джеймс Макфарлейн
0

Если вы используете jQueryUI - есть событие onDrag. В противном случае прикрепите слушателя к mouseup (), а не click ().

Квазипикл
источник
1
Как mouseup будет различать перетаскивание и щелчок?
Поездка
Хммм - да, полагаю, я недостаточно обдумал это. Возможно, вы можете подключить к mousedown одного слушателя, который записывает координаты мыши. Затем, если координаты мыши при наведении курсора совпадают (или действительно близки), считайте это щелчком.
Quasipickle
Это не работает: stackoverflow.com/questions/12231147/…
Чак Ле Батт
Ответу тоже 4 года - учтите.
Quasipickle 02
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
        }
    });
Aiphee
источник
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;
});
Julesezaar
источник