Können Sie das Ziehen in jQuery erkennen?

109

Ich habe einen Throbber, der angezeigt werden soll, wenn ein Benutzer auf einen Link klickt.

Das Problem ist, dass derselbe Link angeklickt und gezogen werden kann, um neu angeordnet zu werden. In diesem Fall würde ich den Throbber nicht brauchen, um zu erscheinen. Es muss nur erscheinen, wenn es tatsächlich darauf wartet, irgendwohin zu gehen.

Wie kann ich mit jQuery einen Ereignis-Listener erstellen, bei dem ein Throbber nur angezeigt wird, wenn ein Klick auf einen Link und kein Klicken und Ziehen erfolgt?

Ausflug
quelle
Vielleicht OOT? Ich habe verschiedene Ansätze für Drag & Drop mit jQuery ausprobiert, einschließlich der jQuery-Benutzeroberfläche, meines eigenen Codes mit Mousedown-, Mouseup- und Mousemove-Ereignissen. Der am besten funktionierende ist github.com/haberman/jdragdrop .
Rafael Vega
Hier ist eine weitere einfache Lösung ohne schweres Framework. blog.blakesimpson.co.uk/read/…
Chemischer Programmierer

Antworten:

224

Starten Sie beim Mousedown den Status. Wenn das Mousemove-Ereignis ausgelöst wird, zeichnen Sie es auf. Überprüfen Sie schließlich beim Mouseup, ob sich die Maus bewegt hat. Wenn es sich bewegt hat, haben wir gezogen. Wenn wir nicht umgezogen sind, ist es ein Klick.

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

Hier ist eine Demo: http://jsfiddle.net/W7tvD/1399/

Simen Echholt
quelle
1
hey..kannst du mir mit diesem stackoverflow.com/questions/19703617/… helfen
HIRA THAKUR
2
Möglicherweise möchten Sie einen Schwellenwert für das Ziehen hinzufügen, damit Ihre Klicks nicht als Verzögerung des Elements "a" interpretiert werden. Suchen Sie einfach nach einer bestimmten Änderung in einem x- und y-Mausbewegungsereignis.
Ash Blue
Genial, gleich nachdem der Wind die Maus entfernt hat, habe ich meinen Code so eingestellt, dass er funktioniert, sobald der Beginn des Ziehens erkannt wurde. Danke!
Valamas
3
Ich habe festgestellt, dass in einigen Fällen und / oder Browsern mousemoveauch ohne Bewegung noch mindestens einmal ausgelöst wird. mouseup Daher habe ich sie geändert, um die Variable bei Bewegung zu erhöhen und dann auf jsfiddle.net/W7tvD/1649 nach einem bestimmten Schwellenwert zu suchen Funktioniert jetzt wie ein Zauber für mich, danke!
Halfbit
27

Aus irgendeinem Grund funktionierten die oben genannten Lösungen bei mir nicht. Ich ging mit folgendem:

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

Sie können das Entfernungslimit nach Belieben anpassen oder sogar auf Null setzen.

neu
quelle
Beste Antwort, hat mir sehr geholfen. Nur ein Gedanke: Math.sqrt ist nicht wirklich notwendig, besser mit quadratischen Abständen arbeiten (sqrt ist langsam, könnte UX beeinflussen).
Bruno Ferreira
1
sqrtist nicht langsam und wirkt sich nicht auf UX aus, auch wenn Sie es hunderte Male getan haben.
NateS
Ja, sorgen Sie sich um unnötige Quadratwurzeln in der inneren Schleife Ihrer Physik-Engine, nicht um Ihren JQuery-Click-Handler ...
PeterT
19

Mit jQuery UI machen Sie das einfach!

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

  },
  drag: function() {

  },
  stop: function() {

  }
});
GaidenFocus
quelle
6
Sie brauchen jquery-ui, aber es ist der einfachste Weg.
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");
});

Diese Lösung verwendet die Funktionen "Ein" und "Aus", um ein Mousemove-Ereignis zu binden (Binden und Entbinden sind veraltet). Sie können auch die Änderung der x- und y-Positionen der Maus zwischen zwei Mausbewegungsereignissen erkennen.

jnaklaas
quelle
3

Versuchen Sie Folgendes: Es wird angezeigt, wann der Status "Ziehen" angezeigt wird. ;) Geigenlink

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

    $("ul").sortable();
});
syC
quelle
2

Ich bin von der akzeptierten Antwort abgezweigt, um nur zu laufen, wenn der Klick nach unten gedrückt und gezogen wird .

Meine Funktion lief, als ich die Maus nicht gedrückt hielt. Hier ist der aktualisierte Code, wenn Sie diese Funktionalität auch möchten:

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

    }
);
Jack
quelle
1

Für diesen einfachsten Weg ist Touch Start, Touch Move und Touch End. Das funktioniert sowohl für den PC als auch für das Touch-Gerät. Überprüfen Sie dies einfach in der jquery-Dokumentation und hoffen Sie, dass dies die beste Lösung für Sie ist. Viel Glück

Anup
quelle
1

jQuery-Plugin basierend auf der Antwort von Simen Echholt. Ich nannte es Single Click.

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

In Benutzung:

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

^^

ipfaffen
quelle
1

Stellen Sie sicher, dass Sie das ziehbare Attribut des Elements auf false setzen, damit beim Abhören von Mouseup-Ereignissen keine Nebenwirkungen auftreten:

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

Dann können Sie jQuery verwenden:

$(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
quelle
0

Sie müssen einen Timer einstellen. Wenn der Timer abgelaufen ist, starten Sie den Throbber und registrieren Sie den Klick. Wenn Sie ziehen, löschen Sie den Timer, damit er nie abgeschlossen wird.

Diodeus - James MacFarlane
quelle
1
..sehr klug, wie erkennt man einen Widerstand?
Reise
1
Wenn Sie Draggable einrichten, sollte ein onDrag-Ereignis auftreten. Schließen Sie es dort an.
Diodeus - James MacFarlane
0

Wenn Sie jQueryUI verwenden, gibt es ein onDrag-Ereignis. Wenn nicht, hängen Sie Ihren Listener an mouseup () an und klicken Sie nicht auf ().

Quasipickle
quelle
1
Wie würde Mouseup zwischen einem Ziehen und einem Klicken unterscheiden?
Reise
Hmmm - ja, ich glaube, ich habe es nicht genug durchdacht. Vielleicht können Sie einen Listener an mousedown anhängen lassen, der die Koordinaten der Maus aufzeichnet. Wenn dann die Koordinaten der Maus beim Mouseup gleich sind (oder wirklich nahe beieinander liegen), betrachten Sie es als einen Klick.
Quasipickle
Dies funktioniert nicht: stackoverflow.com/questions/12231147/…
Chuck Le Butt
Die Antwort ist auch 4 Jahre alt - bedenken Sie das.
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");
});
Joseph
quelle
0

Sie müssen keine Variable einrichten, Sie können nur festlegen, ob sie sich im Datenattribut bewegt

$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
quelle
0

Ich brauchte eine Funktion, die immer die Mausposition verfolgt und das Ziehen nach links, rechts, oben und unten erkennt. Es wird auch nicht beim Klicken ausgelöst, sondern muss mindestens 15 Pixel verschoben werden

/**
 * 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
quelle