Show Guides and do snapping while dragging jquery draggable divs

Viewed 420

If there are multiple jquery draggable divs I want to see guides and snap to guides, edges and corners of others divs.

Here's the code:

$(".draggable").draggable();
$(".draggable").resizable();
body {
  font-family: courier new, courier;
  font-size: 12px;
}

.draggable {
  border: 1px solid #ccc;
  width: 100px;
  height: 80px;
  cursor: move;
  position: relative;
}

.guide {
  display: none;
  position: absolute;
  left: 0;
  top: 0;
}

#guide-h {
  border-top: 1px dashed #55f;
  width: 100%;
}

#guide-v {
  border-left: 1px dashed #55f;
  height: 100%;
}

#image{
  height: 150px;
  width: 200px;
}
img{
  width: 100%;
  height: 100%;
}
#image_h {
  position: absolute;
  color: white;
  top: 0;
  left: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<link rel="stylesheet" type="text/css" href="http://code.jquery.com/ui/1.9.2/themes/base/jquery-ui.css"/>


<div class="draggable">drag me!</div>
<div class="draggable">you can drag me too, if you like</div>
<div class="draggable">hep hep</div>
<div class="draggable" id="image">
  <img src="https://cdn.pixabay.com/photo/2021/02/06/16/29/jay-5988657__340.jpg">
  <div id="image_h">
    Hello
  </div>
</div>
<div id="guide-h" class="guide"></div>
<div id="guide-v" class="guide"></div>

The blue line in following image is what i want to be shown while divs are being dragged see image here. Divs should snap to the blue guiding lines when divs are aligned.

don't change the relative and absolute position of classes as I've used them to overlay one div on another.

I tried searching online but solutions are too old, awakward and work with jquery 2.x Please help!

1 Answers

To address the first part of your question, you can manage the guides like so.

$(function() {
  function moveGuides(top, left) {
    $("#guide-h").css("top", top + "px");
    $("#guide-v").css("left", left + "px");
  }

  function getMyCorners(el) {
    var p = $(el).position();
    return {
      top: p.top,
      left: p.left,
      bottom: p.top + $(el).height(),
      right: p.left + $(el).width()
    };
  }

  function startGuides(targetEl) {
    var c = getMyCorners(targetEl);
    moveGuides(c.top, c.right);
    $(".guide").show();
  }

  function stopGuides() {
    $(".guide").hide();
  }

  $(".draggable").draggable({
    start: function(e, ui) {
      startGuides(this);
    },
    drag: function(e, ui) {
      var c = getMyCorners(this);
      moveGuides(c.top, c.right);
    },
    stop: stopGuides
  });
  $(".draggable").resizable({
    start: function(e, ui) {
      startGuides(this);
    },
    resize: function(e, ui) {
      var c = getMyCorners(this);
      moveGuides(c.top, c.right);
    },
    stop: stopGuides
  });
});
body {
  font-family: courier new, courier;
  font-size: 12px;
}

.draggable {
  border: 1px solid #ccc;
  width: 100px;
  height: 80px;
  cursor: move;
  position: relative;
}

.guide {
  display: none;
  position: absolute;
  left: 0;
  top: 0;
}

#guide-h {
  border-top: 1px dashed #55f;
  width: 100%;
}

#guide-v {
  border-left: 1px dashed #55f;
  height: 100%;
}

#image {
  height: 150px;
  width: 200px;
}

img {
  width: 100%;
  height: 100%;
}

#image_h {
  position: absolute;
  color: white;
  top: 0;
  left: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<link rel="stylesheet" type="text/css" href="http://code.jquery.com/ui/1.9.2/themes/base/jquery-ui.css" />


<div class="draggable">drag me!</div>
<div class="draggable">you can drag me too, if you like</div>
<div class="draggable">hep hep</div>
<div class="draggable" id="image">
  <img src="https://cdn.pixabay.com/photo/2021/02/06/16/29/jay-5988657__340.jpg">
  <div id="image_h">
    Hello
  </div>
</div>
<div id="guide-h" class="guide"></div>
<div id="guide-v" class="guide"></div>

With helper functions, you can reveal the guides, and move them based on specific events.

The next, and much more involved portion, would be to create collision detection for the various elements. This will require checking against each of the elements involved against all the other elements. For example:

if($("#guide-h").position().top == $(".draggable").position().top){
  // Stop event
}

I am guessing that you are looking to create alignment. So when a Guide collides with an edge, it should prevent the User from dragging or resizing the element further in that direction. Also, do you want it to Snap and what tolerance should that snap be?

Since you did not provide those details, I am not really able to address your second question in full.

Related