modernator modernator - 11 months ago 57
Javascript Question

Draggable div with jQuery, how to apply clicked offset of element?

Title might be little confuse, I'll explain. I made a draggable div with jQuery(not jQuery UI's draggable). This is the code:

let target = null;

this.el.on('mousedown', (ev) => {
target = this.el;
}).on('mouseup', (ev) => {
target = null;

$(document.body).on('mousemove', 'div', (ev) => {
if(target) {
this.x = ev.pageX;
this.y = ev.pageY;

this.update(); // update css

code is quite simple, and it works well. The problem is when I dragging from the center or wherever, not left top, element always following cursor's coordination, so always left top of the element is placed where I dragged. Yes, it is correct, because that is what I did, but I want to move element from where I dragging.

It is hard to explain, so I'll give more easy one. If there is a box(div) in (0,0) and it has 5x5 size, and move the box by clicking (0,0) to (10,10), it's destination should be (10,10). But if I move the box by dragging (2.5,2.5) to (10,10), destination must be (12.5,12.5), not (10,10).

But in my code, destination is (10,10), not (12.5,12.5) because offset from the clicking point is not applied in translation.

If you still don't understand what is my problem, please see jquery-ui's draggable example. That is what I want to make exactly.

I know what is the problem, but all of my tried won't work, so I need little help here. Any advice will be very appreciated!

Example is here!

Answer Source

Just include the offsetX and offsetY values from the mousedown event into your calculation, by subtracting it from the pageX and pageY in the mousemove handler.

$(document).ready(function() {
  function DraggableElement() {
    this.x = 0;
    this.y = 0;
    this.width = 100;
    this.height = 100;

    this.el = $('<div></div>')


    var self = this;
    var target = null;
    var offsetX = 0;
    var offsetY = 0;

    this.el.on('mousedown', function(ev) {
      offsetX = ev.offsetX;
      offsetY = ev.offsetY;
      target = self.el;
    }).on('mouseup', function() {
      target = null;

    $(document.body).on('mousemove', 'div', function(ev) {
      if(target) {
        self.x = ev.pageX - offsetX;
        self.y = ev.pageY - offsetY;
  DraggableElement.prototype.update = function() {
      top: this.y + 'px',
      left: this.x + 'px',
      width: this.width + 'px',
      height: this.height + 'px'

  var el = new DraggableElement();
* {
  padding: 0;
  margin: 0;
#playground {
  background-color: #eee;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
.box {
  position: absolute;
  background-color: red;
  cursor: pointer;
<script src=""></script>
<div id="playground"></div>