Глобальное переопределение курсора мыши с помощью JavaScript

В моем веб-приложении я пытаюсь реализовать некоторые функции перетаскивания. У меня есть глобальный компонент JavaScript, который делает основной материал. Этот объект также отвечает за изменение указателя мыши в зависимости от текущей операции перетаскивания (перемещение, копирование, ссылка). На моей веб-странице есть различные HTML-элементы, которые определяют собственный стиль курсора, как встроенный, так и через CSS файл.

Итак, есть ли способ, чтобы мой центральный компонент перетаскивания менял курсор мыши глобально, независимо от стиля элемента, над которым курсор мыши закончился?

Я пробовал:

document.body.style.cursor = "move"

и

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

Но это не сработает. Каждый раз, когда я перетаскиваю элемент, определяющий стиль курсора, курсор меняется на этот стиль.

Конечно, я мог бы изменить стиль элемента, который я сейчас перетаскиваю, но тогда я должен reset его, когда я убираю элемент. Это кажется немного сложным. Я ищу глобальное решение.

Ответ 1

Пожалуйста, не убивайте CSS!

Чтобы реализовать операцию перетаскивания, вам нужно использовать очень важный API: element.setCapture(). Это имеет следующие последствия:

  • Все события мыши перенаправляются на целевой элемент захвата, независимо от того, где они происходили (даже вне окна браузера).
  • Курсор будет курсором целевого элемента захвата, независимо от того, где находится указатель мыши.

Вы должны вызвать element.releaseCapture() или document.releaseCapture(), чтобы вернуться в нормальный режим в конце операции.

Остерегайтесь наивной реализации перетаскивания: у вас может быть много болезненных проблем, например, например (что-то еще): что произойдет, если мышь вывешивается за пределами окна браузера или над элементом, который имеет обработчик, который останавливает распространение. Использование setCapture() решает все эти проблемы и стиль курсора.

Вы можете прочитать этот отличный учебник, который подробно объясняет это, если вы хотите реализовать перетаскивание самостоятельно.

Возможно, вы также можете использовать jQuery UI draggable, если это возможно в вашем контексте.

Ответ 2

document.body.style.cursor = "move"

должен работать нормально.

Однако я рекомендую сделать глобальный стиль с помощью CSS.

определяют следующее:

body{
   cursor:move;
}

Проблема заключается в том, что определенные курсоры на других элементах переопределяют стиль тела.

Вы можете сделать следующее:

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

до reset до унаследованного стиля из тела или с помощью CSS:

body *{
   cursor:inherit;
}

Обратите внимание, что * обычно считается неправильным выбором выбора.

Ответ 3

К сожалению, 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);
}

Ответ 4

Если вы выполните объявление css:

* {cursor:move;}

Он должен работать.

Ответ 5

Это то, что я делаю, и работает в Firefox, Chrome, Edge и IE с 2017 года.

Добавьте это правило CSS на свою страницу:

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

Когда элемент <html> имеет класс "reset -all-cursors", он переопределяет все курсоры, которые устанавливаются для элементов по отдельности в свой атрибут style, без фактического управления самими элементами. Нет необходимости чистить все места.

Затем, когда вы хотите переопределить курсор на всей странице с помощью любой element, e. г. элемент перетаскивается, выполните это в 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. Но в другом месте он не работает каждый раз, в зависимости от браузера, его макета пользовательского интерфейса и пути, по которому курсор мыши покидает окно.; -)

Когда вы закончите, очистите:

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

Это включает jQuery для addClass и removeClass. В простых сценариях вы можете просто сравнить и установить атрибут class document.documentElement. Однако это сломает другие библиотеки, такие как Modernizr. Вы можете избавиться от функции css, если вы уже знаете элемент, который уже нужен, или попробуйте что-то вроде element.style.cursor.