Bạn có thể phát hiện "kéo" trong jQuery không?


109

Tôi có một điều khiển xuất hiện khi người dùng nhấp vào một liên kết.

Vấn đề là liên kết đó có thể được nhấp và kéo để được sắp xếp lại. Trong trường hợp này, tôi sẽ không cần bộ điều chỉnh xuất hiện. Nó chỉ cần xuất hiện nếu nó thực sự đang chờ đến một nơi nào đó.

Với jQuery, làm cách nào để tôi có thể tạo một trình xử lý sự kiện chỉ cho phép một điều khiển xuất hiện nếu nó nhấp qua một liên kết chứ không phải nhấp và kéo?


Có lẽ OOT? Tôi đã thử một số cách tiếp cận để kéo và thả với jQuery bao gồm giao diện người dùng jQuery, mã của riêng tôi với các sự kiện mousedown, mouseup, mousemove và cách hoạt động tốt nhất là github.com/haberman/jdragdrop .
Rafael Vega

Đây là một giải pháp đơn giản khác mà không cần bất kỳ khuôn khổ nặng nào. blog.blakesimpson.co.uk/read/…
Lập trình viên hóa học

Câu trả lời:


224

Khi mousedown, bắt đầu thiết lập trạng thái, nếu sự kiện mousemove được kích hoạt, hãy ghi lại nó, cuối cùng khi mouseup, hãy kiểm tra xem con chuột có di chuyển hay không. Nếu nó di chuyển, chúng tôi đã kéo. Nếu chúng tôi chưa di chuyển, đó là một cú nhấp chuột.

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

Đây là bản demo: http://jsfiddle.net/W7tvD/1399/


1
này..bạn có thể giúp tôi với stackoverflow.com/questions/19703617/…
HIRA THAKUR

2
Bạn có thể muốn thêm ngưỡng kéo để các lần nhấp của bạn không được hiểu là các lần kéo trên phần tử "a". Chỉ cần tìm một lượng thay đổi nhất định trong sự kiện di chuyển chuột x và y.
Ash Blue

Tuyệt vời, ngay sau khi di chuyển chuột, tôi đã đặt mã của mình để hoạt động ngay khi bắt đầu kéo được phát hiện. cảm ơn bạn!
Valamas

3
Tôi nhận thấy rằng trong một số trường hợp và / hoặc trình duyệt, mousemovesẽ vẫn được kích hoạt ít nhất một lần ngay cả khi không có bất kỳ chuyển động nào, vì vậy tôi đã thay đổi nó để tăng biến số khi di chuyển và sau đó kiểm tra một ngưỡng nhất định trên mouseup jsfiddle.net/W7tvD/1649 Hoạt động như một sự quyến rũ đối với tôi bây giờ, cảm ơn!
Halfbit

27

Vì một số lý do, các giải pháp trên không hiệu quả với tôi. Tôi đã đi với những điều sau:

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

Bạn có thể điều chỉnh giới hạn khoảng cách thành bất cứ thứ gì bạn muốn, hoặc thậm chí đưa nó về 0.


Câu trả lời hay nhất, đã giúp tôi rất nhiều. Chỉ cần một suy nghĩ: Math.sqrt không thực sự cần thiết, làm việc tốt hơn với khoảng cách hình vuông (sqrt chậm, có thể ảnh hưởng đến UX).
Bruno Ferreira

1
sqrtkhông chậm và sẽ không ảnh hưởng đến UX, ngay cả khi bạn đã làm điều đó hàng trăm lần.
NateS

Yeah, lo lắng về căn bậc hai không cần thiết trong vòng lặp bên trong của động cơ của bạn vật lý, không nhấp chuột handler jquery của bạn ...
PeterT

19

Với jQuery UI chỉ cần làm điều này!

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

  },
  drag: function() {

  },
  stop: function() {

  }
});

6
Bạn cần jquery-ui, nhưng đó là cách dễ nhất.
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");
});

Giải pháp này sử dụng các hàm "bật" và "tắt" để liên kết một sự kiện di chuyển chuột (liên kết và hủy liên kết không được dùng nữa). Bạn cũng có thể phát hiện sự thay đổi vị trí x và y của chuột giữa hai sự kiện di chuyển chuột.


3

Hãy thử điều này: nó hiển thị trạng thái 'kéo' khi nào. ;) liên kết fiddle

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

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

2

Tôi đã phân nhánh từ câu trả lời được chấp nhận để chỉ chạy khi nhấp chuột được HELD xuống và kéo .

Chức năng của tôi đang chạy khi tôi không giữ chuột. Đây là mã được cập nhật nếu bạn cũng muốn có chức năng này:

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

Đối với cách đơn giản nhất này là chạm bắt đầu, chạm di chuyển và chạm kết thúc. Điều đó đang hoạt động cho cả PC và thiết bị cảm ứng, chỉ cần kiểm tra nó trong tài liệu jquery và hy vọng đây là giải pháp tốt nhất cho bạn. chúc may mắn


1

jQuery plugin dựa trên câu trả lời của Simen Echholt. Tôi gọi nó là một cú nhấp chuột.

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

Đang sử dụng:

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

^^


1

Đảm bảo bạn đặt thuộc tính có thể kéo của phần tử thành false để bạn không gặp phải tác dụng phụ khi nghe các sự kiện di chuột lên:

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

Sau đó, bạn có thể sử dụng 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

Bạn cần phải hẹn giờ. Khi bộ đếm thời gian hết thời gian, hãy bắt đầu điều chỉnh và đăng ký lần nhấp. Khi kéo xảy ra, hãy xóa bộ hẹn giờ để nó không bao giờ hoàn thành.


1
.. rất thông minh, làm thế nào để bạn phát hiện một lực cản?
Chuyến đi

1
khi bạn thiết lập Draggable, sẽ có một sự kiện onDrag. Móc nó lên đó.
Diodeus - James MacFarlane

0

Nếu bạn đang sử dụng jQueryUI - có một sự kiện onDrag. Nếu không, hãy đính kèm trình nghe của bạn vào mouseup (), không phải nhấp vào ().


1
Cách di chuột lên phân biệt giữa kéo và nhấp?
Chuyến đi

Hmmm - vâng, tôi đoán là tôi đã không suy nghĩ kỹ. Có lẽ bạn có thể có một người nghe gắn liền với mousedown ghi lại tọa độ của chuột. Sau đó, nếu tọa độ của chuột khi di chuột lên giống nhau (hoặc thực sự gần), hãy coi đó là một lần nhấp chuột.
Quasipickle

Điều này không làm việc: stackoverflow.com/questions/12231147/...
Chuck Lê Butt

Câu trả lời cũng là 4 năm tuổi - hãy cân nhắc điều đó.
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

Bạn không cần phải thiết lập biến, bạn chỉ có thể đặt nếu nó đang di chuyển trong data-thuộc tính

$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

Tôi cần một chức năng luôn theo dõi vị trí chuột và phát hiện kéo sang trái, phải-, trên-, dưới-. Nó cũng không kích hoạt khi nhấp chuột nhưng cần di chuyển tối thiểu 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;
});
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.