自定义光标与拖放HTML元素没有库

u2nhd7ah  于 2023-04-18  发布在  其他
关注(0)|答案(7)|浏览(137)

我有一个HTML页面,其中有一些可拖动的元素。我们的规格说,悬停在这样的元素鼠标光标 * 必须 * 是grab x1c 0d1x,并在拖动光标 * 必须 * 是grabbing


我知道可以设置dropEffect来改变放置区上方的光标外观,但选项很少:copymovelinknone--无 * 自定义 * 等。
我试过用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>
mbyulnm0

mbyulnm01#

似乎浏览器不允许在拖放操作开始时改变光标。我不知道为什么,但这是一个已知的问题,我相信他们会在未来。
如果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>
zysjyyx4

zysjyyx42#

这是此处报告的已知问题
拖动时,光标将自动变为正常。
我的尝试给了我以下。给了一个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>
vxf3dgd4

vxf3dgd43#

我经历了很多痛苦试图弄清楚这一点。公认的答案 * 是 * 在web上最好的答案,但现在的最佳实践是使用元素的.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)
}

明显的礼物是事实上,没有光标劫持被发现在后门偷偷在这里。

ubby3x7f

ubby3x7f4#

我对纯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>
daupos2t

daupos2t5#

我通过使用mouseover事件来定义光标,然后稍微移动移动坐标以保持鼠标指针在元素内来解决这个问题。

var onDragMove = function (e) {
const target = e.target;
  // keep mouse inside element during drag, so that cursor defined by 'mouseover' stays with it
  const x = e.clientX - 10;
  const y = e.clientY - 10;
  const moveFromLeft = x - target.parentElement.getBoundingClientRect().left; 
  const moveFromTop =  y - target.parentElement.getBoundingClientRect().top;; 

  target.style.left = `${moveFromLeft}px`
  target.style.top = `${moveFromTop}px`
};
var onMouseOver = function(e) {
        e.target.style.cursor = 'grab'
};
var  onMouseOut = function(e) {
        e.target.style.cursor = 'default'
};
var  onMouseUp = function(e) {
        e.target.style.cursor = 'default'
};
var onDragOver = function (e) {
  e.preventDefault();
};
t2a7ltrp

t2a7ltrp6#

试试这个!对我很有效!

.draggable {
    cursor: -webkit-grab;
    cursor: grab;
}

.draggable:active {
    cursor: -webkit-grabbing;
    cursor: grabbing;
}
jm2pwxwz

jm2pwxwz7#

我花了一段时间来寻找解决方案,以这个技巧结束。我觉得这是最好的方式少的代码和apt工作。

.drag{
    cursor: url('../images/grab.png'), auto; 

}

.drag:active {
    cursor: url('../images/grabbing.png'), auto;
}

相关问题