我有一个基本的拖放式trello式看板。您可以在不同的灰色框之间拖动任务。它使用https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API处的HTML拖放API。
var dropTarget = document.querySelector(".drop-target");
var draggables = document.querySelectorAll(".drag-task");
// Tells the other side what data is being passed (e.g. the ID is targeted)
draggables.forEach(item => {
item.addEventListener("dragstart", function(ev){
ev.dataTransfer.setData("srcId", ev.target.id);
});
})
// The end destination, prevent browsers default drag and drop (disabling breaks feature)
// because it's disabled by browsers by default
dropTarget.addEventListener('dragover', function(ev) {
ev.preventDefault();
});
// End destination where item is dropped into
dropTarget.addEventListener('drop', function(ev) {
ev.preventDefault();
let target = ev.target;
let droppable = target.classList.contains('drag-box');
let srcId = ev.dataTransfer.getData("srcId");
if (droppable) {
ev.target.appendChild(document.getElementById(srcId));
}
});
/***********DRAGGABLE BACKGROUND ****************/
.drag-box {
background-color: lightgray;
float: right;
width: 120px;
min-height: 50px;
padding-bottom: 30px;
height: auto;
margin: 30px;
}
.drag-task {
background-color: white;
margin: 15px;
}
.drop-active {
border: 1px dashed red;
}
<div class="drop-target">
<div class="drag-box">
<div class="drag-card">
<div draggable="true" id="task1" class="drag-task">Test Card 1</div>
</div>
<div class="drag-card">
<div draggable="true" id="task2" class="drag-task">Test Card 2</div>
</div>
<div class="drag-card">
<div draggable="true" id="task3" class="drag-task">Test Card 3</div>
</div>
</div>
<div class="drag-box">
</div>
<div class="drag-box">
</div>
</div>
我要实现的效果是类似于here的此gif效果。这样会在拖曳效果上创建与<div>
类相同级别的另一个drag-card
元素,并相应地重新放置自身。
我知道我必须使用dragover
和dragleave
事件侦听器,但就我所知。我在文件末尾添加了此代码。我从未使用过拖动事件侦听器,所以这对我来说是新的。
var makeHoverElement= true;
dropTarget.addEventListener("dragover", function(ev){
if(makeHoverElement){
let newNode =document.createElement('div');
newNode.className ='drop-active'
ev.target.parentElement.prepend(newNode);
makeHoverElement = false;
}
});
dropTarget.addEventListener("dragleave", function(ev){
// really I have no idea how to make this effect
});
到目前为止,结果还没有达到我的预期。拖移应用于task
项源自的元素
答案 0 :(得分:1)
使用jquery和jquery UI,我前一段时间做了类似的事情。我没有创建“制作新卡”功能,而是从“启动板”开始的,并创建了两个可放置区域,可以将卡片附加到它们之间并在它们之间切换-与您所拥有的类似。我记得使用“相交”是使它按我想要的方式工作的转折点-能够在列表中上下移动元素(因此它们不必移回原始位置)。也许这可能是您的起点? 这是fiddle(jQuery较旧。建议升级到较新版本)
希望这会有所帮助。
编辑:我对代码进行了一些小调整,以添加轮廓并在移动时更改光标。根据对another question的评论,添加边框是创建视觉“轮廓”效果的最有效方法。我发现,codepen中演示了一种创建“可排序”效果的更长的方法,并且简单地解释了该功能是基于计算悬停位置以及如果拖动的元素位于其中一个项目的中途,列表,效果就会显示出来,并且该项目可以放在列表项目之间。
希望这很清楚!
// Tells the other side what data is being passed (e.g. the ID is targeted)
var dropTarget = document.querySelector(".drop-target");
var draggables = document.querySelectorAll(".drag-task");
// Tells the other side what data is being passed (e.g. the ID is targeted)
draggables.forEach(item => {
item.addEventListener("dragstart", function(ev) {
ev.dataTransfer.setData("srcId", ev.target.id);
});
})
// The end destination, prevent browsers default drag and drop (disabling breaks feature)
// because it's disabled by browsers by default
dropTarget.addEventListener('dragover', function(ev) {
ev.preventDefault();
});
// End destination where item is dropped into
dropTarget.addEventListener('drop', function(ev) {
ev.preventDefault();
let target = ev.target;
let droppable = target.classList.contains('drag-box');
let srcId = ev.dataTransfer.getData("srcId");
if (droppable) {
ev.target.appendChild(document.getElementById(srcId));
}
});
.drag-box {
background-color: lightgray;
float: left;
width: 120px;
min-height: 80px; /*lengthened the height slightly*/
padding-bottom: 30px;
height: auto;
margin: 30px;
cursor: move; /*added the 'cross' cursor*/
}
.drag-task {
background-color: white;
margin: 10px;
padding: 5px; /*added padding to make tiles bigger*/
border:1px dashed #000000; /*set an outline*/
}
.drop-active {
border: 1px dashed red;
cursor: pointer; /*change the pointer back to the default cursor while moving between lists*/
}
<div class="drop-target">
<div class="drag-box">
<div class="drag-card">
<div draggable="true" id="task1" class="drag-task">Test Card 1</div>
</div>
<div class="drag-card">
<div draggable="true" id="task2" class="drag-task">Test Card 2</div>
</div>
<div class="drag-card">
<div draggable="true" id="task3" class="drag-task">Test Card 3</div>
</div>
</div>
<!-- added tiles to the 2nd list (and deleted 3rd box)-->
<div class="drag-box">
<div class="drag-card">
<div draggable="true" id="orange" class="drag-task">Orange</div>
</div>
<div class="drag-card">
<div draggable="true" id="apple" class="drag-task">Apple</div>
</div>
<div class="drag-card">
<div draggable="true" id="pear" class="drag-task">Pear</div>
</div>
</div>
$("#launchPad").height($(window).height() - 20);
var dropSpace = $(window).width() - $("#launchPad").width();
$("#dropZone").width(dropSpace - 70);
$("#dropZone").height($("#launchPad").height());
$(".card").draggable({
appendTo: "#launchPad",
cursor: "move",
helper: 'clone',
revert: "invalid",
});
$("#launchPad").droppable({
tolerance: "intersect",
accept: ".card",
activeClass: "ui-state-default",
hoverClass: "ui-state-hover",
drop: function(event, ui) {
$("#launchPad").append($(ui.draggable));
}
});
$(".stackDrop").droppable({
tolerance: "intersect",
accept: ".card",
activeClass: "ui-state-default",
hoverClass: "ui-state-hover",
drop: function(event, ui) {
$(this).append($(ui.draggable));
}
});
body {
margin: 0;
background-color: #ffffcc;
}
#launchPad {
width:170px;
float:left;
border: 1px solid #eaeaea;
background-color: #f5f5f5;
}
#dropZone {
float:right;
border: 1px solid #eaeaea;
background-color: #ffffcc;
}
.card {
width: 130px;
padding: 5px 10px;
margin:5px;
border:1px solid #ccc;
background-color: #eaeaea;
}
.stack {
display:inline-block;
vertical-align:top;
width: 180px;
border: 1px solid #ccc;
background-color: #f5f5f5;
margin: 20px;
}
.stackHdr {
background-color: #eaeaea;
border: 1px solid #fff;
padding: 5px
}
.stackDrop {
min-height:100px;
padding: 15px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>
<div id="launchPad">
<div class="card draggable" >
apple
</div>
<div class="card draggable">
orange
</div>
<div class="card draggable">
banana
</div>
<div class="card draggable">
car
</div>
<div class="card draggable">
bus
</div>
</div>
<div id="dropZone">
<div class="stack">
<div class="stackHdr">
Drop here
</div>
<div class="stackDrop droppable">
</div>
</div>
<div class="stack">
<div class="stackHdr">
Or here
</div>
<div class="stackDrop droppable">
</div>
</div>
</div>
答案 1 :(得分:1)
问题出在ev.target.parentElement.prepend(newNode);
中
您的ev.target
仍然是您要从 拖动节点的子节点。这就是将虚线边框div添加到“旧”框中的原因。我建议您在“拖动”功能中明确找到鼠标悬停的元素,然后向其中添加newNode。例如,您可以通过document.querySelector(":hover" )
进行选择,或尝试在那里处理“鼠标悬停”事件。
对于“ dragleave”效果,建议您使用ev.target
方法克隆Node.cloneNode()
,然后使用ev.target.parentElement
将克隆附加到Node.insertBefore()
。
MDN on .insertBefore()