Implemented in my project support for drag & drop functionality for elements with a draggable class. Unfortunately, this implementation leads sowing sometimes strange: the element sometimes starts to “run away” from the cursor and “gets stuck” when moving the mouse.

 //window.onload = function() { let elements = document.querySelectorAll('.draggable'); elements.forEach(function(el) { let mover = false, x, y, posx, posy, first = true; document.onmousedown = function() { mover = true; }; document.onmouseup = function() { mover = false; first = true; }; el.onmousemove = function(e) { el.style.cursor = "move"; if (mover) { if (first) { x = e.offsetX; y = e.offsetY; first = false; } posx = e.pageX - x; posy = e.pageY - y; el.style.left = posx + 'px'; el.style.top = posy + 'px'; } } }); //} 
 html, body { height: 100%; margin: 0; padding: 0; overflow: hidden; } body { overflow: auto; /* добавить полосу прокрутки */ } header { height: 60px; background-color: white; } .wrap { display: inline-flex; flex-direction: row; flex-wrap: wrap; justify-content: space-between; align-content: stretch; align-items: flex-start; width: 100%; } .header-link { padding: 1.1em; } .header-h1 { padding-left: 1em; } #header-title { color: #1c5a7d; } .header-link>a { font-weight: 500; color: #888; } .header-link>a:hover { color: #444; } .header-menu-wrapper { display: inline-flex; flex-direction: row; flex-wrap: wrap; } header-h1 { width: 100%; text-align: right; font-size: 26px; float: right; } .botmaker-container { float: right; position: relative; width: 100%; height: 100%; overflow: hidden; } .botmaker-node { width: 100%; height: 100%; max-width: 230px; max-height: 130px; border: 1px solid #333; border-bottom-right-radius: 120px; border-top-right-radius: 120px; } .node-form-input { width: 100%; max-width: 170px; } .draggable { position: absolute; z-index: 1; top: 100px; } .botmaker { min-height: 1000px; } 
 <header> <div class="wrap"> <div id="header-title" class=""> <h1 class="header-h1">Visual bot maker</h1> </div> <div class="header-menu-wrapper"> <div class="wrapper-item header-link"> <a href="">DOCUMENTATION</a> </div> <div class="wrapper-item header-link"> <a href="">FORUM</a> </div> <div class="wrapper-item header-link"> <a href="">SUPPORT</a> </div> </div> </div> </header> <section class="botmaker-container dragscroll"> <div class="botmaker"> <div class="botmaker-node start-node draggable" style="cursor: move; left: 570px; top: 129px;"> <form action="" method="post" class="form-group"> <div class="node-form-input"> <label for="startNode">Phrase</label> <input type="text" class="form-control" id="startNode" placeholder="Start phrase"> <button type="submit" class="btn btn-primary node-submit">Ок</button> </div> </form> </div> </div> </section> 

These bugs sometimes can not be repeated, but they happen. Maybe this is not the best implementation and is the best example of drag & drop? or in my case, some kind of defect interferes?

  • running away from the cursor treats the alignment of the element in the center relative to the mouse. Here everything is painted. - Misha Saidov
  • @MishaSaidov centered on onmousedown event? - Evgeny Shalaev

1 answer 1

The thing is that el.onmousemove says that the block will be dragged only when the mouse is over it, but if you pull the mouse abruptly, the element will come out from under the mouse and you get these same lags.

This code tracks the position of the mouse relative to the parent of the draggable element and it does not matter whether it is under the mouse or not.

 let elements = document.querySelectorAll('.draggable'); elements.forEach(function(el) { let mover = false, x, y, posx, posy, first = true; el.onmousedown = function() { mover = true; }; el.onmouseup = function() { mover = false; first = true; }; el.parentNode.onmousemove = function(e) { el.style.cursor = "move"; if (mover) { if (first) { x = e.offsetX; y = e.offsetY; first = false; } posx = e.pageX - x; posy = e.pageY - y; el.style.left = posx + 'px'; el.style.top = posy + 'px'; } } }); 
  • I also did el.parentNode.onmouseup because your example did not work after you unzipped LKM without this line) - Evgeny Shalaev