Bisakah Anda mendeteksi "menyeret" di jQuery?


109

Saya memiliki denyut yang muncul saat pengguna mengklik link.

Masalahnya adalah bahwa tautan yang sama dapat diklik dan diseret untuk diatur ulang. Dalam hal ini, saya tidak perlu detak jantung muncul. Itu hanya perlu muncul jika benar-benar menunggu untuk pergi ke suatu tempat.

Bagaimana saya bisa, dengan jQuery, membuat event listener yang hanya akan memungkinkan berdenyut untuk muncul jika itu adalah klik ke tautan , dan bukan klik dan seret?


Mungkin OOT? Saya telah mencoba beberapa pendekatan untuk drag and drop dengan jQuery incluing jQuery UI, kode saya sendiri dengan mousedown, mouseup, event mousemove dan yang paling berhasil adalah github.com/haberman/jdragdrop .
Rafael Vega

Berikut solusi sederhana lainnya tanpa kerangka kerja yang berat. blog.blakesimpson.co.uk/read/…
Programmer Kimia

Jawaban:


225

Di mousedown, mulai setel status, jika peristiwa mousemove dipecat, rekam, akhirnya di mouseup, periksa apakah mouse bergerak. Jika pindah, kita sudah menyeret. Kalau kita belum pindah, itu klik.

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

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


1
hey..dapatkah Anda membantu saya dengan stackoverflow.com/questions/19703617/…
HIRA THAKUR

2
Anda mungkin ingin menambahkan ambang seret agar klik Anda tidak diartikan sebagai seret pada elemen "a". Cari saja sejumlah perubahan dalam acara x dan y mousemove.
Ash Blue

Luar biasa, tepat setelah angin melepaskan mousemove saya meletakkan kode saya untuk bertindak segera setelah awal menyeret terdeteksi. terimakasih!
Valamas

3
Saya telah menemukan bahwa dalam beberapa kasus dan / atau browser, mousemovemasih akan diaktifkan setidaknya sekali bahkan tanpa gerakan apa pun, jadi saya mengubahnya menjadi menaikkan variabel pada gerakan dan kemudian memeriksa ambang tertentu di mouseup jsfiddle.net/W7tvD/1649 Bekerja seperti pesona bagi saya sekarang, terima kasih!
halfbit

27

Untuk beberapa alasan, solusi di atas tidak berfungsi untuk saya. Saya pergi dengan yang berikut:

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

Anda dapat menyesuaikan batas jarak menjadi apa pun yang Anda inginkan, atau bahkan membawanya ke nol.


Jawaban terbaik, banyak membantu saya. Sekadar pemikiran: Math.sqrt tidak terlalu diperlukan, lebih baik bekerja dengan jarak kuadrat (sqrt lambat, dapat mempengaruhi UX).
Bruno Ferreira

1
sqrttidak lambat dan tidak akan memengaruhi UX, meskipun Anda melakukannya ratusan kali.
NateS

Ya, khawatir tentang akar kuadrat yang tidak perlu di loop dalam mesin fisika Anda, bukan pengendali klik jquery Anda ...
PeterT

19

Dengan jQuery UI lakukan ini!

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

  },
  drag: function() {

  },
  stop: function() {

  }
});

6
Anda membutuhkan jquery-ui, tapi ini cara termudah.
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");
});

Solusi ini menggunakan fungsi "on" dan "off" untuk mengikat peristiwa mousemove yang dilepaskan (bind dan unbind tidak berlaku lagi). Anda juga dapat mendeteksi perubahan posisi x dan y mouse antara dua peristiwa gerakan mouse.


3

Coba ini: ini menunjukkan kapan status 'diseret'. ;) link biola

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

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

2

Saya bercabang dari jawaban yang diterima untuk hanya berjalan ketika klik sedang DIBANTU dan diseret .

Fungsi saya berjalan saat saya tidak menahan mouse. Berikut kode yang diperbarui jika Anda juga menginginkan fungsi ini:

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

Untuk cara termudah ini adalah sentuhan mulai, gerakan sentuh, dan ujung sentuh. Itu berfungsi untuk PC dan perangkat sentuh, cukup periksa di dokumentasi jquery dan harap ini adalah solusi terbaik untuk Anda. semoga berhasil


1

Plugin jQuery berdasarkan jawaban Simen Echholt. Saya menyebutnya satu klik.

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

Digunakan:

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

^^


1

Pastikan Anda menyetel atribut elemen yang dapat diseret ke false sehingga Anda tidak memiliki efek samping saat mendengarkan peristiwa mouseup:

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

Kemudian, Anda dapat menggunakan 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

Anda perlu menyetel pengatur waktu. Saat penghitung waktu habis, nyalakan denyut dan daftarkan kliknya. Saat seret terjadi, hapus pengatur waktu agar tidak pernah selesai.


1
.. sangat pintar, bagaimana Anda mendeteksi hambatan?
Perjalanan

1
saat Anda menyiapkan Draggable, seharusnya ada acara onDrag. Hubungkan di sana.
Diodeus - James MacFarlane

0

Jika Anda menggunakan jQueryUI - ada acara onDrag. Jika tidak, maka lampirkan listener Anda ke mouseup (), bukan click ().


1
Bagaimana mouseup membedakan antara seret dan klik?
Perjalanan

Hmmm - ya saya rasa saya tidak cukup memikirkannya. Mungkin Anda dapat memiliki satu pendengar yang terpasang ke mousedown yang mencatat koordinat mouse. Kemudian jika koordinat mouse pada mouseup sama (atau sangat dekat), anggap sebagai klik-tayang.
Quasipickle


Jawabannya juga 4 tahun - pertimbangkan itu.
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

Anda tidak perlu menyiapkan variabel, Anda dapat menyetelnya jika variabel tersebut bergerak di atribut 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

Saya membutuhkan fungsi yang selalu melacak posisi mouse dan mendeteksi penarikan ke kiri, kanan, atas, bawah. Itu juga tidak memicu saat klik tetapi membutuhkan minimal pergerakan 15px

/**
 * 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;
});
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.