最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

pure javascript draggable element - Stack Overflow

programmeradmin0浏览0评论

I know there're example of doing this on the web but every example is different and so is my own implementation. I'm trying to figure what's wrong with my implementation since it doesn't work as expected.

code snippet:

var mousePressX = -1;
var mousePressY = -1;

document.getElementById("contextMenu").addEventListener("mousedown", function(event) {
    mousePressX = event.clientX;
    mousePressY = event.clientY;
}, false);

document.getElementById("contextMenu").addEventListener("mouseup", function(event) {
    mousePressX = -1;
    mousePressY = -1;
}, false);

document.getElementById("contextMenu").addEventListener("mousemove", function(event) {
    if (mousePressX != -1 && mousePressY != -1) {
        repositionElement(event.target, event.clientX, event.clientY);
    }
}, false);

function repositionElement(element, currentMouseX, currentMouseY) {
    element.style.left = element.offsetLeft + (currentMouseX - mousePressX) + 'px';
    element.style.top = element.offsetTop + (currentMouseY - mousePressY) + 'px';
}

jsfiddle : /

can't really figure out what's wrong but I've noticed that if I change the following lines:

element.style.left = element.offsetLeft + (currentMouseX - mousePressX) + 'px';
element.style.top = element.offsetTop + (currentMouseY - mousePressY) + 'px';

to :

element.style.left = currentMouseX - mousePressX + 'px';
element.style.top = currentMouseY - mousePressY + 'px';

The element will be properly dragged only when it's being dragged towards the positive x-axis (to the right) and towards the positive y-axis (to the bottom) and when mouseup is triggered it'll be positioned in somewhere near the left-most top-most corner area (around 0,0)

I know there're example of doing this on the web but every example is different and so is my own implementation. I'm trying to figure what's wrong with my implementation since it doesn't work as expected.

code snippet:

var mousePressX = -1;
var mousePressY = -1;

document.getElementById("contextMenu").addEventListener("mousedown", function(event) {
    mousePressX = event.clientX;
    mousePressY = event.clientY;
}, false);

document.getElementById("contextMenu").addEventListener("mouseup", function(event) {
    mousePressX = -1;
    mousePressY = -1;
}, false);

document.getElementById("contextMenu").addEventListener("mousemove", function(event) {
    if (mousePressX != -1 && mousePressY != -1) {
        repositionElement(event.target, event.clientX, event.clientY);
    }
}, false);

function repositionElement(element, currentMouseX, currentMouseY) {
    element.style.left = element.offsetLeft + (currentMouseX - mousePressX) + 'px';
    element.style.top = element.offsetTop + (currentMouseY - mousePressY) + 'px';
}

jsfiddle : http://jsfiddle.net/4rLctko8/

can't really figure out what's wrong but I've noticed that if I change the following lines:

element.style.left = element.offsetLeft + (currentMouseX - mousePressX) + 'px';
element.style.top = element.offsetTop + (currentMouseY - mousePressY) + 'px';

to :

element.style.left = currentMouseX - mousePressX + 'px';
element.style.top = currentMouseY - mousePressY + 'px';

The element will be properly dragged only when it's being dragged towards the positive x-axis (to the right) and towards the positive y-axis (to the bottom) and when mouseup is triggered it'll be positioned in somewhere near the left-most top-most corner area (around 0,0)

Share Improve this question asked Apr 17, 2015 at 15:30 dikson231dikson231 2015 silver badges10 bronze badges 0
Add a comment  | 

2 Answers 2

Reset to default 19

Quite interesting, had so far only done it with jQuery. Rewrote it a bit and made sure that every mousemove has it's event listener removed afterwards - that would be a memory leak that you might start to notice otherwise :

http://jsfiddle.net/8wtq17L8/

var contextmenu = document.getElementById('contextMenu');
var initX, initY, mousePressX, mousePressY;

contextmenu.addEventListener('mousedown', function(event) {

    initX = this.offsetLeft;
    initY = this.offsetTop;
    mousePressX = event.clientX;
    mousePressY = event.clientY;

    this.addEventListener('mousemove', repositionElement, false);

    window.addEventListener('mouseup', function() {
      contextmenu.removeEventListener('mousemove', repositionElement, false);
    }, false);

}, false);

function repositionElement(event) {
    this.style.left = initX + event.clientX - mousePressX + 'px';
    this.style.top = initY + event.clientY - mousePressY + 'px';
}

Seems to be working well. :-)

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Edit - thought I'd add a version with touch support too (although newer devices seem to emulate mouse events). Not like Jquery where you can select multiple event listeners so it's mostly a repetition, just with touch events :

http://codepen.io/Shikkediel/pen/VLZKor?editors=011

var object = document.getElementById('element'),
initX, initY, firstX, firstY;

object.addEventListener('mousedown', function(e) {

    e.preventDefault();
    initX = this.offsetLeft;
    initY = this.offsetTop;
    firstX = e.pageX;
    firstY = e.pageY;

    this.addEventListener('mousemove', dragIt, false);

    window.addEventListener('mouseup', function() {
        object.removeEventListener('mousemove', dragIt, false);
    }, false);

}, false);

object.addEventListener('touchstart', function(e) {

    e.preventDefault();
    initX = this.offsetLeft;
    initY = this.offsetTop;
    var touch = e.touches;
    firstX = touch[0].pageX;
    firstY = touch[0].pageY;

    this.addEventListener('touchmove', swipeIt, false);

    window.addEventListener('touchend', function(e) {
        e.preventDefault();
        object.removeEventListener('touchmove', swipeIt, false);
    }, false);

}, false);

function dragIt(e) {
    this.style.left = initX+e.pageX-firstX + 'px';
    this.style.top = initY+e.pageY-firstY + 'px';
}

function swipeIt(e) {
    var contact = e.touches;
    this.style.left = initX+contact[0].pageX-firstX + 'px';
    this.style.top = initY+contact[0].pageY-firstY + 'px';
}

Extending upon @Shikkediel answer, my version is here

Basically, I switched to an absolute positioned div and simply got the offset x, y and added them to the initial x - y of the dragged element. The absolute position also helps in case you have multiple divs inside a single container.

document.getElementById('dragHandle').addEventListener('mousedown', 
function(e) {

  e.preventDefault();
  originalY = e.clientY;
  originalX = e.clientX;
  elementY = object2.offsetTop;
  elementX = object2.offsetLeft;

  window.addEventListener('mousemove', dragIt, false);

  window.addEventListener('mouseup', function()
  {
      window.removeEventListener('mousemove', dragIt, false);
  }, false);

  }, false);

function dragIt(e)
{
  let deltaY = e.clientY - originalY;
  let deltaX = e.clientX - originalX;
  originalY = e.clientY;
  originalX = e.clientX;
  elementY += deltaY;
  elementX += deltaX;
  object2.style.top = elementY + "px";

  object2.style.left = Math.min(Math.max(container.getBoundingClientRect().left, elementX), container.getBoundingClientRect().right- object2.offsetWidth) + "px";
  object2.style.top = Math.min(Math.max(container.getBoundingClientRect().top, elementY), container.getBoundingClientRect().bottom - object2.offsetHeight) + "px";
}

I also included a drag handle and constrained the dragging to the parent #container.

发布评论

评论列表(0)

  1. 暂无评论