ember-drag-drop icon indicating copy to clipboard operation
ember-drag-drop copied to clipboard

Possible to use setDragImage() to use a custom drag image?

Open zethussuen opened this issue 7 years ago • 4 comments

Tried using dragStartHook, but I don't think that's the correct place. Any pointers?

zethussuen avatar Sep 27 '17 22:09 zethussuen

Hey glad you asked this question. I have a similar task where I need to customize the drag image and am trying to modify the ghost image without any luck. I tried the following method but the drag image is not updating.

Anyone else had any luck customizing the drag image?

dragStartAction(event){
    let clonedItem = event.target.cloneNode(true);
    clonedItem.style.position = "absolute"; 
    clonedItem.style.background = "red"; 
    clonedItem.style.top = "0px"; 
    clonedItem.style.right = "0px";
    document.body.appendChild(clonedItem);
    event.dataTransfer.setDragImage(clonedItem, 0 ,0 );
}

fxvarga avatar Oct 05 '17 20:10 fxvarga

+1

AlekzZz avatar Nov 16 '17 00:11 AlekzZz

You need to use dragStartAction='dragStartAction' instead of dragStartHook=(action 'dragStartAction') because of this: https://github.com/mharris717/ember-drag-drop/blob/master/addon/components/draggable-object.js#L78-L83

majnikov avatar Jul 03 '18 19:07 majnikov

Anyone else had any luck customizing the drag image?

yup.

First of all, the dragStartAction actions works with 2 arguments (obj, event), see:

this.get('dragStartAction')(obj, event);

Source: https://github.com/mharris717/ember-drag-drop/blob/v0.9.0-beta.0/addon/components/draggable-object.js#L115

Hence, the replacement:

dragStartAction(object, event){
    let clonedItem = event.target.cloneNode(true);
    clonedItem.style.position = "absolute"; 
    clonedItem.style.background = "red"; 
    clonedItem.style.top = "0px"; 
    clonedItem.style.right = "0px";
    document.body.appendChild(clonedItem);
    event.dataTransfer.setDragImage(clonedItem, 0 ,0 );
}

should make it works.

Apart from that, the setDragImage needs the existed node in DOM, the document.body.appendChild(clonedItem); solves this, but I think it's better to use the Ember component for this to have full customization ability, for example, we can use https://github.com/lifeart/ember-ref-bucket for this reference or archived alternative https://github.com/lifeart/ember-ref-modifier.

The implementation looks like this: app/components/draggable-item.hbs

<DraggableObject
  @dragStartAction={{this.onDragStart}}
>
</DraggableObject>

app/components/draggable-item.js

import Component from '@glimmer/component';
import { action } from '@ember/object';
import { globalRef } from 'ember-ref-bucket';

export default class DraggableItemComponent extends Component {
  @globalRef('draggableNode') draggableNode = null;

  @action
  onDragStart(object, event) {
    const x = 0;
    const y = 0;
    event.dataTransfer.setDragImage(this.draggableNode, x, y);
  }
}

app/components/drag-item.js

<div
  class="absolute -left-full"
  {{create-global-ref "draggableNode"}}
  ...attributes
>
  "We can use here any components with full customization ability"
</div> 

the classes absolute -left-full takes from https://tailwindcss.com/ it needs to move this node out of the visible screen, in CSS way it looks like this:

  position: absolute;
  left: -100%;

app/templates/application.hbs or anywhere you want just to have global reference:

...
<DragItem/>
...

Mifrill avatar Dec 03 '21 07:12 Mifrill