使用JavaScript全局覆盖鼠标光标

时间:2012-05-25 07:51:35

标签: javascript html css mouse-cursor

在我的Web应用程序中,我尝试实现一些拖放功能。我有一个全局JavaScript组件,它完成了基本的工作。此对象还负责根据当前拖动操作(移动,复制,链接)更改鼠标光标。在我的网页上有各种HTML元素,它们可以内联或通过CSS文件定义自己的光标样式。

那么,我的中央拖放组件是否有办法全局更改鼠标光标,与鼠标光标所在元素的样式无关?

我试过了:

document.body.style.cursor = "move"

document.body.style.cursor = "move !important"

但它不起作用。每次我拖动一个定义光标样式的元素时,光标会变为该样式。

当然,我可以改变我正在拖动的元素的样式,但是当我把元素拉出来时我必须重置它。这似乎有点复杂。我正在寻找全球解决方案。

6 个答案:

答案 0 :(得分:12)

请:不要屠杀你的CSS!

要实现拖放功能,您必须使用非常重要的API: element.setCapture()。这会产生这样的后果:

  • 所有鼠标事件都被重定向到捕获的目标元素,无论它们发生在何处(甚至在浏览器窗口之外)
  • 无论鼠标指针在何处,光标都将成为捕获目标元素的光标。

您必须在操作结束时调用 element.releaseCapture() document.releaseCapture()切换回正常模式。

谨防拖放的天真实现: 你可能会遇到很多痛苦的问题,比如(等等):如果鼠标是什么会发生什么在浏览器窗口外部或在具有停止传播的处理程序的元素上释放。使用setCapture()解决了所有这些问题,以及光标样式。

如果您想自行实施拖放操作,可以阅读this excellent tutorial,详细解释这一点。

如果可能,您也可以在上下文中使用jQuery UI draggable

答案 1 :(得分:4)

document.body.style.cursor = "move"

应该可以正常工作。

但是,我建议通过CSS进行全局样式设计。

定义以下内容:

body{
   cursor:move;
}

问题是,其他元素上定义的游标会覆盖正文样式。

你可以这样做:

your-element.style.cursor = "inherit"; // (or "default")

将其重置为主体或CSS的继承样式:

body *{
   cursor:inherit;
}

但请注意,*通常被视为选择不当的选择。

答案 2 :(得分:4)

不幸的是element.setCapture()不适用于IE

我使用蛮力方法 - 在拖放期间在整个页面的顶部打开透明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);
}

答案 3 :(得分:1)

由于这里提供了其他一些答案,因此效果很好:

/* Disables all cursor overrides when body has this class. */
body.inheritCursors * {
    cursor: inherit !important;
}

注意:我不是需要使用<html>document.documentElement;相反,<body>document.body可以正常工作:

document.body.classList.add('inheritCursors');

这会导致<body>的{​​{3}} all个元素(因为它现在有了这个inheritCursors类)会从<body>本身继承其光标,您将其设置为:

document.body.style.cursor = 'progress';

然后要放弃对后代元素的控制,只需删除该类:

document.body.classList.remove('inheritCursors');

,然后将<body>上的光标descendant设为默认值:

document.body.style.cursor = 'unset';

答案 4 :(得分:0)

这就是我的工作,它可以在2017年的Firefox,Chrome,Edge和IE中使用。

将此CSS规则添加到您的网页:

html.reset-all-cursors *
{
    cursor: inherit !important;
}

<html>元素具有&#34; reset-all-cursors&#34; class,这将覆盖在style属性中单独为元素设置的所有游标 - 而不实际操作元素本身。无需在整个地方进行清理。

然后,如果要覆盖整个页面上的光标,请使用任何element覆盖光标,e。 G。要拖动的元素,请在JavaScript中执行此操作:

element.setCapture && element.setCapture();
$("html").addClass("reset-all-cursors");
document.documentElement.style.setProperty("cursor", $(element).css("cursor"), "important");

它使用可用的setCapture函数。这只是Firefox,虽然他们说它是Microsoft API。然后将特殊类添加到整个文档,这将禁用所有自定义游标。最后在文档上设置所需的光标,使其随处出现。

结合捕获事件,这甚至可以将拖动光标扩展到页面外部和浏览器窗口。 setCapture在Firefox中可靠地完成此操作。但在其他地方,它每次都不起作用,具体取决于浏览器,UI布局以及鼠标光标离开窗口的路径。 ; - )

当你完成后,清理:

element.releaseCapture && element.releaseCapture();
$("html").removeClass("reset-all-cursors");
document.documentElement.style.setProperty("cursor", "");

这包括addClassremoveClass的jQuery。在简单的场景中,您可以简单地比较并设置class的{​​{1}}属性。这会破坏像Modernizr这样的其他库。如果您已经知道元素所需的光标,则可以删除document.documentElement函数,或尝试css之类的内容。

答案 5 :(得分:0)

我尝试使用 setPointerCapture 效果很好。缺点是,(当然)所有指针事件都不会像以前那样工作。所以我失去了悬停样式等

我现在的解决方案非常简单,对于我的用例来说,比上述 CSS 解决方案更适合。

为了设置光标,我向头部添加了一个新的样式表:

const cursorStyle = document.createElement('style');
cursorStyle.innerHTML = '*{cursor: grabbing!important;}';
cursorStyle.id = 'cursor-style';
document.head.appendChild(cursorStyle);

要重置它,我只需删除样式表:

document.getElementById('cursor-style').remove();