如何在拖动时更改光标?Material CDK 拖放

13

我正在使用 Material CDK 库的拖放行为(Drag and Drop behavior),尝试在拖动 cdkDrag 元素时更改光标。

例如,在这个 StackBlitz中,当鼠标悬停时,光标是 grab。我希望在拖动时它可以更改为 grabbing。谷歌表格中抓取行时发生的情况就是一个例子:

enter image description here

根据文档为拖放组件设置样式,似乎将 cursor 属性添加到该类即可解决问题:

.cdk-drop-list-dragging: 当用户拖动项目时添加到 cdkDropList 中的类。

代码看起来像这样:

.example-box {
  /* other CSS properties */
  cursor: grab;
}

.cdk-drop-list-dragging {
  cursor: grabbing;
}

然而,正如您在 StackBlitz 中看到的那样,似乎并没有改变光标。我猜想这是因为此类应用于列表而非光标。

另一个可能性是 .cdk-drag-preview 类:

.cdk-drag-preview:这是在可排序列表中拖动项目时将呈现在用户光标旁边的元素。默认情况下,该元素看起来与正在拖动的元素完全相同。

这似乎也不起作用。我认为这是因为它改变了在光标旁边呈现的元素而不是光标本身。

有什么想法可以在拖动时更改光标吗?


之前的解决方案对我没有用,但是这里有一个解决方案很可能适用于仍然遇到问题的任何人 - Neveh
6个回答

13
之前的解决方案对我没有用,但是这里有一个很可能适用于仍然遇到问题的任何人的解决方案:
首先添加以下全局CSS:
body.inheritCursors * {
  cursor: inherit !important;
}

在你的cdkDrag元素中添加cdkDragStarted,并将其附加到你的.ts文件中的一个方法:

<div cdkDrag (cdkDragStarted)="dragStart($event)"></div>

在您的 .ts 文件中,您可以切换拖动开始和停止时想要的光标:

bodyElement: HTMLElement = document.body;

  dragStart(event: CdkDragStart) {
    this.bodyElement.classList.add('inheritCursors');
    this.bodyElement.style.cursor = 'move'; 
    //replace 'move' with what ever type of cursor you want
  }

  drop(event: CdkDragDrop<string[]>) {
    this.bodyElement.classList.remove('inheritCursors');
    this.bodyElement.style.cursor = 'unset';
    ...
    ...
  }

这是一个在StackBlitz上工作的链接示例。希望这对你有所帮助。


标记的答案适用于 OP 的示例。然而,这个答案在更一般的情况下也适用,特别是在使用 cdkDropList 时。 - ShadowOfLies
没错,我相信这对于那些在寻找解决方案时遇到与 OP 相似障碍的人来说是一个不错的选择。在我的情况下,我有多个 cdkDropList,它们之间是连接的。当我将 cdkDrag 元素从其原始父元素中拖出时,我没有得到想要的抓取光标。 - Neveh

1

对于我自己,我添加了以下样式覆盖来在拖动时重新启用自定义光标。

.draggable-element .drag-handle{
  cursor: grab;
}

.draggable-element.cdk-drag-preview .drag-handle{
  pointer-events: auto;
  cursor: grabbing;
}

链接到 实时示例

(保留HTML)

嗨Joel,感谢您的贡献。不幸的是,这个解决方案无法像被接受的答案一样在单击时复制抓取行为(因为它仅在拖动时抓取)。 - Patrick

1
如果我们有这个例子。
    <div cdkDropList class="drag-drop-container">
      <div *ngFor="let item of array" cdkDrag>
        // content
      </div>
    </div>

使用 .cdk-drop-list-dragging

.drag-drop-container.cdk-drop-list-dragging {
  cursor: grabbing;
}

你可能也需要将这个添加到其他类中


1

只需在您的 example-box:active 上添加 cursor: grabbing 即可。

.example-box:active {
  box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),
              0 8px 10px 1px rgba(0, 0, 0, 0.14),
              0 3px 14px 2px rgba(0, 0, 0, 0.12);
  cursor: grabbing;
}

:active选择器用于选择和样式化活动链接。

当您单击链接时,链接变为活动状态。

提示::active选择器不仅可用于链接,也可用于所有元素。

此处提供额外信息。

https://www.w3schools.com/cssref/sel_active.asp


Stackblitz

https://stackblitz.com/edit/angular-b8kjj3-r993mc?embed=1&file=app/cdk-drag-drop-overview-example.css


你能否在回答中加入active在这里的作用以及你是如何知道使用该属性的呢?我之所以问是因为我在文档中没有看到任何解释,我不仅想知道答案,还想了解背后的原因。 - Patrick
1
@Marshal,有什么办法可以让这个在cdkDropList中工作?这个例子不起作用。 - lostintranslation
我没有给你的回答点踩,但你可能需要添加一些细节来说明这个答案与CSS伪类有关,当我们点击并按住任何元素时。它不是特定于Angular的。 - Ben Racicot

0
在您的 Stackblitz 示例中,您没有使用 droplist,因此您需要使用以下 css:
.cdk-drag-dragging {
  cursor: grabbing;
}

在我的情况下,使用表格主体元素上的列表进行拖放,我使用了:
table tbody.cdk-drop-list-dragging td {
  cursor: grabbing !important;
}

被接受的答案使用了OP引用的链接Stackblitz来提供问题的解决方案。 - Marshal
确实,当使用下拉列表时,被接受的答案并不足够。一旦您开始移动元素,它将失去样式。但是这个答案也不完全正确,因为它会错过在开始移动之前的抓取。为了使其完全工作,我不得不结合这个答案和被接受的答案。 - Recek

-1
只需使用 onmousedown = "changeCursorPoint()" 事件函数 -
private changeCursorPoint(): void {
    document.body.style.cursor = 'grabbing';
}

(cdkDropListDropped) = "clearCursorEvent()" 上再次清除该函数。

private changeCursorToDefault(): void {
    document.body.style.cursor = 'default';
 }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接