3

I have an element that is draggable. I want to remove the ghost image, since I will be creating that in another way.

However, Google Chrome is not letting me stop the ghost image from appearing using setDragImage(). The blank image is being created before the drag, and I'm using setDragImage() inside the dragstart event handler, so I don't see what I'm doing wrong. The ghost image should not be appearing.

Here's an example:

const blankCanvas = document.createElement('canvas');

document.querySelector('.item')
  .addEventListener('dragstart', (e) => {
    e.dataTransfer.setDragImage(blankCanvas, 0, 0);
  });
.item {
  display: inline-block;
  width: 5rem;
  height: 5rem;
  overflow: hidden;
  margin: 1rem;
  border: 2px solid #fe0000;
  cursor: pointer;
}

.item__img {
  width: 100%;
  height: auto;
}
<div draggable="true" class="item">
  <img src="https://i.stack.imgur.com/drhx7.png" alt="" class="item__img">
</div>

On Chrome, If you drag the box with the red border, the ghost image will appear, even though I'm using setDragImage(). Everything works correctly on Firefox (and Edge... doesn't even have the function).

My Chrome version is 66.

Andrew Myers
  • 2,754
  • 5
  • 32
  • 40

2 Answers2

4

The problem is coming from the image. If you try dragging the red border, it will work correctly. The problem will appear only when the drag begins on the image inside the draggable element. Maybe Chrome has some special treatment for images; I don't know.

You can mitigate this by disabling pointer events on the image:

.item img {
  pointer-events: none;
}

Here is a working example:

const blankCanvas = document.createElement('canvas');

document.querySelector('.item')
  .addEventListener('dragstart', (e) => {
    e.dataTransfer.setDragImage(blankCanvas, 0, 0);
  });
.item {
  display: inline-block;
  width: 5rem;
  height: 5rem;
  overflow: hidden;
  margin: 1rem;
  border: 2px solid #fe0000;
  cursor: pointer;
}

.item__img {
  width: 100%;
  height: auto;
  
  /* The fix */
  pointer-events: none;
}
<div draggable="true" class="item">
  <img src="https://i.stack.imgur.com/drhx7.png" alt="" class="item__img">
</div>
Andrew Myers
  • 2,754
  • 5
  • 32
  • 40
  • 2
    Do you know how to remove the globe icon that gets added to the cursor on this example? I've seen some suggesting using `onmousedown="event.preventDefault()"` but that disables dragging altogether. – anabella Mar 12 '21 at 11:18
  • I'm not sure what you mean by "globe icon". Are you talking about the Not Allowed cursor? If so, I don't think there's any easy way to change it. I believe that the cursors used during drag and drop are based on the platform. For custom cursors, you would have to reimplement your own drag and drop using JavaScript. – Andrew Myers Mar 12 '21 at 14:22
  • 1
    That globe icon is very frustrating – ness-EE Jun 22 '21 at 14:41
  • 1
    @ness-EE If you're talking about the Not Allowed cursor, I think that means your mouse is not over a valid drop target. Maybe if you had a container that is a valid drop target surrounding the image then the cursor wouldn't turn into Not Allowed immediately. But that's a little beyond the scope of this question. – Andrew Myers Jun 22 '21 at 15:33
  • Nope... I'm talking about the globe icon --> https://stackoverflow.com/questions/6771196/stopping-chrome-from-changing-cursor-to-a-globe-while-dragging-a-link – ness-EE Jun 22 '21 at 16:19
  • @ness-EE I saw that question, but I'm still not sure what the globe is. I'm using Chrome, but all I see is a Not Allowed cursor. Can you take a screenshot or link to a picture of it? – Andrew Myers Jun 22 '21 at 18:20
  • 3
    @ness-EE I had the same globe icon problem (mac + chrome). Solution is canvas need to be part of the DOM. If we extend the example above before this line `e.dataTransfer.setDragImage(blankCanvas, 0, 0);` you will want something like this: `document.body.appendChild(blankCanvas);`. This should remove the "404" globe default icon. (Of course you can remove the blankCanvas element on dragend event. – Bálint Réthy Jul 17 '21 at 20:28
  • ^ was looking so long for this – max Oct 16 '22 at 21:54
2

Adding to a solution provided by @ness-EE.

This is the solution I used and also handles case of hiding the globe in chrome

public handleDragStart( event : DragEvent ) : void {
    const blankCanvas: any = document.createElement('canvas');
    event.dataTransfer?.setDragImage( blankCanvas, 0, 0);
    document.body?.appendChild( blankCanvas);
}
Cory Lewis
  • 559
  • 5
  • 6