Можете ли вы обнаружить «перетаскивание» в 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() {

  }
});

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

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 и надеюсь, что это лучшее решение для вас. удачи


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

^^


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


Ответу тоже 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
        }
    });

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;
});
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.