使用纯javascript拖放并再次拖动
Posted
技术标签:
【中文标题】使用纯javascript拖放并再次拖动【英文标题】:Drag and drop and drag again using pure javascript 【发布时间】:2017-01-01 04:55:38 【问题描述】:我正在尝试从一列到另一列进行简单的拖放。我正在复制元素,以便右侧的列表可以在左侧有多个版本的元素。别担心,我在实际追加之前设置了唯一 ID。
但是,我也希望用户能够从盒子中拖出以删除相同的对象。但是一旦 DIV 被放置到位(即一旦它在第 2 列中),就不能再次拖动它。初始拖放工作正常。
我发现处理 jQuery ui 的解决方案。我正在构建一个 angularJS 应用程序,并且对使用完整的 jQuery 或任何其他插件不感兴趣。
救命!
示例代码:
<div id="column1">
<div class="dragme" draggable="true" ondragstart="drag(event)">Item1</div>
<div class="dragme" draggable="true" ondragstart="drag(event)">Item1</div>
</div>
<div id="column2" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<script>
function allowDrop(ev)
ev.preventDefault();
function drag(ev)
ev.dataTransfer.setData("text", ev.target.id);
function drop(ev)
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
var newEl = $(document.getElementById(data)).clone()[0];
newEl.id = newEl.id + (+new Date());
ev.target.appendChild(newEl);
</script>
更新
似乎不是拖放导致问题。任何动态添加的内容都不会拖动。我在控制台中对此进行了测试。
仅供参考...下面的代码在这里工作得很好,问题最终是我的拖放是在一个可拖动的容器中。
function allowDrop(ev)
ev.preventDefault();
function drag(ev)
ev.dataTransfer.setData("text", ev.target.id);
function drop(ev)
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
var origThing = document.getElementById(data);
var newThing = origThing.cloneNode(true);
ev.target.appendChild(newThing);
.thing
width: 100px;
height: 2em;
padding: 0.5em;
margin: 0.5em;
background: rgba(0,0,0,0.8);
color: white;
font-family: sans-serif;
.col
width: 130px;
height: 450px;
padding: 1em;
border: 1px solid;
border-radius: 5px;
position: relative;
float: left;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div class="col" id="col1">
<div class="thing" draggable="true" ondragstart="drag(event)" id="thing1">THING 1</div>
<div class="thing" draggable="true" ondragstart="drag(event)" id="thing2">THING 2</div>
<div class="thing" draggable="true" ondragstart="drag(event)" id="thing3">THING 3</div>
<div class="thing" draggable="true" ondragstart="drag(event)" id="thing4">THING 4</div>
</div>
<div class="col" id="col2" ondrop="drop(event)" ondragover="allowDrop(event)">
</div>
【问题讨论】:
在ondragstart
事件中多做一些事情,在ondragend
事件中少做其他事情。
请确认:您只想要一个仅用于 JS 的解决方案来使用鼠标拖动(和重新拖动)div ——仅此而已?如果是的话,我会用一些我已经闲逛的代码发布答案。
是的,马克。那是我最大的问题......我找不到任何 JS 唯一的解决方案。请看下面我的回答。我真正的问题是委托,但也请发表您的答案。
【参考方案1】:
这是一种在窗口周围动态拖动创建的 div 的纯 javascript 方法。
var divs=[];
var draggingIndex;
var isDown=false;
var startX,startY;
// add some divs dynamically
addDiv(50,50,100,75,'blue','batch1');
addDiv(250,50,50,38,'green','batch1');
// listen to mouse events
window.onmousedown=(function(e)handleMouseDown(e););
window.onmousemove=(function(e)handleMouseMove(e););
window.onmouseup=(function(e)handleMouseUp(e););
function addDiv(x,y,w,h,bk,classname)
var div=document.createElement('div');
div.style.width=w+'px';
div.style.height=h+'px';
div.className=classname;
div.style.position='absolute';
div.style.left=x+'px';
div.style.top=y+'px';
div.style.background=bk;
divs.push(div:div,w:w,h:h);
document.body.appendChild(div);
function handleMouseDown(e)
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
// get mouse position
startX=parseInt(e.clientX);
startY=parseInt(e.clientY);
// Is any div under the mouse?
draggingIndex=undefined;
for(var i=0;i<divs.length;i++)
var d=divs[i];
var x=parseInt(d.div.style.left);
var y=parseInt(d.div.style.top);
if(startX>x && startX<x+d.w && startY>y && startY<y+d.h)
draggingIndex=i;
isDown=true;
break;
function handleMouseUp(e)
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
isDown=false;
function handleMouseMove(e)
if(!isDown)return;
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
// get mouse position
mouseX=parseInt(e.clientX);
mouseY=parseInt(e.clientY);
// move the dragging div by the distance the mouse has moved
var dragging=divs[draggingIndex].div;
var dx=mouseX-startX;
var dy=mouseY-startY;
startX=mouseX;
startY=mouseY;
dragging.style.left=(parseInt(dragging.style.left)+dx)+'px';
dragging.style.top=(parseInt(dragging.style.top)+dy)+'px';
body background-color: ivory;
.batch1border:1px solid red;
【讨论】:
我喜欢这段代码,因为它处理了拖放的每一个细节。通过重命名一些东西来使其适用于触控也相当容易(例如,当该功能适用于触控和鼠标时,将“鼠标”向下作为开始拖动会更好)我没有将其标记为正确回答只是因为它没有解决我的问题......这是我无法在将项目拖放到“新位置”后“重新拖动”项目。这是特定于克隆项目的。【参考方案2】:所以,问题就这么简单。我的可拖动项目是自定义指令,我使用 draggable="true" 设置并使用像 ondrop="drop(event)" 这样的内联绑定。所以,我没有意识到在其他地方,有一些非常有用的代码没有使用委托,也就是只在初始加载时绑定。这个小警告会影响任何动态加载的 DOM 元素!
原始代码
$(document).ready(function()
$('.dragme').on('mousedown', function(e)
// disable swiper when user clicks on drawer
$(this).parents('.swiper-wrapper').addClass('no-swiping');
);
$('.dragme').on('mouseup dragend', function(e)
// re-enable when user is done
$(this).parents('.swiper-wrapper').removeClass('no-swiping');
);
);
修复
$(document).ready(function()
$(document).on('mousedown', '.dragme', function(e)
// disable swiper when user clicks on drawer
$(this).parents('.swiper-wrapper').addClass('no-swiping');
);
$(document).on('mouseup dragend', '.dragme', function(e)
// re-enable when user is done
$(this).parents('.swiper-wrapper').removeClass('no-swiping');
);
);
请注意,此代码之前已实现,以允许在可拖动容器中拖动!
【讨论】:
以上是关于使用纯javascript拖放并再次拖动的主要内容,如果未能解决你的问题,请参考以下文章