javascript 在 HTML5 中拖动时如何更改光标图标?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30052111/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 11:34:43  来源:igfitidea点击:

How to change the cursor icon when dragging in HTML5?

javascriptjquerycsshtml

提问by GibboK

I need to set the icon for cursor when a user is dragging DIV (red div in the following example).

当用户拖动 DIV 时,我需要为光标设置图标(以下示例中为红色 div)。

I have tried several attempt, including using CSS cursor:moveand event.dataTransfer.dropEffectwith no success, as the icon always show up a "crossed circle".

我尝试了好几种尝试,包括使用CSScursor:moveevent.dataTransfer.dropEffect没有成功,因为图标总是显示了一个“十字圆”。

Any ideas how to solve this issue using HTML5 drag-and-drop API?

任何想法如何使用 HTML5 拖放 API 解决此问题?

http://jsbin.com/hifidunuqa/1/

http://jsbin.com/hifidunuqa/1/

 <script>
        window.app = {
            config: {
                canDrag: false,
                cursorOffsetX: null,
                cursorOffsetY: null
            },
            reset: function () {
                this.config.cursorOffsetX = null;
                this.config.cursorOffsetY = null;
            },
            start: function () {
                document.getElementById('target').addEventListener('dragstart', function (event) {
                    console.log('+++++++++++++ dragstart')
                    this.config.cursorOffsetX = event.offsetX;
                    this.config.cursorOffsetY = event.offsetY;
                    this.adjustPostion(event);
                    event.dataTransfer.effectAllowed = 'move';
                    event.dataTransfer.dropEffect = 'move';
                }.bind(this));
                document.getElementById('target').addEventListener('drag', function (event) {
                    console.log('+++++++++++++ drag')
                    this.adjustPostion(event);
                }.bind(this));
                document.getElementById('target').addEventListener('dragend', function (event) {
                    console.log('+++++++++++++ dragend')
                    this.reset();
                }.bind(this));;
            },
            adjustPostion: function (event) {
                if (event.pageX <= 0 || event.pageY <= 0) {
                    console.log('skipped');
                    return;
                }
                var elm = document.getElementById('target');
                elm.style.left = (event.pageX - this.config.cursorOffsetX) + 'px';
                elm.style.top = (event.pageY - this.config.cursorOffsetY) + 'px';
                console.log(event.pageX);
                console.log(event.pageY);
            }

        };
    </script>

采纳答案by Ihsan

use mousedown and mousemove

使用 mousedown 和 mousemove

window.app = {
  dragging: false,
  config: {
    canDrag: false,
    cursorOffsetX: null,
    cursorOffsetY: null
  },
  reset: function () {
    this.config.cursorOffsetX = null;
    this.config.cursorOffsetY = null;
  },
  start: function () {
    document.getElementById('target').addEventListener('mousedown', function (event) {
      console.log('+++++++++++++ dragstart');
      this.dragging = true;
      this.config.cursorOffsetX = event.offsetX;
      this.config.cursorOffsetY = event.offsetY;
      this.adjustPostion(event);
    }.bind(this));
    document.getElementById('target').addEventListener('mousemove', function (event) {
      if (this.dragging) {
        console.log('+++++++++++++ drag');
        event.target.style.cursor = 'move'; 
        this.adjustPostion(event);
      }
    }.bind(this));
    document.getElementById('target').addEventListener('mouseup', function (event) {
      console.log('+++++++++++++ dragend');
      this.dragging = false;
      event.target.style.cursor = 'pointer'; 
      this.reset();
    }.bind(this));
  },
  adjustPostion: function (event) {
    if (event.clientX <= 0 || event.clientY <= 0) {
      console.log('skipped');
      return;
    }
    var elm = document.getElementById('target');
    elm.style.left = (event.clientX - this.config.cursorOffsetX) + 'px';
    elm.style.top = (event.clientY - this.config.cursorOffsetY) + 'px';
    console.log(event.pageX);
    console.log(event.pageY);
  }

};
#target {
            position: absolute;
            top: 100px;
            left: 100px;
            width: 400px;
            height: 400px;
            background-color: red;
            -moz-user-select: none;
            -ms-user-select: none;
            -webkit-user-select: none;
            user-select: none;
        }

        #ui1 {
            position: absolute;
            top: 50px;
            left: 50px;
            width: 100px;
            height: 400px;
            background-color: blue;
            z-index: 100;
        }

        #ui2 {
            position: absolute;
            top: 50px;
            left: 550px;
            width: 100px;
            height: 400px;
            background-color: green;
            z-index: 100;
        }
<!-- simulate -->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>title</title>
</head>
<body onload="window.app.start();">
    <div id="ui1"></div>
    <div id="ui2"></div>
    <div id="target"></div>
</body>
</html>

回答by Ihsan

Adding event.dataTransfer.setData();should solve the problem. Once the element is recognized as draggable the browser will add a move cursor automatically once you drag. Of course, you will have to remove all other cursor: movedeclarations to see the cursor changing while dragging.

添加event.dataTransfer.setData();应该可以解决问题。一旦元素被识别为可拖动,浏览器将在您拖动时自动添加移动光标。当然,您必须删除所有其他cursor: move声明才能看到拖动时光标的变化。

Minimal example:

最小的例子:

document.getElementById('target').addEventListener('dragstart', function (event) {
  event.dataTransfer.setData( 'text/plain', '' );
}.bind(this));

If you still want to change the icon (e.g. to use a custom drag icon), you could access the element style using event.target.style.cursor.

如果您仍想更改图标(例如使用自定义拖动图标),您可以使用 访问元素样式event.target.style.cursor

For more info see MDN Drag & Dropand MDN Recommended Drag Types

有关更多信息,请参阅MDN 拖放MDN 推荐的拖放类型

回答by nikk wong

Do you actually needthe DragAPI? I found that I was using the DragAPI because I was having trouble with the reliability of mouse events (mouseupsnot being captured, for example).

你真的需要DragAPI?我发现我在使用DragAPI 是因为我在鼠标事件的可靠性方面遇到了问题(mouseups例如,没有被捕获)。

The DragAPI is only for drag-and-drop functionality, and, if you're simply fiddling with the reliability of your clicking and pointing events, a new API, .setPointerCaptureis made to handle these cases more effectively. Here's the minimal viable way to achieve this:

DragAPI 仅用于拖放功能,如果您只是摆弄单击和指向事件的可靠性,则可以使用新的 API.setPointerCapture更有效地处理这些情况。这是实现这一目标的最小可行方法:

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

Beautifully, you will maintain full control over your cursor's display style.

美妙的是,您将保持对光标显示样式的完全控制。

回答by mikiqex

I didn't care about a particular cursor, I just wanted to get rid of the "crossed circle" one. My solution was to include dragoverevent (with following function) to all elements, that already had dragenter, dragstart and dragend events.

我不关心特定的光标,我只是想摆脱“交叉圆圈”的光标。我的解决方案是将dragover事件(具有以下功能)包含到所有已经具有 dragenter、dragstart 和 dragend 事件的元素中。

function dragover(event)
{
    event.dataTransfer.dropEffect = "move";
    event.preventDefault();
}