Чи можете ви виявити "перетягування" в jQuery?


109

У мене є пульсація, яка повинна з’являтися, коли користувач натискає посилання.

Проблема полягає в тому, що ту саму посилання можна клацати та перетягувати, щоб переставити її. У цьому випадку мені не знадобиться пульсація. Він повинен з'являтися лише в тому випадку, якщо його насправді чекає кудись поїхати.

Як я можу за допомогою jQuery створити прослуховувач подій, який дозволив би з'явитися пульсацію лише у випадку, якщо це клацання посилання на посилання , а не натискання та перетягування?


Можливо OOT? Я спробував кілька підходів для перетягування з включенням інтерфейсу jQuery з включенням інтерфейсу jQuery, власний код з подіями mousedown, mouseup, mousemove та той, який найкраще працював - github.com/haberman/jdragdrop .
Рафаель Вега

Ось ще одне просте рішення без важких рамок. blog.blakesimpson.co.uk/read/…
програміст з хімічних речовин

Відповіді:


225

Початок встановлення стану, якщо подія переміщення миші запущено, запишіть її, нарешті, на миші, перевірте, чи рухалася миша. Якщо він рухався, ми затягувались. Якщо ми не переїхали, це клацання.

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
hey..can ви допомогти мені з цим stackoverflow.com/questions/19703617 / ...
Хіра Тхакур

2
Ви можете додати поріг перетягування, щоб ваші кліки не трактувалися як перетягування елемента "a". Просто шукайте певну кількість змін у події переміщення миші x та y.
Попелясто-блакитний

Дивовижно, одразу після того, як вітер відкрутить миші, я поставив свій код, щоб діяти, як тільки було виявлено початок перетягування. Дякую тобі!
Валамас

3
Я виявив, що в деяких випадках та / або браузерах mousemoveвсе одно буде запускатися хоча б раз навіть без будь-якого руху, тому я змінив його, щоб збільшити змінну при русі, а потім перевірити певний поріг на mouseup jsfiddle.net/W7tvD/1649 Зараз працює для мене як шарм, дякую!
півбіт

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 click ...
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");
});

Це рішення використовує функції "увімкнено" та "вимкнено", щоб прив'язати від'єднати подію переміщення миші (прив'язка та відключення застаріли). Ви також можете виявити зміну позицій миші 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, щоб у вас не було побічних ефектів під час прослуховування подій миші:

<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. Якщо ви цього не зробите, прикріпіть слухача до миші (), а не натисніть ().


1
Як би миші відрізняли перетягування та натискання?
Поїздка

Гммм - так, гадаю, я не продумав це достатньо. Можливо, у вас може бути один слухач, прикріплений до міста, який записує координати миші. Тоді якщо координати миші на миші є однаковими (або дійсно близькими), вважайте це клацанням.
Quasipickle


Відповідь також 4 роки - врахуйте це.
Quasipickle

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

Вам не потрібно встановлювати змінну, ви можете просто встановити, якщо вона рухається в атрибуті data

$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.