Skip to content Skip to sidebar Skip to footer

Custom Cursor With Drag And Drop An Html Element Without Libraries

I have an HTML page which has some draggable elements. Our specs say that hovering mouse on such element the cursor must be grab , and during drag cursor must be grabbing . I know

Solution 1:

It seems that browsers don't allow changing the cursor at the beginning of a drag & drop operation. I don't know why but it's a known issue, I believe they will in the future.

If jQuery is not an option, a possible way around is to implement a drag & drop from scratch, using mouse events and cloning the source element:

var onDragStart = function (event) {
  event.preventDefault();
  var clone = event.target.cloneNode(true);
  clone.classList.add("dragging");
  event.target.parentNode.appendChild(clone);
  var style = getComputedStyle(clone);
  clone.drag = {
    x: (event.pageX||(event.clientX+document.body.scrollLeft)) - clone.offsetLeft + parseInt(style.marginLeft),
    y: (event.pageY||(event.clientY+document.body.scrollTop)) - clone.offsetTop + parseInt(style.marginTop),
    source: event.target
  };
};

var onDragMove = function (event) {
  if (!event.target.drag) {return;}
  event.target.style.left = ((event.pageX||(event.clientX+document.body.scrollLeft)) - event.target.drag.x) + "px";
  event.target.style.top = ((event.pageY||(event.clientY+document.body.scrollTop)) - event.target.drag.y) + "px";
};

var onDragEnd = function (event) {
  if (!event.target.drag) {return;}
  // Define persist true to let the source persist and drop the target, otherwise persist the target.var persist = true;
  if (persist || event.out) {
    event.target.parentNode.removeChild(event.target);
  } else {
    event.target.parentNode.removeChild(event.target.drag.source);
  }
  event.target.classList.remove("dragging");
  event.target.drag = null;
};

var onDragOver = function (event) {
  event.preventDefault();
};
.dropzone {
  width: 500px;
  height: 200px;
  background-color: silver;
}

.block {
  position: absolute;
  background-color: pink;
  margin: 10px;
  border: 20px solid pink;
}

.draggable {
  position: absolute;
  cursor: pointer; /* IE */cursor: -webkit-grab;
  cursor: grab;
}

.dragging {
  cursor: -webkit-grabbing;
  cursor: grabbing;
  background-color: red;
}
<divclass="dropzone"onmouseover="onDragOver(event);">
  Grab and drag block around
  <divclass    = "draggable block"onmousedown = "onDragStart(event);"onmousemove = "onDragMove(event);"onmouseup   = "onDragEnd(event);"onmouseout  = "event.out = true; onDragEnd(event);"
  >
    I'm draggable
  </div></div>

Solution 2:

It is a known issue reported here

While dragging, the cursor will automatically changed to normal.

My tries gave me the following. Gave an active on the element with grabbing cursor. While it is active, the cursor will change but once you start the drag, it will change automatically.

I tried to set body cursor to grabbing on dragstart but no result. Even it is not working.

var onDragStart = function(event) {
    event.dataTransfer.setData("Text", event.target.id);
    event.currentTarget.classList.add("being-dragged");
};

var onDragEnd = function(event) {
    event.currentTarget.classList.remove("being-dragged");
};

var onDragOver = function(event) {
    event.preventDefault();
};
.dropzone {
    width: 500px;
    height: 200px;
    background-color: silver;
}

.block {
    position: absolute;
    background-color: pink;
    margin: 10px;
    border: 20px solid pink;
}

.draggable {
    cursor: -webkit-grab;
    cursor: grab;
}

.draggable:active{
    cursor : -moz-grabbing;
    cursor: -webkit-grabbing;
    cursor: grabbing;
}
.being-dragged{
    background-color: red;
    cursor : -moz-grabbing;
    cursor: -webkit-grabbing;
    cursor: grabbing;
}
<divclass      = "dropzone"ondragover  = "onDragOver(event);"
    >
    Grab and drag block around
    <divclass      = "draggable block"draggable   = "true"ondragstart = "onDragStart(event);"ondragend   = "onDragEnd(event);"
        >
        I'm draggable
    </div></div>

Solution 3:

I went through a lot of pain trying to figure this out. The accepted answer was the best answer on the web, but best practices now would be to use the element's .setPointerCapture event, which allows you to listen to and act upon drag like behaviors on an element without being boxed into the narrow behavior of the Drag API. One way to do it would be like so:

el.onpointerdown = ev => {
    el.onpointermove = pointerMove 
    el.setPointerCapture(ev.pointerId)
}

pointerMove = ev => {
    console.log('Dragged!')
}

el.onpointerup = ev => {
    el.onpointermove = null
    el.releasePointerCapture(ev.pointerId)
}

The obvious gift being the fact that there is no cursor hijacking to be found sneaking in the backdoor here.

Solution 4:

I know just a little bit about draggable elements with pure JavaScript and I'm sorry that I can't explain the following. The problem was that the onDragEnd never get fired so I've searched something and find this example with draggable elements. Now, if you change the function of the onDragStart event it will work but I think you have to change the cursor in another way like to change the class of the body onDragStart

var onDragStart = function(event) {
  event.dataTransfer.setData("Text", event.target.id);
  event.currentTarget.classList.add("being-dragged");
};

All in one

var onDragStart = function(event) {
  event.dataTransfer.setData("Text", event.target.id);
  event.currentTarget.classList.add("being-dragged");
};
var onDragEnd = function(event) {
  event.currentTarget.classList.remove("being-dragged");
};
var onDragOver = function(event) {
  event.preventDefault();
};
.dropzone {
  width: 500px;
  height: 500px;
  background-color: silver;
}
.block {
  width: 200px;
  height: 50px;
  background-color: pink;
}
.draggable1 {
  cursor: -webkit-grab;
  cursor: grab;
}
.being-dragged {
  cursor: -webkit-grabbing;
  cursor: grabbing;
  background-color: red;
}
<divclass="dropzone"ondragover="onDragOver(event);"><divclass="draggable1 block"draggable="true"ondragstart="onDragStart(event);"ondragend="onDragEnd(event);">
    I'm draggable
  </div></div>

Solution 5:

Try this ! It works for me !

.draggable {
    cursor: -webkit-grab;
    cursor: grab;
}

.draggable:active {
    cursor: -webkit-grabbing;
    cursor: grabbing;
}

Post a Comment for "Custom Cursor With Drag And Drop An Html Element Without Libraries"