jqueryjquery-uijquery-draggable

Center dragged object under the Cursor


I have created a fiddle here that you can play with: http://codepen.io/anon/pen/pvOKey

I want to center the dragged object vertically/horizontally to the cursor that means when I drag an object at its corners I want then that the object is centered under the cursor else the user experience is very bad dragging large objects.

I have googled for SO solutions and found some but they do not work.

I use the create function of a draggable to set the top/left position , but it does not work.

Anyone can help?

<div id="itemContainer1"> 
  <div class="item i2">2</div>
</div>

<div id="itemContainer2"> 
  <div class="item i4">4</div>
</div>


<!-- border-box => IE9+ -->
* {
  -webkit-box-sizing: border-box;
     -moz-box-sizing: border-box;
          box-sizing: border-box;
}

body, html { 
  padding:0;
  margin:0;
  height:100%; 
}

.start-dragging{
  transform: scale(0.25); /* Standard syntax */
  transition: transform .3s ease-out; 
}
.stop-dragging{
  transform: scale(1); /* Standard syntax */
  transition: transform .3s ease-out; 
}


.item{
  position:absolute; 
} 

#itemContainer1{
  background:green;
  height:100%; 
  position:relative; 
  right:50%;

}

#itemContainer2{
  background:blue;
  height:100%; 
  width:50%;
  position:relative; 
  left:50%;
  top:-100%;

}
.item.i2 {
  top:50%;
  left:50%;
   width: 44%; 
   height:44%;
   background:lightgreen;  
}

.align-vertical-colums {
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
}



$(document).ready(function () {
    $("#itemContainer1 > div").each(function (index, element) {

      $(element).addClass("stop-dragging"); 

      $(element).draggable({cursor: 'move', stack: ".item",helper: "original",
        create: function(e,x){
          $(this).draggable("option", "cursorAt", {
                 left: Math.floor(ui.helper.width() / 2),
                 top: Math.floor(ui.helper.height() / 2)
               }); 
        },

                            start: function() {

           // $(this).css({"z-index": 100000 }); // the highest z-index
            $(this).toggleClass( 'stop-dragging start-dragging');
          },
          drag: function() {
          },
          stop: function() {
           //  $(this).css("z-index", ''); // remove the z-index
              $(this).toggleClass( 'start-dragging stop-dragging');

          }
       });   

        $(element).addClass("align-vertical-colums");
    });

  $("#itemContainer1").droppable({       
        activeClass: "ui-state-hover",
        hoverClass: "ui-state-active",
        drop: function (event, ui) {
     var element = document.elementFromPoint(event.clientX, event.clientY);        

        }
    });
});

Solution

  • I think you're having a problem finding ui.helper, if you check the console you will see that message:

    Uncaught ReferenceError: ui is not defined
    

    I edited your code and used only width() and height() functions of JQuery, and it seems to work. Check it out on this CodePen

    Edited: Also you have to included the cursorAt option inside the drag callback, in order to update width() and height() in case of resizing window.

    drag: function(e,x){
        addCursorAtOption(this);
    }
    
    function addCursorAtOption(element){
        $(element).draggable("option", "cursorAt", {
          left: $(element).width()/2,
          top: $(element).height()/2
        }); 
      }
    

    For dealing with resizing screen problem, you could call the function addCursorAtOption on window resize callback, check this CodePen

    create: function(e,x){
        var self = this;
        $(window).resize(function() {
           addCursorAtOption(self);
        });
        addCursorAtOption(self);
    }