javascript use drag to move element
Asked Answered
O

3

10

How does one set the position of an element? When the user drags an element (an image), I'd like to have it move synchronously. I see that my "mousemove" handler is being called. However I cannot get the element to actually move.

Here's the mousemove handler (the element being dragged is "overlay"):

function handleMouseMove (event)
{
  var deltaX = event.movementX;
  var deltaY = event.movementY;

  var divOverlay = document.getElementById ("overlay");
  var rect = divOverlay.getBoundingClientRect();

  divOverlay.style.left = rect.x + deltaX;
  divOverlay.style.top = rect.y + deltaY;
}

Here's the html for "overlay":

<div id="overlay">
  ... some other stuff ...
  <img id="large" src="something.jpg" >
</div>

And the css:

#overlay {position:absolute; left:0; top:0}

It appears that the default drag action manifests, which is a shadow of "overlay" that moves with the mouse. But the element itself does not move.

Ogg answered 23/8, 2017 at 5:37 Comment(3)
It seems that the problem was solved in jquery.sortable. Just look how it works.Kylstra
Well, I'd appreciate an actual answer, if you are able. I looked at sortable but don't see anything that looks like assigning an element position - though I realize it must be infered someplace. Apologies, I'm not very familar with jquery.Ogg
for some reasons I don't consider SO as a code generator service.Kylstra
C
18

Not sure about your actual implementation. However this code works:

To do it using your code, here is the code. One obvious issue with your code is you need to add 'px' to your style.left and style.right. Also it is unknown how you actually handle the event from your code. Using this code, the element moves in a circle, you need to fix it but you get the idea.

var divOverlay = document.getElementById ("overlay");
var isDown = false;
divOverlay.addEventListener('mousedown', function(e) {
    isDown = true;
}, true);

document.addEventListener('mouseup', function() {
  isDown = false;
}, true);

document.addEventListener('mousemove', function(event) {
   event.preventDefault();
   if (isDown) {
   var deltaX = event.movementX;
   var deltaY = event.movementY;
  var rect = divOverlay.getBoundingClientRect();
  divOverlay.style.left = rect.x + deltaX + 'px';
  divOverlay.style.top  = rect.x + deltaX + 'px';
 }
}, true);

Below is another way of doing it. Codepen example

var offset = [0,0];
var divOverlay = document.getElementById ("overlay");
var isDown = false;

divOverlay.addEventListener('mousedown', function(e) {
isDown = true;
offset = [
    divOverlay.offsetLeft - e.clientX,
    divOverlay.offsetTop - e.clientY
 ];
}, true);

document.addEventListener('mouseup', function() {
   isDown = false;
}, true);

document.addEventListener('mousemove', function(e) {
    event.preventDefault();
    if (isDown) {
        divOverlay.style.left = (e.clientX + offset[0]) + 'px';
        divOverlay.style.top  = (e.clientY + offset[1]) + 'px';
   }
}, true);
Cutch answered 23/8, 2017 at 5:57 Comment(4)
Thanks. Adding 'px' made the difference. My code still doesn't work properly but at least the element now moves. I now realize that when updating or reading the DOM style fields, they should have the exact syntax defined as used in CSS. This is all new for me.Ogg
Can we add limit to 'px' that it should go higher than 500px or something from top and bottom when dragging?Sciuroid
caniuse.com/?search=movementX not work for ie11Wedgwood
In your first example you should use your DeltaY var.Fervidor
B
2

I did make something similar few weeks ago for Angular, see here. It might help you a bit.

Basically, I wanted to do something you're probably thinking of doing, but to use drag events you also need to drop the elements you're dragging (at least that's what I ended up searching). So if you just want to drag/move the elements you need to be able to set their position on the page using top, bottom and left, right styles. So you those elements must have the position fixed or absolute ideally.

Then you go for the core of this, which is to calculate vector your going to move the element with. Because mousemove event only dispatches the MouseEvent which get you an access to mouse coordinates, you can count up in what vector your mouse has moved and move the element by the same vector.

Basically what I did was (hope it's understandable in ES5):

var elementPosition = [0,0];
var mousePosition   = [0,0];
var element         = document.getElementById('yourElement');

var mainEH = function (event) {
    mousePosition = [event.clientX, event.clientY];
    document.addEventListener('mousemove', calcEH);
    document.addEventListener('mouseup', removeHandlers);
    document.addEventListener('contextmenu', removeHandlers);
};

var calcEH = function (event) {
    var vector      = [-mousePosition[0] + event.clientX, -mousePosition[1] + event.clientY];
    mousePosition   = [mousePosition[0] + vector[0], mousePosition[1] + vector[1]];
    elementPosition = [elementPosition[0] + vector[0], elementPosition[1] + vector[1]];
    updatePosition();
};

var removeHandlers = function () {
    document.removeEventListener('mousemove', calcEH);
    document.removeEventListener('mouseup', removeHandlers);
    document.removeEventListener('contextmenu', removeHandlers);
};

function updatePosition() {
    element.style.left = elementPosition[0] + "px";
    element.style.top  = elementPosition[1] + "px";
}

element.addEventListener('mousedown', mainEH, true);

I'm not sure if this exact code is working as I cannot test it now, but you can see here how I did this using angular. Hope it'll work just fine for you. At least you get the idea. Anyway, you might need to run some function that sets up initial position of the element for you.

UPDATE

I've just realized that it's not exactly what you're looking for. If I understood you correctly you want to move the whole element while dragging and dropping. However I will probably leave the answer here because the solution might be pretty much similar. I would probably do it by using the logic I posted before and to actually be able to move the element I would set it's position to absolute while mousemove event is fired, then on mouseup you can remove position absolute attribute.

Baker answered 23/8, 2017 at 6:16 Comment(0)
M
1

Is jQuery an option for you? It makes what you are doing really simple since the code already exists.

http://jqueryui.com/demos/draggable/

Demo : http://jsfiddle.net/wfbY8/4/

JavaScript Code

window.onload = addListeners;

function addListeners(){
    document.getElementById('dxy').addEventListener('mousedown', mouseDown, false);
    window.addEventListener('mouseup', mouseUp, false);

}

function mouseUp()
{
    window.removeEventListener('mousemove', divMove, true);
}

function mouseDown(e){
  window.addEventListener('mousemove', divMove, true);
}

function divMove(e){
    var div = document.getElementById('dxy');
  div.style.position = 'absolute';
  div.style.top = e.clientY + 'px';
  div.style.left = e.clientX + 'px';
}​
Mencius answered 23/8, 2017 at 5:45 Comment(2)
I don't see anything significantly different in what you posted versus my code. You, also, assign to div.style.top and div.style.left. Everything else is the same except for usig e.clientX instead of getBoundClientRect(). I doubt that is significant regarding the problem I'm encountering.Ogg
find many problem for example div.style.position and function mouseUp() and function mouseDown(e) , I will update the Jsfile to show the Demo Here jsfiddle.net/g6m5t8co/658Mencius

© 2022 - 2025 — McMap. All rights reserved.