JQuery'de "sürüklemeyi" tespit edebiliyor musunuz?


109

Bir kullanıcı bir bağlantıyı tıkladığında görünecek bir zonklayıcım var.

Sorun, aynı bağlantının yeniden düzenlenmek üzere tıklanıp sürüklenebilmesidir. Bu durumda, zonklayıcı görünmesine ihtiyacım olmazdı. Sadece gerçekten bir yere gitmeyi bekliyorsa ortaya çıkması gerekir.

JQuery ile, bir tıklama ve sürükleme yerine yalnızca bir bağlantıya tıklandığında bir zonklayıcı görünmesine izin veren bir olay dinleyicisi nasıl oluşturabilirim ?


Belki OOT? JQuery ile sürükle ve bırak için çeşitli yaklaşımlar denedim, jQuery UI, mousedown ile kendi kodum, mouseup, mousemove olayları ve en iyi çalışan github.com/haberman/jdragdrop .
Rafael Vega

İşte herhangi bir ağır çerçeve içermeyen başka bir basit çözüm. blog.blakesimpson.co.uk/read/…
Kimyasal Programcı

Yanıtlar:


226

Fare altındayken, durumu ayarlamaya başlayın, eğer fare hareketi tetiklenirse kaydedin, son olarak mouseup üzerine farenin hareket edip etmediğini kontrol edin. Eğer hareket ettiyse, sürüklüyoruz demektir. Hareket etmediysek, bu bir klik.

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

İşte bir demo: http://jsfiddle.net/W7tvD/1399/


1
hey..bana yardım eder misin bu stackoverflow.com/questions/19703617/…
HIRA THAKUR

2
Tıklamalarınızın "a" öğesindeki sürüklemeler olarak yorumlanmaması için bir sürükleme eşiği eklemek isteyebilirsiniz. Bir x ve y mousemove olayında belirli miktarda değişiklik arayın.
Ash Blue

Müthiş, rüzgarın bağını çözdükten hemen sonra, sürüklemenin başlangıcı algılanır algılanmaz kodumu koydum. teşekkürler!
Valamas

3
Bazı durumlarda ve / veya tarayıcılarda mousemoveherhangi bir hareket olmaksızın en az bir kez hala ateşleneceğini buldum, bu yüzden hareket halinde değişkeni artırmak için değiştirdim ve ardından mouseup jsfiddle.net/W7tvD/1649 adresinde belirli bir eşiği kontrol ettim. Şimdi benim için bir cazibe gibi çalışıyor, teşekkürler!
2016

27

Nedense yukarıdaki çözümler benim için çalışmıyordu. Aşağıdakilerle gittim:

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

Mesafe sınırını istediğin kadar değiştirebilir, hatta sıfıra kadar alabilirsin.


En iyi cevap, bana çok yardımcı oldu. Sadece bir düşünce: Math.sqrt gerçekten gerekli değil, kare mesafelerle daha iyi çalışmak (sqrt yavaştır, UX'i etkileyebilir).
Bruno Ferreira

1
sqrtyavaş değildir ve yüzlerce kez yapmış olsanız bile UX'i etkilemeyecektir.
NateS

Evet, jquery tıklama işleyiciniz değil, fizik motorunuzun iç döngüsündeki gereksiz karekök hakkında endişelenin ...
PeterT

19

JQuery UI ile sadece bunu yapın!

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

  },
  drag: function() {

  },
  stop: function() {

  }
});

6
Jquery-ui'ye ihtiyacınız var, ancak bu en kolay yol.
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");
});

Bu çözüm, bir mousemove olayını çözme olayını bağlamak için "açık" ve "kapalı" işlevlerini kullanır (bağlama ve çözme kullanımdan kaldırılmıştır). Ayrıca, iki mousemove olayı arasında fare x ve y konumlarındaki değişikliği de algılayabilirsiniz.


3

Şunu deneyin: Ne zaman 'sürüklendiğini' gösterir. ;) keman bağlantısı

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

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

2

Kabul edilen yanıttan ayrıldım ve yalnızca tıklama TUTULDUĞU ve sürüklendiği zaman çalıştırdım .

Fareyi basılı tutmadığım zamanlarda işlevim çalışıyordu. Bu işlevi de istiyorsanız işte güncellenmiş kod:

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

Bunun için en basit yol dokunarak başlatma, dokunma hareket ettirme ve bitişe dokunmaktır. Bu hem PC hem de dokunmatik cihaz için çalışıyor, sadece jquery belgelerinde kontrol edin ve bunun sizin için en iyi çözüm olduğunu umuyoruz. iyi şanslar


1

Simen Echholt'un cevabına dayanan jQuery eklentisi. Tek tıklama olarak adlandırdım.

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

Kullanımda:

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

^^


1

Fareyle çekilen olayları dinlerken yan etkilerin olmaması için öğenin sürüklenebilir özelliğini false olarak ayarladığınızdan emin olun :

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

Ardından jQuery'yi kullanabilirsiniz:

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

Bir zamanlayıcı ayarlamanız gerekiyor. Zamanlayıcı zaman aşımına uğradığında, zonklayıcıyı başlatın ve klik sesini kaydedin. Sürükleme meydana geldiğinde, zamanlayıcıyı hiçbir zaman tamamlamaması için temizleyin.


1
..çok zeki, bir sürüklemeyi nasıl algılarsınız?
Yolculuk

1
Draggable'ı kurduğunuzda, bir onDrag olayı olmalıdır. Oraya bağla.
Diodeus - James MacFarlane

0

JQueryUI kullanıyorsanız - bir onDrag olayı vardır. Değilseniz, dinleyicinizi mouseup () öğesine ekleyin, () öğesine değil.


1
Fare ile, sürükleme ve tıklama arasında nasıl bir ayrım yapılır?
Yolculuk

Hmmm - evet sanırım yeterince düşünmemiştim. Farenin koordinatlarını kaydeden fareye eklenmiş bir dinleyiciniz olabilir. Daha sonra, farenin farenin üstündeki koordinatları aynıysa (veya gerçekten yakınsa), bir tıklama olarak düşünün.
Quasipickle


Cevap da 4 yaşında - bunu bir düşünün.
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

Değişkeni ayarlamanız gerekmez, sadece veri özniteliğinde hareket edip etmediğini ayarlayabilirsiniz.

$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

Her zaman farenin konumunu takip eden ve sol, sağ, üst, alt sürüklemeyi algılayan bir işleve ihtiyacım vardı. Ayrıca tıklamada tetiklemez ancak minimum 15 piksellik hareket gerektirir

/**
 * 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;
});
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.