tryhuma
tryhuma

Reputation: 25

angular 2 drag&drop duplicated element

I have some code on plunker in drag.ts > http://plnkr.co/edit/PITLKzBB6YXobR1gubOw?p=preview which impements drag&drop (it works only in separated window preview)

import {Component, OnInit, ElementRef, Renderer} from '@angular/core'

@Component({
  selector: 'my-drag',
  template: `
    <div class="drag"
        draggable="true"
        (dragstart)="onDragStart($event)"
        (dragend)="onDragEnd($event)"
        (drag)="onDrag($event)">
      drag
    </div>
  `,
  styles: ['.drag {width: 50px; height: 50px; border: 1px solid black; background-color: red;}']
})
export class DragComponent implements OnInit {
  private dx: number = 0;
  private dy: number = 0;

  constructor(private el: ElementRef, private renderer: Renderer) { }

  ngOnInit() {
    this.renderer.setElementStyle(this.el.nativeElement, 'position', 'absolute');
  }

  onDragStart(event: MouseEvent) {
    this.dx = event.x - this.el.nativeElement.offsetLeft;
    this.dy = event.y - this.el.nativeElement.offsetTop;
  }

  onDrag(event: MouseEvent) {
    this.move(event.x, event.y);
    this.renderer.setElementAttribute(this.el.nativeElement, 'draggable', 'false');
  }

  onDragEnd(event: MouseEvent) {
    this.dx = 0;
    this.dy = 0;
  }

  move(x: number, y: number) {
    if (!x || !y) return;

    this.renderer.setElementStyle(this.el.nativeElement, 'top', (y - this.dy) + 'px');
    this.renderer.setElementStyle(this.el.nativeElement, 'left', (x - this.dx) + 'px');
  }
}

and some problems with it:

  1. when div is dragged, it is duplicated behind - how to fix it?
  2. when div is dragged, the cursor changes - how to set it to default?

Thanks all!

Upvotes: 1

Views: 1074

Answers (1)

Fiddles
Fiddles

Reputation: 2915

You can set the native drag image to a transparent image to remove the duplication.

  onDragStart(event: MouseEvent) {
    var dragImgEl = document.createElement('img'); 
    dragImgEl.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'; // Creates a minimal transparent image
    event.dataTransfer.setDragImage(dragImgEl, 0, 0);

    this.dx = event.x - this.el.nativeElement.offsetLeft;
    this.dy = event.y - this.el.nativeElement.offsetTop;
  }

You could achieve something similar by playing opacity games, but I suspect they might be Cross-Browser Trouble(tm).

To get the cursor to appear as something other than the disabled circle, you could set the moveEffect on itself.

...
<div class="drag"
        draggable="true"
        (dragstart)="onDragStart($event)"
        (dragend)="onDragEnd($event)"
        (drag)="onDrag($event)"
        (dragover)="ondragover($event)">
      drag
    </div>
...

onDragStart(event: MouseEvent) {
    ..
    event.dataTransfer.effectAllowed = 'move';
    ...
  }  

ondragover(mouseEv: MouseEvent){
    mouseEv.dataTransfer.effectAllowed = 'move';
    mouseEv.preventDefault();
  }

Here's a plunker demo: http://plnkr.co/edit/cGKcjxJGUKlWOC9GFyaJ?p=preview

Upvotes: 1

Related Questions