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?

Perjalanan
sumber
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/

Simen Echholt
sumber
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.

pendatang baru
sumber
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() {

  }
});
GaidenFocus
sumber
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.

jnaklaas
sumber
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();
});
syC
sumber
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);
        }

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

Anup
sumber
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!');
});

^^

ipfaffen.dll
sumber
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;
  });
});
Marcelo Kanzaki
sumber
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.

Diodeus - James MacFarlane
sumber
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 ().

Quasipickle
sumber
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
Ini tidak berfungsi: stackoverflow.com/questions/12231147/…
Chuck Le Butt
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");
});
Joseph
sumber
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
        }
    });
Aiphee
sumber
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;
});
Julesezaar
sumber