How to change the cursor icon when dragging in HTM

2020-08-09 08:42发布

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

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

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

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>

4条回答
Ridiculous、
2楼-- · 2020-08-09 09:28

use mousedown and 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>

查看更多
混吃等死
3楼-- · 2020-08-09 09:28

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: move declarations to see the cursor changing while dragging.

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.

For more info see MDN Drag & Drop and MDN Recommended Drag Types

查看更多
疯言疯语
4楼-- · 2020-08-09 09:28

Do you actually need the Drag API? I found that I was using the Drag API because I was having trouble with the reliability of mouse events (mouseups not being captured, for example).

The Drag API 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, .setPointerCapture is made to handle these cases more effectively. Here's the minimal viable way to achieve this:

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.

查看更多
够拽才男人
5楼-- · 2020-08-09 09:31

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

function dragover(event)
{
    event.dataTransfer.dropEffect = "move";
    event.preventDefault();
}
查看更多
登录 后发表回答