DEV Community

Cover image for Draggable elements between two lists
angelina-white
angelina-white

Posted on

Draggable elements between two lists

This is for a basic dragging and dropping capability in between two set spots.

Helpful resources

This is the documentation for GSAP draggable, which is what I used. I also watched this Youtube tutorial by Wael Yasmina that was helpful in getting an idea for what you're able to do with this function.

Image description
I found this CodePen by Steve Wojcik and worked from there. I wanted to get familiar with the basics so I removed a lot of extra features that was in it like dropShadow, dragGroup, and highlight. I tested each section to see if it would effect the main drag and drop function, and if it didn't, I just removed it. This also helped get an idea for what different parts do.

Imports

I used these scripts:
//cdnjs.cloudflare.com/ajax/libs/gsap/1.17.0/utils/Draggable.min.js
//cdnjs.cloudflare.com/ajax/libs/gsap/1.19.1/TweenMax.min.js
//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js

HTML

<div id="container" class="container">
  <h1 id="list1">List 1</h1>
  <h1 id="list2">List 2</h1>

  <div id="dropArea"></div>
  <div id="dropArea2"></div>
  <div id="dropArea3"></div>

  <div class="first">
    <h3>1</h3>
  </div>
  <div class="second">
    <h3>2</h3>
  </div>
  <div class="third">
    <h3>3</h3>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode
  • container: the boundary

  • lists: just the titles and will not be used

  • drop areas: where the boxes will drop under list 2

  • first/second/third: the draggable boxes

CSS

.container
{
  position: absolute;
  margin: auto;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 400px;
  height: 330px;
  border-radius: 3px;
  border-style: solid;
  border-color: #fed3c1;
  border-width: 2px;
}

#list1 {
  margin-left: 100px;
  position: relative;
  margin-top: 35px;
}

#list2 {
  margin-left: 230px;
  position: absolute;
  margin-top: -58px;
}

.first
{
  position: absolute;
  top: 0px;
  left: 0px;
  width: 50px;
  height: 50px;
  background-color: pink;
  top: 100px;
  left: 106px;
  text-align: center;
}

#dropArea
{
  position: absolute;
  top: 100px;
  left: 242px;
  width: 50px;
  height: 50px;
}

.second
{
  position: absolute;
  top: 0px;
  left: 0px;
  width: 50px;
  height: 50px;
  background-color: pink;
  top: 175px;
  left: 105px;
  text-align: center;
}

#dropArea2
{
  position: absolute;
  top: 175px;
  left: 242px;
  width: 50px;
  height: 50px;
}

.third
{
  position: absolute;
  top: 0px;
  left: 0px;
  width: 50px;
  height: 50px;
  background-color: pink;
  top: 250px;
  left: 105px;
  text-align: center;
}

#dropArea3
{
  position: absolute;
  top: 250px;
  left: 242px;
  width: 50px;
  height: 50px;
}
Enter fullscreen mode Exit fullscreen mode

I added background colors to everything while I was working with it so I could see exactly where everything was. I pretty much kept everything in the same place except when adding a new box, I made the start and finish lower.

Javascript

var dropArea = "#dropArea";
var overlapThreshold = "60%";

Draggable.create(".first", 
{
  bounds: "#container",
  onDrag: function(e) 
  {
      TweenLite.to(".first", 0.2, 
      {
        scaleX:1.10,
        scaleY:1.10
      });
  },
  onDragEnd: function(e) 
  {
    if (this.hitTest(dropArea, overlapThreshold)) 
    {
      TweenLite.to(this.target, 0.2, 
      {
        x: 136,
        y: 0,
        scaleX:1,
        scaleY:1
      });
    } 
    else 
    {
      TweenLite.to(this.target, 0.2, 
      {
        x: 0,
        y: 0,
        scaleX:1,
        scaleY:1
      });
    }
  }
});


var dropArea2 = "#dropArea2";
var overlapThreshold = "60%";

Draggable.create(".second", 
{
  bounds: "#container",
  onDrag: function(e) 
  {
      TweenLite.to(".second", 0.2, 
      {
        scaleX:1.10,
        scaleY:1.10
      });
  },
  onDragEnd: function(e) 
  {
    if (this.hitTest(dropArea2, overlapThreshold)) 
    {
      TweenLite.to(this.target, 0.2, 
      {
        x: 136,
        y: 0,
        scaleX:1,
        scaleY:1
      });
    } 
    else 
    {
      TweenLite.to(this.target, 0.2, 
      {
        x: 0,
        y: 0,
        scaleX:1,
        scaleY:1
      });
    }
  }
});


var dropArea3 = "#dropArea3";
var overlapThreshold = "60%";

Draggable.create(".third", 
{
  bounds: "#container",
  onDrag: function(e) 
  {
      TweenLite.to(".third", 0.2, 
      {
        scaleX:1.10,
        scaleY:1.10
      });
  },
  onDragEnd: function(e) 
  {
    if (this.hitTest(dropArea3, overlapThreshold)) 
    {
      TweenLite.to(this.target, 0.2, 
      {
        x: 136,
        y: 0,
        scaleX:1,
        scaleY:1
      });
    } 
    else 
    {
      TweenLite.to(this.target, 0.2, 
      {
        x: 0,
        y: 0,
        scaleX:1,
        scaleY:1
      });
    }
  }
});
Enter fullscreen mode Exit fullscreen mode

This has the same code base three times, one for each box. I just changed the variable names to reflect where the box should land.

  • bound: this is where you put the container you want to keep your draggable item in
  • onDrag: when the box is being dragged, it will look slightly bigger
  • onDragEnd: If the box is placed in the dropArea, it will stay there, else, it will go back to its original position under List 1

Top comments (0)