Pouvez-vous détecter le «glissement» dans jQuery?

109

J'ai un throbber qui doit apparaître lorsqu'un utilisateur clique sur un lien.

Le problème est que ce même lien peut être cliqué et déplacé pour être réorganisé. Dans ce cas, je n'aurais pas besoin du throbber pour apparaître. Il n'a besoin d'apparaître que s'il attend réellement d'aller quelque part.

Comment puis-je, avec jQuery, créer un écouteur d'événements qui ne permettrait à un throbber d'apparaître que s'il s'agit d'un clic vers un lien , et non d'un clic et d'un glisser?

Voyage
la source
Peut-être OOT? J'ai essayé plusieurs approches pour le glisser-déposer avec jQuery, y compris l'interface utilisateur jQuery, mon propre code avec les événements mousedown, mouseup, mousemove et celui qui a le mieux fonctionné est github.com/haberman/jdragdrop .
Rafael Vega
Voici une autre solution simple sans aucun cadre lourd. blog.blakesimpson.co.uk/read/…
Programmeur chimique

Réponses:

226

Sur mousedown, commencez à définir l'état, si l'événement mousemove est déclenché, enregistrez-le, enfin sur mouseup, vérifiez si la souris a bougé. S'il a bougé, nous avons traîné. Si nous n'avons pas bougé, c'est un clic.

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

Voici une démo: http://jsfiddle.net/W7tvD/1399/

Simen Echholt
la source
1
hey..pouvez-vous m'aider avec ce stackoverflow.com/questions/19703617/…
HIRA THAKUR
2
Vous pouvez ajouter un seuil de glissement afin que vos clics ne soient pas interprétés comme des traînées sur l'élément "a". Recherchez simplement une certaine quantité de changement dans un événement mousemove x et y.
Ash Blue
Génial, juste après que le vent se détache de la souris, j'ai mis mon code à agir dès que le début du glissement a été détecté. Merci!
Valamas
3
J'ai constaté que dans certains cas et / ou navigateurs, mousemovesera toujours déclenché au moins une fois même sans aucun mouvement, alors je l'ai changé pour incrémenter la variable sur le mouvement, puis vérifier un certain seuil sur mouseup jsfiddle.net/W7tvD/1649 Fonctionne comme un charme pour moi maintenant, merci!
halfbit
27

Pour une raison quelconque, les solutions ci-dessus ne fonctionnaient pas pour moi. Je suis allé avec ce qui suit:

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

Vous pouvez ajuster la limite de distance à ce que vous voulez, ou même la ramener à zéro.

nouveau venu
la source
Meilleure réponse, m'a beaucoup aidé. Juste une pensée: Math.sqrt n'est pas vraiment nécessaire, mieux travailler avec des distances carrées (sqrt est lent, pourrait affecter l'UX).
Bruno Ferreira
1
sqrtn'est pas lent et n'affectera pas l'UX, même si vous l'avez fait des centaines de fois.
NateS
Ouais, inquiétez-vous de la racine carrée inutile dans la boucle interne de votre moteur physique, pas de votre gestionnaire de clics jquery ...
PeterT
19

Avec jQuery UI, faites cela!

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

  },
  drag: function() {

  },
  stop: function() {

  }
});
GaidenFocus
la source
6
Vous avez besoin de jquery-ui, mais c'est le moyen le plus simple.
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");
});

Cette solution utilise les fonctions "on" et "off" pour lier un événement de détachement d'un mousemove (la liaison et la dissociation sont obsolètes). Vous pouvez également détecter le changement des positions x et y de la souris entre deux événements mousemove.

jnaklaas
la source
3

Essayez ceci: il montre quand est l'état «glissé». ;) lien violon

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

    $("ul").sortable();
});
syC
la source
2

J'ai bifurqué de la réponse acceptée pour ne courir que lorsque le clic est maintenu vers le bas et traîné .

Ma fonction fonctionnait alors que je ne tenais pas la souris enfoncée. Voici le code mis à jour si vous souhaitez également cette fonctionnalité:

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
la source
1

Pour ce moyen le plus simple, touchez le début, touchez le mouvement et touchez la fin. Cela fonctionne à la fois pour le PC et le périphérique tactile, il suffit de le vérifier dans la documentation jquery et j'espère que c'est la meilleure solution pour vous. bonne chance

Anup
la source
1

Plugin jQuery basé sur la réponse de Simen Echholt. Je l'ai appelé un seul clic.

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

Utilisé:

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

^^

ipfaffen
la source
1

Assurez-vous de définir l' attribut déplaçable de l'élément sur false afin de ne pas avoir d'effets secondaires lors de l'écoute des événements mouseup:

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

Ensuite, vous pouvez utiliser 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
la source
0

Vous devez régler une minuterie. Lorsque la minuterie expire, démarrez le throbber et enregistrez le clic. Lorsqu'un glissement se produit, effacez le minuteur pour qu'il ne se termine jamais.

Diodeus - James MacFarlane
la source
1
..très intelligent, comment détectez-vous une traînée?
Voyage du
1
lorsque vous configurez le Draggable, il devrait y avoir un événement onDrag. Accrochez-le là-haut.
Diodeus - James MacFarlane
0

Si vous utilisez jQueryUI, il existe un événement onDrag. Si ce n'est pas le cas, attachez votre auditeur à mouseup (), et non à cliquer ().

Quasipickle
la source
1
Comment mouseup différencie-t-il un glissement et un clic?
Voyage du
Hmmm - ouais je suppose que je n'y ai pas suffisamment réfléchi. Peut-être pouvez-vous avoir un écouteur attaché à mousedown qui enregistre les coordonnées de la souris. Ensuite, si les coordonnées de la souris sur la souris sont identiques (ou vraiment proches), considérez-le comme un clic.
Quasipickle
Cela ne fonctionne pas: stackoverflow.com/questions/12231147/…
Chuck Le Butt
La réponse a également 4 ans - considérez cela.
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
la source
0

Vous n'avez pas à configurer la variable, vous pouvez simplement définir si elle se déplace dans l'attribut de données

$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
la source
0

J'avais besoin d'une fonction qui garde toujours la trace de la position de la souris et détecte le glissement vers la gauche, la droite, le haut et le bas. Il ne se déclenche pas non plus au clic mais nécessite un déplacement minimum de 15 pixels

/**
 * 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
la source