Moving elements by dragging in Dart

Issue

I am trying to move an element using drag and drop. I want to be able to drag and element to a different location, and when I drop it, the element moves to the dropped location. Super basic, and nothing fancy. This is what I have so far:

html:

<input type='button' id='drag' class='draggable' value='drag me' draggable='true'>

Dart code:

Element drag = querySelector('.draggable');
drag.onDragEnd.listen((MouseEvent e) {
  drag.style.left = '${e.client.x}px';
  drag.style.top = '${e.client.y}px';
});

This doesn’t quite do what I want it to do. The element is slightly off from where I drop it. I see examples in javascript with appendChild, clone(), parentNode, but none of the examples that I have seen can be reproduced in Dart. What is the best way to accomplish this? I don’t want to use the DND package, since I am really trying to personally understand the concepts better.

Solution

index.html

<!doctype html>
<html>
  <head>
    <style>
      #dropzone {
        position: absolute;
        top: 50px;
        left: 50px;
        width: 300px;
        height: 150px;
        border: solid 1px lightgreen;
      }
      #dropzone.droptarget {
        background-color: lime;
      }
    </style>
  </head>
  <body>
    <input type='button' id='drag' class='draggable' value='drag me'
           draggable='true'>

    <div id="dropzone"></div>
    <script type="application/dart" src="index.dart"></script>
    <script src="packages/browser/dart.js"></script>
  </body>
</html>

index.dart

library _template.web;

import 'dart:html' as dom;
import 'dart:convert' show JSON;

main() async {
  dom.Element drag = dom.querySelector('.draggable');
  drag.onDragStart.listen((event) {
    final startPos = (event.target as dom.Element).getBoundingClientRect();
    final data = JSON.encode({
      'id': (event.target as dom.Element).id,
      'x': event.client.x - startPos.left,
      'y': event.client.y - startPos.top
    });
    event.dataTransfer.setData('text', data);
  });

  dom.Element dropTarget = dom.querySelector('#dropzone');
  dropTarget.onDragOver.listen((event) {
    event.preventDefault();
    dropTarget.classes.add('droptarget');
  });

  dropTarget.onDragLeave.listen((event) {
    event.preventDefault();
    dropTarget.classes.remove('droptarget');
  });

  dropTarget.onDrop.listen((event) {
    event.preventDefault();
    final data = JSON.decode(event.dataTransfer.getData('text'));
    final drag = dom.document.getElementById(data['id']);
    event.target.append(drag);
    drag.style
      ..position = 'absolute'
      ..left = '${event.offset.x - data['x']}px'
      ..top = '${event.offset.y - data['y']}px';
    dropTarget.classes.remove('droptarget');
  });
}

Answered By – Günter Zöchbauer

Answer Checked By – Cary Denson (FlutterFixes Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *