Czy potrafisz wykryć „przeciąganie” w jQuery?


109

Mam pulsujący, który pojawia się, gdy użytkownik kliknie link.

Problem polega na tym, że ten sam link można kliknąć i przeciągnąć, aby zmienić jego kolejność. W tym przypadku nie potrzebowałbym, aby pojawił się pulsujący. Musi się pojawić tylko wtedy, gdy faktycznie czeka, aby gdzieś iść.

Jak mogę za pomocą jQuery stworzyć nasłuchiwanie zdarzeń, które pozwoliłoby na pojawienie się pulsującego tylko wtedy, gdy jest to kliknięcie do linku , a nie kliknięcie i przeciągnięcie?


Może OOT? Wypróbowałem kilka podejść do przeciągania i upuszczania z jQuery, w tym interfejs użytkownika jQuery, mój własny kod z zdarzeniami mousedown, mouseup, mousemove, a ten, który działał najlepiej, to github.com/haberman/jdragdrop .
Rafael Vega

Oto kolejne proste rozwiązanie bez ciężkich ram. blog.blakesimpson.co.uk/read/…
Programista chemiczny

Odpowiedzi:


226

Przy wyciąganiu kursora zacznij ustawiać stan, jeśli zdarzenie mousemove zostanie uruchomione, nagraj je, a na końcu po najechaniu myszą sprawdź, czy mysz się poruszyła. Jeśli się poruszył, przeciągnęliśmy. Jeśli się nie ruszyliśmy, to kliknięcie.

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

Oto demo: http://jsfiddle.net/W7tvD/1399/


1
hej .. czy możesz mi pomóc z tym stackoverflow.com/questions/19703617/…
HIRA THAKUR

2
Możesz chcieć dodać próg przeciągania, aby kliknięcia nie były interpretowane jako przeciągnięcia elementu „a”. Po prostu poszukaj pewnej zmiany w zdarzeniu przesunięcia myszy xiy.
Ash Blue

Niesamowite, zaraz po tym, jak wiatr odwiązał ruch myszy, wstawiłem kod tak, aby działał natychmiast po wykryciu początku przeciągania. dzięki Ci!
Valamas

3
Zauważyłem, że w niektórych przypadkach i / lub przeglądarkach mousemovenadal będą odpalane przynajmniej raz, nawet bez żadnego ruchu, więc zmieniłem to, aby zwiększać zmienną przy ruchu, a następnie sprawdzałem pewien próg na mouseup jsfiddle.net/W7tvD/1649 Teraz działa jak urok, dzięki!
Halfbit

27

Z jakiegoś powodu powyższe rozwiązania nie działały u mnie. Poszedłem z następującymi:

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

Możesz dostosować limit odległości do cokolwiek zechcesz, a nawet sprowadzić go do zera.


Najlepsza odpowiedź, bardzo mi pomogła. Tylko jedna myśl: Math.sqrt nie jest naprawdę potrzebny, lepiej działa z odległościami kwadratowymi (sqrt jest powolne, może wpłynąć na UX).
Bruno Ferreira

1
sqrtnie jest powolny i nie wpłynie na UX, nawet jeśli zrobiłeś to setki razy.
NateS

Tak, martw się o niepotrzebny pierwiastek kwadratowy w wewnętrznej pętli silnika fizycznego, a nie o
moduł

19

Dzięki interfejsowi jQuery po prostu zrób to!

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

  },
  drag: function() {

  },
  stop: function() {

  }
});

6
Potrzebujesz jquery-ui, ale to najłatwiejszy sposób.
Ortomala Lokni

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

To rozwiązanie korzysta z funkcji „on” i „off” w celu powiązania zdarzenia „unbind” ze zdarzeniem mousemove (powiązanie i rozłączenie są przestarzałe). Możesz również wykryć zmianę pozycji x i y myszy między dwoma zdarzeniami przesunięcia myszy.


3

Spróbuj tego: pokazuje, kiedy jest „przeciągnięty”. ;) link skrzypcowy

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

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

2

Odłączyłem się od zaakceptowanej odpowiedzi, by biec tylko wtedy, gdy kliknięcie jest HELD w dół i przeciągane .

Moja funkcja działała, gdy nie przytrzymywałem myszy. Oto zaktualizowany kod, jeśli chcesz również skorzystać z tej funkcji:

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

Najprostszy sposób to start dotykowy, ruch dotykowy i koniec dotykowy. To działa zarówno na komputerze, jak i urządzeniu dotykowym, po prostu sprawdź to w dokumentacji jQuery i miej nadzieję, że jest to najlepsze rozwiązanie dla Ciebie. powodzenia


1

Wtyczka jQuery oparta na odpowiedzi Simena Echholta. Nazwałem to jednym kliknięciem.

/**
 * 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);
        });
    });
};

W użyciu:

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

^^


1

Upewnij się, że ustawiłeś atrybut draggable elementu na false, aby nie mieć efektów ubocznych podczas słuchania zdarzeń mouseup:

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

Następnie możesz użyć 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

Musisz ustawić minutnik. Kiedy licznik czasu wygaśnie, uruchom pulsator i zarejestruj kliknięcie. Kiedy wystąpi przeciąganie, wyczyść licznik czasu, aby nigdy się nie skończył.


1
..bardzo sprytnie, jak rozpoznajesz opór?
Wycieczka

1
kiedy konfigurujesz Draggable, powinno być zdarzenie onDrag. Podłącz to tam.
Diodeus - James MacFarlane

0

Jeśli używasz jQueryUI - istnieje zdarzenie onDrag. Jeśli nie, to dołącz swój listener do mouseup (), a nie kliknij ().


1
Jak mysz rozróżnia przeciągnięcie od kliknięcia?
Wycieczka

Hmmm - tak, chyba nie przemyślałem tego wystarczająco. Być może możesz mieć jednego słuchacza dołączonego do przycisku myszy, który rejestruje współrzędne myszy. Następnie, jeśli współrzędne myszy po najechaniu myszą są takie same (lub bardzo bliskie), potraktuj to jako kliknięcie.
Quasipickle


Odpowiedź też ma 4 lata - zastanów się nad tym.
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

Nie musisz ustawiać zmiennej, możesz po prostu ustawić, czy porusza się w atrybucie danych

$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

Potrzebowałem funkcji, która zawsze śledzi pozycję myszy i wykrywa przeciąganie w lewo, w prawo, w górę i w dół. Nie uruchamia się również po kliknięciu, ale wymaga ruchu o co najmniej 15 pikseli

/**
 * 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;
});
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.