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

Posted

技术标签:

【中文标题】在 HTML5 中拖动时如何更改光标图标?【英文标题】:How to change the cursor icon when dragging in HTML5? 【发布时间】:2015-07-15 03:16:14 【问题描述】:

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

我尝试了几次,包括使用 CSS cursor:moveevent.dataTransfer.dropEffect 都没有成功,因为图标总是显示一个“交叉的圆圈”。

任何想法如何使用 html5 拖放 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>

【问题讨论】:

mousedown 事件呢? 是的 jquery 解决方案也可以。谢谢 @Pete 这行得通吗?该元素一直都有cursor: move !important; 样式。在拖动时添加这样的样式似乎不太可能改变行为。 @lharby 您的示例未使用 HTML5 拖放 API,这是此特定问题的根源。 @GibboK this may help you - 请参阅拖动属性部分。它显示您可以在拖动时添加自己的图标,但它似乎与禁止进入的圆圈一起使用(这可能是强制性的,因为它表明您不允许将对象放在您所在的位置) 【参考方案1】:

使用 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>

【讨论】:

为什么需要控制光标偏移?该示例运行完美,但无法在我的应用中复制,不知道为什么。 确保元素不会跳转,因为当您单击元素时,您在元素内单击了它,并且您需要在元素内偏移光标位置。【参考方案2】:

您真的需要Drag API 吗?我发现我正在使用Drag API,因为我在鼠标事件的可靠性方面遇到了问题(例如,mouseups 未被捕获)。

Drag API 仅用于拖放功能,而且,如果您只是在摆弄单击和指向事件的可靠性,则可以使用新的 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)

您可以完全控制光标的显示样式。

【讨论】:

这应该是公认的答案。确实是一个漂亮的解决方案。 很好的建议【参考方案3】:

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

function dragover(event)

    event.dataTransfer.dropEffect = "move";
    event.preventDefault();

【讨论】:

【参考方案4】:

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

小例子:

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

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

有关更多信息,请参阅MDN Drag & Drop 和 MDN Recommended Drag Types

【讨论】:

不幸的是,这似乎不起作用。使用 event.target.style.cursor='none';不改变光标。您能否将您的解决方案应用于我的 jsfiddle 并将链接发送给我?谢谢 老实说,我不再完全确定您要做什么。如果您的目标是在拖动过程中更改/删除图标,我不知道这是否可能。似乎 CSS 更改仅影响未拖动的元素。有几个指点:***.com/questions/6079346/…developer.mozilla.org/en-US/docs/Web/Guide/HTML/Drag_operations 正确,我需要在使用 HTML5 拖放 API 的拖动过程中更改图标。感谢您抽出宝贵时间。

以上是关于在 HTML5 中拖动时如何更改光标图标?的主要内容,如果未能解决你的问题,请参考以下文章

HTML5 Drag & Drop 在拖动时更改光标(不要使用 UI)

如何将 HTML5 <canvas> 保存为 ICO 图像(图标文件)或 .cur 文件(静态鼠标光标)而不是 JavaScript 中的 PNG?

C# Winforms - 更改鼠标的光标图标

Qt - 如何在拖动项目时显示图像/图标/数据?

更改html5拖放功能,使元素看起来附加到光标[重复]

自定义 UISlider 拇指图标:如何阻止拇指图标在拖动时恢复为默认圆形图标?