使用 JavaScript 全局覆盖鼠标光标
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10750582/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Global override of mouse cursor with JavaScript
提问by n.dee
In my web application I try to implement some drag and drop functionality. I have a global JavaScript component which does the the basic stuff. This object is also responsible for changing the mouse cursor, depending of the current drag operation (move, copy, link). On my web page there are various HTML elements which define an own cursor style, either inline or via a CSS file.
在我的 Web 应用程序中,我尝试实现一些拖放功能。我有一个全局 JavaScript 组件来完成基本的工作。该对象还负责根据当前的拖动操作(移动、复制、链接)更改鼠标光标。在我的网页上有各种 HTML 元素,它们定义了自己的光标样式,内联或通过 CSS 文件。
So, is there a way for my central drag and drop component to change the mouse cursor globally, independent from the style of the element the mouse cursor is over?
那么,有没有办法让我的中央拖放组件全局更改鼠标光标,而与鼠标光标所在元素的样式无关?
I tried:
我试过:
document.body.style.cursor = "move"
and
和
document.body.style.cursor = "move !important"
But it doesn't work. Everytime I drag over an element wich defines a cursor style, the cursor changes to that style.
但它不起作用。每次我拖过一个定义光标样式的元素时,光标都会更改为该样式。
Sure, I could change the style of the element I'm currently dragging over, but then I have to reset it when I leavy the element. This seems a little bit to complicated. I'm looking for a global solution.
当然,我可以更改我当前正在拖动的元素的样式,但是当我离开元素时我必须重置它。这似乎有点复杂。我正在寻找全球解决方案。
回答by Samuel Rossille
Please: don't massacre your CSS!
请:不要屠杀你的 CSS!
To implement a drag and drop functionality, you have to use a very important API: element.setCapture(). This has this consequences:
要实现拖放功能,您必须使用一个非常重要的 API:element.setCapture()。这有以下后果:
- All mouse events are redirected to the target element of the capture, regardless of where they occured (even outside the browser window)
- The cursor will be the cursor of the target element of the capture, regardless where the mouse pointer is.
- 所有鼠标事件都被重定向到捕获的目标元素,无论它们发生在哪里(甚至在浏览器窗口之外)
- 光标将是捕获目标元素的光标,无论鼠标指针在哪里。
You have to call element.releaseCapture()or document.releaseCapture()to switch back to normal mode at the end of the operation.
您必须调用element.releaseCapture()或document.releaseCapture()在操作结束时切换回正常模式。
Beware of a na?ve implementation of drag and drop:you can have a lot of painful issues, like for example (among others): what happens if the mouse is released outside the browser's window, or over an element which has a handler that stops propagation. Using setCapture() solves all this issues, and the cursor style as well.
当心拖放的幼稚实现:您可能会遇到很多痛苦的问题,例如(除其他外):如果鼠标在浏览器窗口外释放,或者在具有处理程序的元素上释放会发生什么停止传播。使用 setCapture() 解决了所有这些问题,也解决了光标样式。
You can read this excellent tutorialthat explains this in detail if you want to implement the drag and drop yourself.
如果你想自己实现拖放,你可以阅读这个优秀的教程,它详细解释了这一点。
Maybe you could also use jQuery UI draggableif possible in your context.
如果可能,您也可以在上下文中使用可拖动的 jQuery UI。
回答by Christoph
document.body.style.cursor = "move"
should work just fine.
应该工作得很好。
However, I recommend to do the global styling via CSS.
但是,我建议通过 CSS 进行全局样式设置。
define the following:
定义以下内容:
body{
cursor:move;
}
The problem is, that the defined cursors on the other elements override the body style.
问题是,其他元素上定义的光标覆盖了正文样式。
You could do someting like this:
你可以这样做:
your-element.style.cursor = "inherit"; // (or "default")
to reset it to the inherited style from the body or with CSS:
将其重置为从正文或 CSS 继承的样式:
body *{
cursor:inherit;
}
Note however, that *
is normally considered a bad selector-choice.
但是请注意,这*
通常被认为是一个糟糕的选择器选择。
回答by Andrey Subbotin
Unfortunately element.setCapture()
does not work for IE
不幸的是element.setCapture()
不适用于 IE
I use a brute force approach - open a transparent div on top of entire page for the duration of drag-drop.
我使用蛮力方法 - 在拖放期间在整个页面顶部打开一个透明的 div。
.tbFiller {
position:absolute;
z-index:5000;
left:0;
top:0;
width:100%;
height:100%;
background-color:transparent;
cursor:move;
}
...
function dragStart(event) {
// other code...
document.tbFiller=document.createElement("div");
document.tbFiller.className="tbFiller"
}
function dragStop(event) {
// other code...
document.tbFiller.parentNode.removeChild(document.tbFiller);
}
回答by ygoe
This is what I do and it works in Firefox, Chrome, Edge and IE as of 2017.
这就是我所做的,它在 2017 年适用于 Firefox、Chrome、Edge 和 IE。
Add this CSS rule to your page:
将此 CSS 规则添加到您的页面:
html.reset-all-cursors *
{
cursor: inherit !important;
}
When the <html>
element has the "reset-all-cursors" class, this overrides all cursors that are set for elements individually in their style
attribute – without actually manipulating the elements themselves. No need to clean up all over the place.
当<html>
元素具有“reset-all-cursors”类时,这会覆盖在其style
属性中为元素单独设置的所有光标——而不实际操作元素本身。无需到处清理。
Then when you want to override your cursor on the entire page with that of any element
, e.?g. the element being dragged, do this in JavaScript:
然后,当您想用 any 覆盖整个页面上的光标时element
,例如 被拖动的元素,在 JavaScript 中执行此操作:
element.setCapture && element.setCapture();
$("html").addClass("reset-all-cursors");
document.documentElement.style.setProperty("cursor", $(element).css("cursor"), "important");
It uses the setCapture
function where it is available. This is currently just Firefox although they say it's a Microsoft API. Then the special class is added to the entire document, which disables all custom cursors. Finally set the cursor you want on the document so it should appear everywhere.
它使用setCapture
可用的功能。目前这只是 Firefox,尽管他们说它是 Microsoft API。然后将特殊类添加到整个文档,这将禁用所有自定义光标。最后在文档上设置您想要的光标,使其随处可见。
In combination with capturing events, this may even extend the dragging cursor to outside of the page and the browser window. setCapture
does this reliably in Firefox. But elsewhere it doesn't work every time, depending on the browser, its UI layout, and the path along which the mouse cursor leaves the window. ;-)
结合捕获事件,这甚至可以将拖动光标扩展到页面和浏览器窗口之外。setCapture
在 Firefox 中可靠地做到这一点。但在其他地方,它并非每次都有效,这取决于浏览器、其 UI 布局以及鼠标光标离开窗口的路径。;-)
When you're finished, clean up:
完成后,清理:
element.releaseCapture && element.releaseCapture();
$("html").removeClass("reset-all-cursors");
document.documentElement.style.setProperty("cursor", "");
This includes jQuery for addClass
and removeClass
. In simple scenarios you could just plain compare and set the class
attribute of document.documentElement
. This will break other libraries like Modernizr though. You can get rid of the css
function if you know the element's desired cursor already, or try something like element.style.cursor
.
这包括 jQueryaddClass
和removeClass
. 在简单的场景,你可以只是简单的比较和设置class
的属性document.documentElement
。不过,这会破坏像 Modernizr 这样的其他库。css
如果您已经知道元素所需的光标,则可以摆脱该函数,或者尝试类似element.style.cursor
.