web-dev-qa-db-ja.com

ライブラリなしのHTML要素をドラッグアンドドロップするカスタムカーソル

ドラッグ可能な要素を含むHTMLページがあります。私たちの仕様では、カーソルをそのような要素の上に置くとカーソルmustgrabgrab 、およびドラッグカーソル中must be grabbinggrabbing

dropEffect を設定して、ドロップゾーンの上にカーソルの外観を変更することは可能ですが、選択肢はほとんどありません:copymovelink、およびnone-いいえcustomなど。

ondragstartが発生したときにcursor: grabbing;を設定するなど、JavaScriptとCSSでカーソルを変更しようとしました。ただし、ドロップゾーンでドラッグすると、ブラウザのデフォルトの移動カーソルが代わりに表示されます。

だから問題は次のとおりです:グラブカーソル( 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>
18
Travenin

ブラウザーがドラッグアンドドロップ操作の最初にカーソルを変更することを許可していないようです。理由はわかりませんが、これは既知の問題です。将来的には解決されると思います。

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>
5
Javier Rey

これは報告されている既知の問題です ここ

ドラッグ中、カーソルは自動的に通常に変わります。

私の試みは私に次のことを与えました。カーソルをつかんで要素に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>
5
Sagar V

私はこれを理解しようとして多くの苦痛を経験しました。受け入れられた回答was Webでの最良の回答ですが、今のベストプラクティスは、要素の.setPointerCaptureイベントを使用することです。これにより、要素のドラッグのような動作を聞いて操作できます。 Drag AP​​Iの狭い動作に囲まれることなく。それを行う1つの方法は次のようになります。

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)
}

明らかな贈り物は、ここのバックドアに忍び寄るカーソルハイジャックがないことです。

1
nikk wong

これを試して !わたしにはできる !

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

.draggable:active {
    cursor: -webkit-grabbing;
    cursor: grabbing;
}
0
Richard Foucaud

純粋な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>
0
UfguFugullu

私はしばらくの間、この解決策を見つけるために費やし、このトリックで終わりました。これは、コードを減らして適切に機能する最善の方法だと思います。

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

}

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