คุณสามารถตรวจจับ "การลาก" ใน jQuery ได้หรือไม่?


109

ฉันมีอาการสั่นที่จะปรากฏขึ้นเมื่อผู้ใช้คลิกลิงก์

ปัญหาคือลิงก์เดียวกันนั้นสามารถคลิกและลากเพื่อจัดเรียงใหม่ได้ ในกรณีนี้ฉันไม่ต้องการให้นักสั่นปรากฏตัว มันจะต้องปรากฏขึ้นถ้ามันกำลังรอไปที่ไหนสักแห่งจริงๆ

ฉันจะใช้ jQuery สร้างตัวฟังเหตุการณ์ที่จะอนุญาตให้ตัวสั่นเท่านั้นปรากฏขึ้นได้อย่างไรหากมีการคลิกผ่านไปยังลิงก์ไม่ใช่การคลิกและลาก


บางที OOT? ฉันได้พยายามหลายวิธีสำหรับการลากและวางกับ jQuery incluing jQuery UI รหัสของตัวเองกับ mousedown, mouseup เหตุการณ์ mousemove และเป็นคนที่มีการทำงานที่ดีที่สุดคือgithub.com/haberman/jdragdrop
Rafael Vega

นี่เป็นอีกวิธีง่ายๆที่ไม่มีกรอบงานหนัก ๆ blog.blakesimpson.co.uk/read/…
Chemical Programmer

คำตอบ:


227

ในการวางเมาส์ให้เริ่มตั้งค่าสถานะหากเหตุการณ์ mousemove ถูกยิงบันทึกในที่สุดเมื่อวางเมาส์ให้ตรวจสอบว่าเมาส์ขยับหรือไม่ ถ้ามันย้ายเราก็ลากไปแล้ว ถ้าเราไม่ย้ายก็คลิก

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

นี่คือการสาธิต: http://jsfiddle.net/W7tvD/1399/


1
เฮ้.. ช่วยฉันด้วย stackoverflow.com/questions/19703617/…
HIRA THAKUR

2
คุณอาจต้องการเพิ่มเกณฑ์การลากเพื่อไม่ให้การคลิกของคุณถูกตีความว่าเป็นการลากองค์ประกอบ "a" เพียงแค่มองหาการเปลี่ยนแปลงจำนวนหนึ่งในเหตุการณ์ x และ y mousemove
Ash Blue

สุดยอดทันทีหลังจากลมคลายการพันมูสฉันใส่รหัสให้ดำเนินการทันทีที่ตรวจพบการเริ่มลาก ขอบคุณ!
Valamas

3
ฉันพบว่าในบางกรณีและ / หรือเบราว์เซอร์mousemoveจะยังคงถูกยิงอย่างน้อยหนึ่งครั้งแม้ว่าจะไม่มีการเคลื่อนไหวใด ๆ ก็ตามดังนั้นฉันจึงเปลี่ยนเป็นเพิ่มตัวแปรตามการเคลื่อนไหวจากนั้นตรวจสอบเกณฑ์ที่แน่นอนในmouseup jsfiddle.net/W7tvD/1649 ใช้งานได้เหมือนมีเสน่ห์สำหรับฉันตอนนี้ขอบคุณ!
halfbit

27

ด้วยเหตุผลบางประการวิธีแก้ปัญหาข้างต้นไม่ได้ผลสำหรับฉัน ฉันไปกับสิ่งต่อไปนี้:

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

คุณสามารถปรับแต่งขีด จำกัด ระยะทางเป็นสิ่งที่คุณต้องการหรือแม้กระทั่งนำมันไปที่ศูนย์


คำตอบที่ดีที่สุดช่วยฉันได้มาก แค่คิด: Math.sqrt ไม่จำเป็นจริงๆทำงานได้ดีกว่ากับระยะทางกำลังสอง (sqrt ช้าอาจส่งผลต่อ UX)
Bruno Ferreira

1
sqrtไม่ช้าและจะไม่ส่งผลกระทบต่อ UX แม้ว่าคุณจะทำหลายร้อยครั้งก็ตาม
NateS

ใช่กังวลเกี่ยวกับรากที่สองที่ไม่จำเป็นในวงในของเครื่องมือฟิสิกส์ของคุณไม่ใช่ตัวจัดการคลิก jquery ของคุณ ...
PeterT


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");
});

โซลูชันนี้ใช้ฟังก์ชัน "เปิด" และ "ปิด" เพื่อเชื่อมโยงเหตุการณ์การคลายการเชื่อมโยงของมูสมูฟ (การเชื่อมและเลิกผูกจะเลิกใช้) คุณยังสามารถตรวจจับการเปลี่ยนแปลงของตำแหน่ง x และ y ของเมาส์ระหว่างสองเหตุการณ์ของมูสมูฟได้


3

ลองสิ่งนี้: มันจะแสดงสถานะเมื่อถูก 'ลาก' ;) ลิงค์ซอ

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

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

2

ฉันแยกออกจากคำตอบที่ยอมรับเพื่อให้ทำงานเมื่อคลิกถูก HELD และลากลงเท่านั้น

ฟังก์ชันของฉันกำลังทำงานเมื่อฉันไม่ได้กดเมาส์ค้างไว้ นี่คือรหัสที่อัปเดตหากคุณต้องการฟังก์ชันนี้:

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

สำหรับวิธีที่ง่ายที่สุดคือการเริ่มต้นด้วยการสัมผัสแตะย้ายและปลายสัมผัส ใช้งานได้กับทั้งพีซีและอุปกรณ์สัมผัสเพียงตรวจสอบในเอกสาร jquery และหวังว่านี่จะเป็นทางออกที่ดีที่สุดสำหรับคุณ โชคดี


1

ปลั๊กอิน jQuery ตามคำตอบของ Simen Echholt เรียกว่าคลิกเพียงครั้งเดียว

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

ใช้งานอยู่:

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

^^


1

ตรวจสอบให้แน่ใจว่าคุณตั้งค่าแอตทริบิวต์ที่ลากได้ขององค์ประกอบเป็นเท็จเพื่อให้คุณไม่มีผลข้างเคียงเมื่อฟังเหตุการณ์การวางเมาส์:

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

จากนั้นคุณสามารถใช้ 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

คุณต้องตั้งเวลา เมื่อหมดเวลาให้เริ่มการสั่นและลงทะเบียนคลิก เมื่อเกิดการลากให้ล้างตัวจับเวลาไม่ให้เสร็จสิ้น


1
.. ฉลาดมากคุณจะตรวจจับการลากได้อย่างไร?
ทริป

1
เมื่อคุณตั้งค่า Draggable ควรมีเหตุการณ์ onDrag เกี่ยวขึ้นที่นั่น
Diodeus - James MacFarlane

0

หากคุณใช้ jQueryUI - มีเหตุการณ์ onDrag หากคุณไม่ใช่ให้แนบ Listener ของคุณเข้ากับ mouseup () ไม่ใช่คลิก ()


1
เมาส์อัพจะแยกความแตกต่างระหว่างการลากและคลิกอย่างไร
ทริป

อืม - ใช่ฉันคิดว่าฉันไม่ได้คิดผ่านมากพอ บางทีคุณอาจมีตัวฟังหนึ่งตัวติดอยู่กับมูสดาวน์ที่บันทึกพิกัดของเมาส์ จากนั้นหากพิกัดของเมาส์บน mouseup เหมือนกัน (หรือใกล้เคียงกันจริงๆ) ให้พิจารณาคลิกผ่าน
Quasipickle

สิ่งนี้ใช้ไม่ได้: stackoverflow.com/questions/12231147/…
Chuck Le Butt

คำตอบก็คือ 4 ปีเช่นกัน - ลองพิจารณาดู
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

คุณไม่จำเป็นต้องตั้งค่าตัวแปรคุณสามารถตั้งค่าได้ว่าจะย้ายใน data-attribute หรือไม่

$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

ฉันต้องการฟังก์ชั่นที่ติดตามตำแหน่งของเมาส์และตรวจจับการลากไปทางซ้าย, ขวา, บน, ล่าง นอกจากนี้ยังไม่ทำให้เกิดการคลิก แต่ต้องการการเคลื่อนไหวขั้นต่ำ 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;
});
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.