为什么Chrome在拖动时会将光标设置为文本?

60

我的应用程序有许多拖放功能。在拖动时,我希望光标改变为某种抓取光标。Internet Explorer和Firefox可以正常工作,但Chrome始终将光标更改为文本光标。


2
问题描述得足够清楚。在拖动时,即使在被拖动的元素上设置了自定义光标,Chrome也会将光标覆盖为文本选择光标。JSFiddle很好,但不需要代码来解释问题。 - devios1
8个回答

76

这些解决方案对我都没用,因为它们的代码太多了。

我使用了一个自定义的jQuery实现来进行拖动,在mousedown处理程序中添加这行代码可以让Chrome浏览器正常工作。

e.originalEvent.preventDefault();

1
+10 我喜欢这个解决方案的简洁性和它的良好运作。比起附加和分离鼠标或选择事件要好得多。 - Chris Nolet
2
@ChrisNolet 嗯,公平地说,这与我的解决方案完全相同。我只是添加了一个如何附加事件处理程序的示例。Tim正在使用jQuery进行操作,但在他的代码中没有记录,因此看起来更短。您仍然需要在某个地方附加 mousedown 事件才能使其正常工作。 - Lorenzo Polidori
@Lorenzo。看了一下SO的Web编程话题,我有80%的印象是人们在使用jQuery。 - tim
3
当我在mousedown事件处理程序中添加preventDefault()时,元素不能再被拖动。有什么解决办法吗? - lyxio
1
@lyxio 如果你没有使用jQuery,这个方法将不起作用。jQuery有自己的事件,但是这个解决方案将prevent default附加到原始的JavaScript事件上,使得jquery onmousedown仍然可以触发拖动。 - tim

23

尝试关闭文本选择事件。

document.onselectstart = function(){ return false; }

这将禁用页面上的所有文本选择,而且浏览器似乎开始显示自定义光标。

但请记住,文本选择将完全无法使用,因此最好只在拖动时这样做,并在此之后立即重新启用它。只需附加不返回false的函数即可:

document.onselectstart = function(){ return true; }

1
嘿,老兄谢了你的回复,但是我也尝试过这个方法。可惜对我没用。:( - user307635
5
我不明白为什么这个答案会被投票赞同那么多次。这不是正确的方法。你需要精细地选择要应用此行为的元素,然后阻止mousedown事件的默认操作。请参见此处链接:https://dev59.com/P3E85IYBdhLWcg3wgDvd#12957678 - Lorenzo Polidori
1
远不及 @tim 的解决方案简单 - 即使是 Lorenzo 的解决方案也有点复杂。只需像 tim 建议的那样在 mouseDown 中放置 e.originalEvent.preventDefault(); - Chris Nolet
2
-1因为这是不必要的,影响范围太大,而且无效。 - devios1
@LorenzoPolidori的评论应该成为这里的顶部答案,因为它在我的情况下起作用了(在OS X 10.11.5上的Safari 9.1.1中),而许多其他建议没有起作用。 - bluebinary
显示剩余2条评论

18

如果你想防止浏览器选中元素内的文本并显示选择光标,你可以采取以下措施:

element.addEventListener("mousedown", function(e) { e.preventDefault(); }, false);

+1 很少有人认识到你的答案与我的完全相同,只是你的答案不依赖于插件。由于许多人在编写 Web 应用程序时使用 jQuery,即使问题很普遍,我通常也会假设使用 jQuery。 - tim
@JosephLennox 如果有人因为某些原因仍需要支持IE8:http://www.w3schools.com/browsers/browsers_explorer.asp - Lorenzo Polidori
@LorenzoPolidori 我完全同意一般网站不应该针对IE8提供支持。不幸的是,在一些办公室中,可能也签发你薪水的地方,IE8的使用率达到了100%。 - Joseph Lennox
在2022年,React拯救了我的生命。 - Fer Toasted

8

陷阱

您不能放置

document.onselectstart = function(){ return false; };

因为onselectstart事件已经被触发,所以需要在"mousedown"处理程序中添加此代码,才能使它起作用。

解决方案

因此,为了使它正常工作,您需要在mousedown事件之前执行此操作。我在mouseover事件中执行此操作,因为一旦鼠标进入我的元素,我希望它可以被拖动,而不是可选择的。然后你可以将

document.onselectstart = null;

在调用mouseout事件时需要注意一个问题。当拖动时,可能会触发mouseover/mouseout事件。为了解决这个问题,在拖动/mousedown事件中,设置一个名为flag_dragging的标志,并在拖动停止(mouseup)时将其设置为false。在执行mouseout函数之前,可以检查该标志。

document.onselectstart = null;

示例

我知道您没有使用任何库,但这里有一个jQuery代码示例,可能对其他人有帮助。

var flag_dragging = false;//counter Chrome dragging/text selection issue
$(".dragme").mouseover(function(){
    document.onselectstart = function(){ return false; };
}).mouseout(function(){
    if(!flag_dragging){
        document.onselectstart = null;
    }
});

//make them draggable
$(".dragme").draggable({
    start: function(event, ui){
        flag_dragging = true;
    }, stop: function(event, ui){
        flag_dragging = false;
    }
});

1
谢谢。对于我的需求,mouseentermouseleave正是我想要的,因为在拖动元素时会不断触发mouseover - jberryman

6

我通过使元素不可选,并在拖动的元素上添加一个活动伪类来解决了同样的问题:

* {
    -webkit-user-select: none; 
}

.your-class:active {
    cursor: crosshair;
}

这个很好用,你可以添加类似于 input { -webkit-user-select: auto; } 的代码,让用户在输入框中选择文本。 - Laurence
为了得到一个完整的答案: 你需要添加e.preventDefault(),因为在WebKit中拖动的默认操作是选择。 - shex
这对我解决了问题,其中e.originalEvent.preventDefault();没有起作用。 - Ed Fryed

4

我面临了几乎相同的问题。我希望光标在我的DIV元素及其所有子元素内时都是默认的,这里的CSS技巧对IE、FF和Opera有帮助,但对Google Chrome无效。这是我在父DIV中所做的:

<div ... onselectstart="return false;" ... > ... </div>

现在它正常工作了。希望这能帮到你。


2
我发现您可能正在使用相同的jQuery UI库,遇到了与我类似的问题。然而问题是由于jQuery UI中的一个错误(实际上是为其他Safari错误修复而添加的)引起的。我在jQuery UI上提出了这个问题,链接为http://dev.jqueryui.com/ticket/5678。因此,我认为您需要等待直到它被修复。
我找到了一个解决方法,但它比较高级,所以只有当您真正知道发生了什么时才能使用它。请注意保留HTML标签。
if ($.browser.safari) {
    $.ui.mouse.prototype.__mouseDown = $.ui.mouse.prototype._mouseDown;
    $.ui.mouse.prototype._mouseDown = function(event){
        event.preventDefault();
        return $.ui.mouse.prototype.__mouseDown.apply(this, arguments);
    }
}

它只是关闭了jQuery UI代码中的修复程序,因此基本上可能会破坏某些内容。


嗨,谢谢你的回复,但是我没有使用任何JavaScript库。所以它不能帮助我 :( - user307635

2

在你的mousedown事件内使用这行代码

arguments[0].preventDefault();

您可以通过将此类添加到可拖动元素中,使用CSS禁用文本选择:

您可以通过将此类添加到可拖动元素中,使用CSS禁用文本选择

.nonselectable {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

谢谢,这个很好用!arguments[0].preventDefault(); 已经足够了。 - A1rPun

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