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?

Wyjazd
źródło
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/

Simen Echholt
źródło
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.

przybysz ponownie
źródło
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() {

  }
});
GaidenFocus
źródło
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.

jnaklaas
źródło
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();
});
syC
źródło
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);
        }

    }
);
Jacek
źródło
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

Anup
źródło
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!');
});

^^

ipfaffen
źródło
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;
  });
});
Marcelo Kanzaki
źródło
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ł.

Diodeus - James MacFarlane
źródło
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 ().

Quasipickle
źródło
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
To nie działa: stackoverflow.com/questions/12231147/ ...
Chuck Le Butt
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");
});
Józef
źródło
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
        }
    });
Aiphee
źródło
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;
});
Julesezaar
źródło