自定义光标与拖放没有库的 HTML 元素
Posted
技术标签:
【中文标题】自定义光标与拖放没有库的 HTML 元素【英文标题】:Custom cursor with drag and drop an HTML element without libraries 【发布时间】:2017-11-10 20:19:39 【问题描述】:我有一个包含一些可拖动元素的 html 页面。我们的规范规定,将鼠标悬停在此类元素上时,光标必须为grab
,并且在拖动期间光标必须为grabbing
。
我知道可以设置 dropEffect
来改变拖放区上方的光标外观,但选项很少:copy
、move
、link
和 none
-- 没有 自定义 或类似的。
我尝试使用 javascript 和 CSS 更改光标,例如在触发 ondragstart
时设置 cursor: grabbing;
。但是在拖放区域上拖动时会出现浏览器默认的移动光标。
所以问题是:在拖动过程中我缺少什么来显示抓取光标 ()?
不幸的是,我无法在解决方案中使用 JQuery 或其他帮助库。提前致谢!
var onDragStart = function(event)
event.dataTransfer.setData("Text", event.target.id);
event.currentTarget.classList.add("being-dragged");
;
var onDragEnd = function(event)
event.currentTarget.classList.remove("being-dragged");
;
var onDragOver = function(event)
event.preventDefault();
;
.dropzone
width: 500px;
height: 200px;
background-color: silver;
.block
position: absolute;
background-color: pink;
margin: 10px;
border: 20px solid pink;
.draggable
cursor: -webkit-grab;
cursor: grab;
.being-dragged
cursor: -webkit-grabbing;
cursor: grabbing;
background-color: red;
<div class = "dropzone"
ondragover = "onDragOver(event);"
>
Grab and drag block around
<div class = "draggable block"
draggable = "true"
ondragstart = "onDragStart(event);"
ondragend = "onDragEnd(event);"
>
I'm draggable
</div>
</div>
【问题讨论】:
应该是简单的JavaScript
还是你也会使用jQuery
?如果你会使用jQuery
,那么你会使用jQuery UI
s Draggable
插件吗?
纯 JS。 jQuery 无法使用,抱歉。
您将不得不使用假光标;跟随鼠标的img。这将与本机图标一起显示,因此您需要使其与外观相得益彰,而不是与之竞争。 afaik,你会得到最接近的。
【参考方案1】:
为了弄清楚这一点,我经历了很多痛苦。接受的答案是网络上的最佳答案,但现在的最佳做法是使用元素的 .setPointerCapture
事件,它允许您在元素上收听类似拖动的行为并采取行动限制在Drag
API 的狭隘行为中。一种方法是这样的:
el.onpointerdown = ev =>
el.onpointermove = pointerMove
el.setPointerCapture(ev.pointerId)
pointerMove = ev =>
console.log('Dragged!')
el.onpointerup = ev =>
el.onpointermove = null
el.releasePointerCapture(ev.pointerId)
显而易见的礼物是,这里没有发现潜行在后门中的光标劫持。
【讨论】:
【参考方案2】:似乎浏览器不允许在拖放操作开始时更改光标。我不知道为什么,但这是一个已知问题,我相信他们将来会这样做。
如果 jQuery 不是一个选项,一种可能的解决方法是从头开始实现拖放,使用鼠标事件并克隆源元素:
var onDragStart = function (event)
event.preventDefault();
var clone = event.target.cloneNode(true);
clone.classList.add("dragging");
event.target.parentNode.appendChild(clone);
var style = getComputedStyle(clone);
clone.drag =
x: (event.pageX||(event.clientX+document.body.scrollLeft)) - clone.offsetLeft + parseInt(style.marginLeft),
y: (event.pageY||(event.clientY+document.body.scrollTop)) - clone.offsetTop + parseInt(style.marginTop),
source: event.target
;
;
var onDragMove = function (event)
if (!event.target.drag) return;
event.target.style.left = ((event.pageX||(event.clientX+document.body.scrollLeft)) - event.target.drag.x) + "px";
event.target.style.top = ((event.pageY||(event.clientY+document.body.scrollTop)) - event.target.drag.y) + "px";
;
var onDragEnd = function (event)
if (!event.target.drag) return;
// Define persist true to let the source persist and drop the target, otherwise persist the target.
var persist = true;
if (persist || event.out)
event.target.parentNode.removeChild(event.target);
else
event.target.parentNode.removeChild(event.target.drag.source);
event.target.classList.remove("dragging");
event.target.drag = null;
;
var onDragOver = function (event)
event.preventDefault();
;
.dropzone
width: 500px;
height: 200px;
background-color: silver;
.block
position: absolute;
background-color: pink;
margin: 10px;
border: 20px solid pink;
.draggable
position: absolute;
cursor: pointer; /* IE */
cursor: -webkit-grab;
cursor: grab;
.dragging
cursor: -webkit-grabbing;
cursor: grabbing;
background-color: red;
<div class="dropzone" onmouseover="onDragOver(event);">
Grab and drag block around
<div class = "draggable block"
onmousedown = "onDragStart(event);"
onmousemove = "onDragMove(event);"
onmouseup = "onDragEnd(event);"
onmouseout = "event.out = true; onDragEnd(event);"
>
I'm draggable
</div>
</div>
【讨论】:
浏览器似乎不支持原生拖动事件中的自定义光标,这很可悲。你的回答最接近我的预期。谢谢。【参考方案3】:我花了一些时间来解决这个问题,以这个技巧结束。我觉得这是减少代码和恰当工作的最佳方式。
.drag
cursor: url('../images/grab.png'), auto;
.drag:active
cursor: url('../images/grabbing.png'), auto;
【讨论】:
【参考方案4】:试试这个!它对我有用!
.draggable
cursor: -webkit-grab;
cursor: grab;
.draggable:active
cursor: -webkit-grabbing;
cursor: grabbing;
【讨论】:
不适合我。您使用的是哪种浏览器和操作系统?我使用的是 Windows 和最新的 Chrome 和 Firefox。 我使用的是 Windows 8 和 Chrome 59,对我来说没问题 在这个 JS fiddle 中也有? jsfiddle.net/7Lrofezt我将您的答案与我的代码结合在一起。 好的,我明白了.. 移动框时光标会发生变化。我试图修改你的 jsfiddle 来帮助你解决这个问题,但我还不能。祝你好运【参考方案5】:这是一个已知问题报告here
拖动时,光标会自动变正常。
我的尝试给了我以下信息。使用抓取光标在元素上添加active
。当它处于活动状态时,光标会改变,但一旦你开始拖动,它会自动改变。
我尝试将 body
光标设置为在 dragstart 上抓取但没有结果。即使它不起作用。
var onDragStart = function(event)
event.dataTransfer.setData("Text", event.target.id);
event.currentTarget.classList.add("being-dragged");
;
var onDragEnd = function(event)
event.currentTarget.classList.remove("being-dragged");
;
var onDragOver = function(event)
event.preventDefault();
;
.dropzone
width: 500px;
height: 200px;
background-color: silver;
.block
position: absolute;
background-color: pink;
margin: 10px;
border: 20px solid pink;
.draggable
cursor: -webkit-grab;
cursor: grab;
.draggable:active
cursor : -moz-grabbing;
cursor: -webkit-grabbing;
cursor: grabbing;
.being-dragged
background-color: red;
cursor : -moz-grabbing;
cursor: -webkit-grabbing;
cursor: grabbing;
<div class = "dropzone"
ondragover = "onDragOver(event);"
>
Grab and drag block around
<div class = "draggable block"
draggable = "true"
ondragstart = "onDragStart(event);"
ondragend = "onDragEnd(event);"
>
I'm draggable
</div>
</div>
【讨论】:
【参考方案6】:我对纯JavaScript
的可拖动元素了解一点,很抱歉我无法解释以下内容。
问题是onDragEnd
永远不会被解雇,所以我搜索了一些东西并找到了这个带有可拖动元素的example。
现在,如果您更改 onDragStart
事件的功能,它将起作用,但我认为您必须以另一种方式更改光标,例如更改主体的类 onDragStart
var onDragStart = function(event)
event.dataTransfer.setData("Text", event.target.id);
event.currentTarget.classList.add("being-dragged");
;
一体机
var onDragStart = function(event)
event.dataTransfer.setData("Text", event.target.id);
event.currentTarget.classList.add("being-dragged");
;
var onDragEnd = function(event)
event.currentTarget.classList.remove("being-dragged");
;
var onDragOver = function(event)
event.preventDefault();
;
.dropzone
width: 500px;
height: 500px;
background-color: silver;
.block
width: 200px;
height: 50px;
background-color: pink;
.draggable1
cursor: -webkit-grab;
cursor: grab;
.being-dragged
cursor: -webkit-grabbing;
cursor: grabbing;
background-color: red;
<div class="dropzone" ondragover="onDragOver(event);">
<div class="draggable1 block" draggable="true" ondragstart="onDragStart(event);" ondragend="onDragEnd(event);">
I'm draggable
</div>
</div>
【讨论】:
感谢您的回答,它在我的 sn-p 中提供了一个错误修复(编辑了我的问题),但我真正的问题是抓取光标,而您的回答没有提供。以上是关于自定义光标与拖放没有库的 HTML 元素的主要内容,如果未能解决你的问题,请参考以下文章