JSFiddle - React, Tailwind, and code Playground

by Glenn Reed

HTML

<!doctype html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <title>Drag and Drop Practice </title>
  <meta name="description" content="A simple HTML5 Template for new projects.">
  <meta name="author" content="KiwiHeretic">

  <meta property="og:title" content="A Basic HTML5 Template">
  <meta property="og:type" content="website">
  <meta property="og:url" content="https://www.sitepoint.com/a-basic-html5-template/">
  <meta property="og:description" content="A simple HTML5 Template for new projects.">
  <meta property="og:image" content="image.png">

  <link rel="icon" href="/favicon.ico">
  <link rel="icon" href="/favicon.svg" type="image/svg+xml">
  <link rel="apple-touch-icon" href="/apple-touch-icon.png">

  <link rel="stylesheet" href="css/styles.css?v=1.0">

</head>

<body>
  <!-- your content here... -->
  <h1>Learning to do drag and drop in javascript</h1>
  <div class="container">
    <div class="left-region">
      <div class="canvas">
        <canvas id="universe">
        </canvas>
      </div>
      <div id="object-block-2" class="objects">
        <div class="box">
          <span class="object" draggable="true">O</span>
          <!--
          <img src="asteroid.png" draggable="true" alt="asteroid">
          -->
        </div>
      
      </div>
    </div>
    </div>
  </div>
  <script src="js/canvas-utils.js"></script>
  <script>
    document.onreadystatechange = function () {
       if (document.readyState === "complete") {
         var dragged;
         var universe = new Universe(document.querySelector("canvas#universe"));
         
         //var imgs = document.querySelectorAll("img[draggable='true']");
         var imgs = document.querySelectorAll("div.box span.object");
         imgs.forEach( function (elmt) {
           var obj = new DraggableObject(elmt);
           universe.add(obj);
         });
       }
    }

 ...

CSS

h1 {
  text-align: center;
}

canvas {
  border: 1px solid grey;
  width: 600px;
  background-color: black;
}

div.container {
  display: flex;
  gap: 20px;
  margin: 20px
}

div.objects {
  margin: 10px 0;
}

div.objects div.box {
  border:3px dashed grey;
  width: 60px;
  background-color: black;
}

div.box span.object {
  color: white;
  font-size: 32px;
}

div.objects div.box img {
  width: 50px;
}
div#mouse-values {
  margin: 20px;
}

div#mouse-values input {
  width: 50px;
}

polygon.arrow {
  fill:#0a0;
  stroke:purple;
  stroke-width:2;
}
polygon.arrow:hover {
  fill: yellow;
}

JavaScript

class DraggableObject {
  constructor(object) {
    this.universe = null;
    this.element = object;
    this.element.addEventListener('dragstart', this.onDragStart.bind(this));
  }
  onDragStart(event) {
    console.log("Drag start");
    if (this.universe) {
      this.universe.dragged = this;
      console.log(this);
    }
  }
}


class Universe {
  constructor(canvas) {
    this.canvas = canvas;
    this.dragged = null;
    this.objects = [];
    this.canvas.addEventListener( 'dragenter', elmt => { elmt.preventDefault(); console.log('drag enter'); } );
    this.canvas.addEventListener( 'dragover', elmt => elmt.preventDefault() );
    this.canvas.addEventListener( 'drop', function(evt) {
      console.log(evt);
      this.evt = evt;
      this.objects.forEach( function(e) {
        if (e == this.dragged ) {
          console.log(e.element);
          var ctx = this.canvas.getContext("2d");
          ctx.strokeStyle = "#FFFFFF";
          ctx.lineWidth = 1;
          ctx.beginPath();
          ctx.arc(this.evt.offsetX, this.evt.offsetY, 5, 0, 2 * Math.PI);
          ctx.stroke();
        }
      }.bind(this));
    }.bind(this) );
  }
  add(obj) {
    this.objects.push(obj);
    obj.universe = this;
  }
}