如何让鼠标移动结束后,mouseup事件只触发一次

18

看起来只有在不与 mousemove 事件一起使用时,才会触发 mouseup 事件。换句话说,按下鼠标左键并释放,mouseup 事件会被触发。但是如果您拖动图像然后松开,就不会触发 mouseup 事件。以下是显示此行为的示例:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<div id="Out">
    <img id="Img" src="http://sstatic.net/so/img/logo.png" width=500>
</div>
<script language=JavaScript>
    $(function() {
        $(document).bind("mouseup",function() {alert("UP");});
        //$("#Out").bind("mouseup",function() {alert("UP");});
        //$("#Img").bind("mouseup",function() {alert("UP");});
    });
</script>
如果你加载这个程序,然后点击并松开,会弹出“UP”警报。但是,如果你拖动了一下然后松开,就不会触发UP警报。 如何在mousemove完成后触发mouseup事件,或者如何检查mousemove事件以确定左鼠标按钮现在已关闭?
7个回答

25

这是我经常使用的一种模式,对所有与mousemove相关的事情通常都很有效。当用户点击mousedown时,mouseup事件被绑定,这将强制在用户释放鼠标按钮时触发它,无论它移动了多少。

$('#element').mousedown(function(e) {

    // You can record the starting position with
    var start_x = e.pageX;
    var start_y = e.pageY;

    $().mousemove(function(e) {
        // And you can get the distance moved by
        var offset_x = e.pageX - start_x;
        var offset_y = e.pageY - start_y;

        return false;
    });

    $().one('mouseup', function() {
        alert("This will show after mousemove and mouse released.");
        $().unbind();
    });

    // Using return false prevents browser's default,
    // often unwanted mousemove actions (drag & drop)
    return false;
});

2
不错。它可以工作,但只能一次。我进行了快速更改,并使其在整个页面上无限运行。http://jsbin.com/ajidi 从那里开始,可能可以做得更好,但我认为这是一个相当酷的解决方案。 - Jeff Rupert
这在孤立状态下看起来不错,希望我能将其集成到真正的项目中,然后我会将其作为答案进行检查。 - jwl
你肯定不想取消mousedown事件,因为它有许多副作用。很可能你只是想同时监听mouseup和dragend事件,并将它们都视为mouseup。 - Glenn Maynard
2
这个工作很棒。我无法让$()正常工作,所以我用$('body')代替了它。唯一的小问题是,如果你拖到屏幕外面,用户必须再次点击 - 在这种情况下,您可以在mousemove中检查e.which并在那里结束拖动。 - xtravar
简明有效。如果你只想在鼠标释放时调用一个函数,甚至可以进一步简化。$('#element').mousedown(function () { $(document).one('mouseup', mouseReleased); return false; }); - Jason L.

5

不要忘记给你的事件命名空间,否则所有的事件处理程序都将被取消绑定:

$('#element').bind('mousedown.namespace', function(e) {
    $(document).one('mouseup', function() {
        callback_func();
        $(document).unbind('mousedown.namespace');
    });
 });

我真的需要感谢你!我很长一段时间都完全迷失和茫然,不知道为什么鼠标弹起事件没有触发...这个评论让光明重回生活! - J. Bruni
很棒的解决方案。我尝试了许多其他交叉元素mousedown-mouseup情况的替代方案,但都没有成功。将click添加到one的事件中完成了我所需的实现,适用于用户不将鼠标拖动到绑定元素之外的情况。 - berbt

1
从JQuery 1.4开始,您需要将$()替换为$('document')。实际上,我正在使用它来在JQuery UI对话框内创建菜单,这似乎会捕获mousemove事件。因此,我只需将我的容器div替换为$()(类似于$('#myContainerDiv')),这也可以正常工作。

1
我遇到了类似的问题,这个方法对我起了作用:

$(document).on("dragend", function(e){
  $(e.target).trigger("mouseup");
  e.preventDefault();
});

0

我遇到了相同的问题。即使我在mousedown处理程序中添加了e.preventDefault(),问题仍未解决。

最后,我发现如果我关闭mousemove处理程序中的以下代码,则我的mouseup处理程序就会正常被调用。

     mouseDragArea.css({
         top: dragAreaPos.y + 'px',
         left: dragAreaPos.x + 'px',
         width: Math.abs(mouseCurPos.x - mouseClickPos.x) + 'px',
         height: Math.abs( mouseCurPos.y - mouseClickPos.y ) + 'px'
     });

mouseDragArea 是一个通过编程创建的元素,它具有虚线边框来显示鼠标拖动的矩形区域:

    mouseDragArea = $('<div id="mouse-drag-area"></div>');

然后,我意识到这个#mouse-drag-area元素在处理mouseup事件的原始元素之上。因此,在将以下CSS声明添加到#mouse-drag-area之后,它就被排序了:

    pointer-events:none;

换句话说,关键在于你为哪个元素设置了鼠标抬起处理程序。

0
我发现当我使用下面的CSS将文本设置为不可选择时,mouseup事件也会被抑制 - 或许这对其他人有所帮助。
-moz-user-select: none;
-khtml-user-select: none;
user-select: none;

0

我曾遇到过 KineticJS 对象的类似问题。使用 Kinetic 的 dragend 而不是 mouseup 解决了这个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接