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

javascript - How to keep a draggable element from being moved outside a boundary? - Stack Overflow

programmeradmin2浏览0评论

I've made a draggable element by using code that works in more or less the same way as this example from w3Schools:

//Make the DIV element draggagle:
dragElement(document.getElementById(("mydiv")));

function dragElement(elmnt) {
  var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
  if (document.getElementById(elmnt.id + "header")) {
    /* if present, the header is where you move the DIV from:*/
    document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
  } else {
    /* otherwise, move the DIV from anywhere inside the DIV:*/
    elmnt.onmousedown = dragMouseDown;
  }

  function dragMouseDown(e) {
    e = e || window.event;
    // get the mouse cursor position at startup:
    pos3 = e.clientX;
    pos4 = e.clientY;
    document.onmouseup = closeDragElement;
    // call a function whenever the cursor moves:
    document.onmousemove = elementDrag;
  }

  function elementDrag(e) {
    e = e || window.event;
    // calculate the new cursor position:
    pos1 = pos3 - e.clientX;
    pos2 = pos4 - e.clientY;
    pos3 = e.clientX;
    pos4 = e.clientY;
    // set the element's new position:
    elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
    elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
  }

  function closeDragElement() {
    /* stop moving when mouse button is released:*/
    document.onmouseup = null;
    document.onmousemove = null;
  }
}

The problem is I need the element to be restricted to inside the viewport plus a small bit of padding. I've got somewhat of a solution where you just check if the elements position is less than 0 and if it is set it back to 0 or if it's greater than the width/height set it to the width/height. This isn't good enough though as it creates a kind of janky bounce effect which I don't want.

So I'm wondering if there's a more obvious solution to this problem? Without using jQuery as well.

I've made a draggable element by using code that works in more or less the same way as this example from w3Schools:

//Make the DIV element draggagle:
dragElement(document.getElementById(("mydiv")));

function dragElement(elmnt) {
  var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
  if (document.getElementById(elmnt.id + "header")) {
    /* if present, the header is where you move the DIV from:*/
    document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
  } else {
    /* otherwise, move the DIV from anywhere inside the DIV:*/
    elmnt.onmousedown = dragMouseDown;
  }

  function dragMouseDown(e) {
    e = e || window.event;
    // get the mouse cursor position at startup:
    pos3 = e.clientX;
    pos4 = e.clientY;
    document.onmouseup = closeDragElement;
    // call a function whenever the cursor moves:
    document.onmousemove = elementDrag;
  }

  function elementDrag(e) {
    e = e || window.event;
    // calculate the new cursor position:
    pos1 = pos3 - e.clientX;
    pos2 = pos4 - e.clientY;
    pos3 = e.clientX;
    pos4 = e.clientY;
    // set the element's new position:
    elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
    elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
  }

  function closeDragElement() {
    /* stop moving when mouse button is released:*/
    document.onmouseup = null;
    document.onmousemove = null;
  }
}

The problem is I need the element to be restricted to inside the viewport plus a small bit of padding. I've got somewhat of a solution where you just check if the elements position is less than 0 and if it is set it back to 0 or if it's greater than the width/height set it to the width/height. This isn't good enough though as it creates a kind of janky bounce effect which I don't want.

So I'm wondering if there's a more obvious solution to this problem? Without using jQuery as well.

Share Improve this question asked Jan 4, 2018 at 14:51 NeedsHelpNeedsHelp 4371 gold badge7 silver badges25 bronze badges 3
  • the exemple is not working when i try it in a snippet here or a fiddle (the div is actually not draggable - no errors in console) – Kaddath Commented Jan 4, 2018 at 15:07
  • @Kaddath w3schools./howto/tryit.asp?filename=tryhow_js_draggable – NeedsHelp Commented Jan 4, 2018 at 15:08
  • Thanks, consider adding the styles or the link to the question itself. I just can give you a hint but i don't have the full solution. You can test value before moving your div: if(elmnt.offsetLeft - pos1 >= 0){ elmnt.style.left = (elmnt.offsetLeft - pos1) + "px"; }, this example prevents from going out at the left. But as you'll notice, it causes the text to be selected, and i have no already made solution to that.. – Kaddath Commented Jan 4, 2018 at 15:19
Add a ment  | 

1 Answer 1

Reset to default 8

You need to keep track of the available viewport (a window resize may change it) and make sure the element won't cross the boundary. If the element will cross the boundary, you should do nothing rather than letting it cross and then setting it back. Below is a working example.

Note well that the code example from w3schools is very outdated in its style and feature usage - there are more elegant ways to support dragging in modern HTML.

var PADDING = 8;

var rect;
var viewport = {
  bottom: 0,
  left: 0,
  right: 0,
  top: 0
}

//Make the DIV element draggagle:
dragElement(document.getElementById(("mydiv")));

function dragElement(elmnt) {
  var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
  if (document.getElementById(elmnt.id + "header")) {
    /* if present, the header is where you move the DIV from:*/
    document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
  } else {
    /* otherwise, move the DIV from anywhere inside the DIV:*/
    elmnt.onmousedown = dragMouseDown;
  }

  function dragMouseDown(e) {
    e = e || window.event;
    // get the mouse cursor position at startup:
    pos3 = e.clientX;
    pos4 = e.clientY;
    
    // store the current viewport and element dimensions when a drag starts
    rect = elmnt.getBoundingClientRect();
    viewport.bottom = window.innerHeight - PADDING;
    viewport.left = PADDING;
    viewport.right = window.innerWidth - PADDING;
    viewport.top = PADDING;
    
    document.onmouseup = closeDragElement;
    // call a function whenever the cursor moves:
    document.onmousemove = elementDrag;
  }

  function elementDrag(e) {
    e = e || window.event;
    // calculate the new cursor position:
    pos1 = pos3 - e.clientX;
    pos2 = pos4 - e.clientY;
    pos3 = e.clientX;
    pos4 = e.clientY;
    
    // check to make sure the element will be within our viewport boundary
    var newLeft = elmnt.offsetLeft - pos1;
    var newTop = elmnt.offsetTop - pos2;

    if (newLeft < viewport.left
        || newTop < viewport.top
        || newLeft + rect.width > viewport.right
        || newTop + rect.height > viewport.bottom
    ) {
    	// the element will hit the boundary, do nothing...
    } else {
      // set the element's new position:
      elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
      elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
    }
  }

  function closeDragElement() {
    /* stop moving when mouse button is released:*/
    document.onmouseup = null;
    document.onmousemove = null;
  }
}
#mydiv {
  border: 1px solid black;
  height: 100px;
  left: 8px;
  position: absolute;
  top: 8px;
  width: 100px;
}
<div id="mydiv"></div>

发布评论

评论列表(0)

  1. 暂无评论