<h1>Draggable with "droppable" logic</h1>
<p>Drag the boxes around. We'll run <code>hitTest()</code> logic inside an <code>onDrag</code>, highlighting "droppable" elements but only when at least 50% of their surface area overlaps (you can change the <code>overlapThreshold</code> variable to whatever you want). Then, in an <code>onDragEnd</code>, we'll do the same and make any intersecting "droppable" elements flash. Read the comments in the code to find out how to test for the mouse/touch overlapping an element instead.</p>
<div id="container">
<div id="box1" class="box gradient-green">box1</div>
<div id="box2" class="box gradient-blue">box2</div>
<div id="box3" class="box gradient-red">box3</div>
</div>
body {
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
flex-direction: column;
}
h1 {
text-align: center;
}
body {
padding: 1rem;
}
#container {
position: relative;
display: flex;
align-items: center;
justify-content: space-around;
gap: 1rem;
margin-top: 2rem;
}
.box {
width: 200px;
height: 80px;
text-align: center;
line-height: 80px;
font-size: 20px;
color: var(--color-just-black);
border-radius: 10px;
}
.highlight {
outline: 4px dashed var(--color-surface-white);
width: 196px;
height: 76px;
line-height: 76px;
}
p {
width: 80vw;
}
//see https://www.greensock.com/draggable/ for more details.
var droppables = $(".box");
//the overlapThreshold can be a percentage ("50%", for example, would only trigger when 50% or more of the surface area of either element overlaps) or a number of pixels (20 would only trigger when 20 pixels or more overlap), or 0 will trigger when any part of the two elements overlap.
var overlapThreshold = "50%";
//we'll call onDrop() when a Draggable is dropped on top of one of the "droppables", and it'll make it "flash" (blink opacity). Obviously you can do whatever you want in this function.
function onDrop(dragged, dropped) {
gsap.fromTo(dropped, {opacity:1}, {duration: 0.1, opacity:0, repeat:3, yoyo:true});
}
Draggable.create(droppables, {
bounds:window,
onDrag: function(e) {
var i = droppables.length;
while (--i > -1) {
if (this.hitTest(droppables[i], overlapThreshold)) {
$(droppables[i]).addClass("highlight");
} else {
$(droppables[i]).removeClass("highlight");
}
/* ALTERNATE TEST: you can use the static Draggable.hitTest() method for even more flexibility, like passing in a mouse event to see if the mouse is overlapping with the element...
if (Draggable.hitTest(droppables[i], e) && droppables[i] !== this.target) {
$(droppables[i]).addClass("highlight");
} else {
$(droppables[i]).removeClass("highlight");
}
*/
}
},
onDragEnd:function(e) {
var i = droppables.length;
while (--i > -1) {
if (this.hitTest(droppables[i], overlapThreshold)) {
onDrop(this.target, droppables[i]);
}
}
}
});