如图1所示。
我有一个主div
- 这是Droppable
使用Four Draggables,即 A , B , C ,适合。 在将A,B或C div拖动到可放置的主要Div中时 - 它占据空间,如图2 所示(当我将A拖入主要部分时显示)。现在,如果我拖动另一个div(A,B或C),那么它应该占据空间的宽度大小。 (高度与主要部分相同)
现在,如果我拖动第4个可拖动的div
,即名称适合,则应在主div
内形成div
,其宽度等于空间留在Main div
的两个相邻Div中。
例如:。假设A和B之间(主要内部)和B和c之间有10px空间,空间是40px,所以如果我在A和B之间放置FIT,那么应该形成一个div,它们的空间差异是10px,同样40px div应该是在FIT的阻力下形成在B和C之间
它不应该挤压主要Div中的div,也不应该溢出主要的DIv
请告诉我如何将可拖动的A,B和C放置在用户定位位置的主div
内,而不会干扰主div
宽度。
我所做的是 我把div的A,B,C作为可拖动的
$(".classname").draggable({
helper: 'clone',
stop: function(event, ui) {
}
});
和主div Droppable:
$(".maindivclass").droppable();
并且在可拖动的下降中,我在主div中制作那些Divs Draggable
$("#" + Dropped_div_id).draggable({
axis: 'x',
containment: "#Main_divID",
});
但是在A,B和C的下降时,它总是占据中心位置,现在我可以在主div
内删除任意数量的div
s。请告诉我如何使draggables定位User掉落的确切位置,并且所有div
s的宽度总和应始终等于Main div
宽度。也许Grid是解决方案,但我有动态宽度div
要删除。
我经常研究并找到了一些东西 - 与我的任务相关的10%是http://gridster.net/ - 但这里的容器不是固定的高度或宽度。在我的情况下,所有div
的高度都是相同的。只有宽度不同。
在评论中询问更多其他信息时
1)当A,B或C被拖放到Main时,您希望将该项目附加到Main。
2)当拖动另一个时,不应该在Main中已存在的其他div上删除/重叠。
3)在Fit的拖动上,Main中剩余的空间应该被占用。我的意思是应该根据Main div中剩下的空间创建具有相应宽度的div
答案 0 :(得分:2)
那很有趣又脏。
让你成为一个基本上做两件事的例子:
代码显然需要改进,但我相信它会帮助你走上正轨。
JS代码:
$(function() {
var set = {
appendClass: 'added',
area: { s:"#droppable", w:0, left:0 },
added : [],
};
$( ".exact-pos, #drag_fit" ).draggable({
revert: "invalid",
appendTo: ".wrap",
helper: "clone"
});
$( "#droppable" ).droppable({
accept:".exact-pos, .fill",
drop: function( event, ui ) {
var $area = $(this);
var $origin_ele = $(ui.draggable).clone();
var $ele_clone = $area.closest('.wrap').find('.ui-draggable-dragging').eq(0);
var mes = {};
set.area.w = $area.outerWidth();
set.area.l = $area.offset().left;
if (!$origin_ele.hasClass("fill")) { // Handle non fit
mes = { // measure
s:$origin_ele.attr('class') + " " + set.appendClass,
l:$ele_clone.offset().left - set.area.l,
w:$(ui.draggable).outerWidth(),
r:0
}
//Check borders:
if (mes.l < 0) { mes.l = 0; }
if (mes.l + mes.w > set.area.w) { mes.l = set.area.w - mes.w; }
//Set right side:
mes.r = mes.l + mes.w;
var revert = false;
//Check overlaping left:
$.each(set.added, function(index, ele) {
if (mes.l >= ele.l && mes.l <= ele.r) {
mes.l = ele.r;
mes.r = mes.l + mes.w;
}
});
//Check overlapping right: will revert
$.each(set.added, function(index, ele) {
if (mes.r >= ele.l && mes.r <= ele.r) {
revert = true;
} else if (mes.r >= ele.r && mes.l <= ele.l) {
revert = true;
} else if (mes.r > set.area.w) {
revert = true;
}
});
//append or revert
if (!revert) {
ui.draggable.draggable('option','revert',false);
$area.append($origin_ele.addClass("added").css({"left":mes.l}));
set.added.push($.extend(true, {}, mes));
} else {
ui.draggable.draggable('option','revert',true);
}
} else {
var f = { l:0,w:0,r:0 };
var c = $ele_clone.offset().left - set.area.l + ($(ui.draggable).outerWidth() / 2);
var betw = -1;
var fleft = 0;
var fright = 0;
var revert = false;
//sort by position:
set.added.sort(function(a, b) {
return a.l - b.l;
});
//after which elemnt:
$.each(set.added, function(index, ele) {
if (ele.r < c) { betw = index; }
});
//calc dim:
if (betw == -1 && set.added.length == 0) {
fright = set.area.w;
} else if (betw == -1 && set.added.length > 0) {
fright = set.added[0].l;
} else if (betw == set.added.length - 1) {
fleft = set.added[betw].r;
fright = set.area.w;
} else if (typeof set.added[betw + 1] != 'undefined') {
fleft = set.added[betw].r;
fright = set.added[betw + 1].l;
}
if (fright - fleft > 1) {
f.l = fleft;
f.w = fright - fleft;
f.r = f.l + f.w;
} else {
revert = true;
}
//append or revert:
if (!revert) {
ui.draggable.draggable('option','revert',false);
$area.append($origin_ele.addClass("added").css({"left":f.l, width:f.w}).text(""));
set.added.push($.extend(true, {}, f));
} else {
ui.draggable.draggable('option','revert',true);
}
}
}
});
$('#resetAll').click(function resetAll() {
set.added = [];
$(set.area.s).find('div').fadeOut(function(){ $(this).remove(); });
});
});
答案 1 :(得分:2)
这个答案并不完全,但它非常实用,我计划更新它。目前这将执行以下功能:
当前工作示例:https://jsfiddle.net/Twisty/35nd6y3g/10/
<强> HTML 强>
<div class="wrapper">
<div class="box droppable" id="main">Main Div - droppable</div>
<div class="box draggable new" id="a">drag A</div>
<div class="box draggable new" id="b">drag B</div>
<div class="box draggable new" id="c">drag C</div>
<div class="box draggable new" id="fit" data-width="150">fit</div>
</div>
<br />
<button id="resetBtn">Reset</button>
<input type="text" id="leftDetails" style="width: 75%" />
<强> CSS 强>
body {
overflow: hidden;
}
.wrapper {
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
height: 450px;
}
.box {
border: 1px solid black;
display: flex;
//justify-content: center;
align-items: center;
}
#main {
position: relative;
width: 150px;
height: 450px;
}
#main .box {
background: #9d9d9d;
}
#a {
width: 30px;
height: 450px;
}
#b {
width: 45px;
height: 450px;
}
#c {
width: 75px;
height: 450px;
}
#fit {
width: 30px;
height: 40px;
}
<强>的jQuery 强>
$(document).ready(function() {
console.log("Main: " + $("#main").position().left + " Drag A: " + $("#a").position().left + "Drag B: " + $("#b").position().left + " Drag C: " + $("#c").position().left);
var mainBoxes = {};
$("#resetBtn").click(function() {
$("#main").find("div.box").remove();
mainBoxes = {};
});
var dragOrig;
$(".draggable").draggable({
containment: "#main",
axis: "x",
revert: true,
start: function(e, ui) {
dragOrig = ui.position;
},
drag: function(e, ui) {
$("#leftDetails").val(ui.helper.text() + " pos left: " + ui.position.left + " off left: " + ui.offset.left);
if (Object.keys(mainBoxes).length === 0) {
return;
}
var offLeft = ui.offset.left - $("#main").offset().left;
var offRight = offLeft + ui.helper.width();
//var offMouse = e.clientX - $("#main").offset().left;
$.each(mainBoxes, function(k, v) {
if (offLeft >= v.left && offLeft <= v.right) {
ui.position.left = ui.position.left + v.right;
console.log("Info: Left Edge collided with ", k, ui.position);
}
if (offRight > v.left && offRight < v.right) {
//ui.position.left = ui.position.left + (v.left - ui.helper.width());
ui.position.left = ui.position.left + v.right;
console.log("Info: Right Edge collided with ", k, ui.position);
}
});
},
});
$(".droppable").droppable({
hoverClass: "hover",
accept: ".box",
drop: function(event, ui) {
// add functionality here
//var pos = ui.position;
var off = ui.offset;
var c = $("#main .box").length + 1;
var $newBox = ui.draggable.clone();
if (ui.draggable.attr("id") === "fit") {
console.log("Info: Adding 'fit' class");
$newBox.addClass("fit");
if (Object.keys(mainBoxes).length === 0) {
console.log("Info: No other boxes found. Set Max Width.");
$newBox.css({
width: "150px",
height: "450px",
left: "-1px"
});
} else {
var lefts = Object.keys(mainBoxes).map(function(k) {
return mainBoxes[k].left;
});
var rights = Object.keys(mainBoxes).map(function(k) {
return mainBoxes[k].right;
});
var minLeft = Math.min.apply(null, lefts);
var maxRight = Math.max.apply(null, rights);
if ((ui.offset.left - $("#main").offset().left) + ui.helper.width() < minLeft) {
console.log("Info: 'fit' dropped left of boxes.");
$newBox.css({
width: minLeft + "px",
height: "450px",
left: "-1px"
});
$newBox.data("width", minLeft);
console.log("Info: ", minLeft, maxRight, $newBox[0]);
}
if ((ui.offset.left - $("#main").offset().left) > maxRight) {
console.log("Info: 'fit' dropped right of boxes.");
$newBox.css({
width: (150 - maxRight) + "px",
height: "450px",
left: maxRight + "px"
});
$newBox.data("width", 150 - maxRight);
console.log("Info: ", minLeft, maxRight, (450 - maxRight), $newBox[0]);
}
}
} else {
$newBox = ui.draggable.clone();
if ($newBox.hasClass("new")) {
$newBox.removeClass("new");
} else {
return;
}
}
console.log("Info: Removing .draggable");
$newBox.removeClass("draggable");
console.log("Info: Setting ID = box" + c);
$newBox.attr("id", "box" + c);
$newBox.draggable({
containment: "#main",
axis: "x",
drag: function(e, ui) {
if (Object.keys(mainBoxes).length === 0) {
return;
}
var offLeft = ui.offset.left - $("#main").offset().left;
var offRight = offLeft + ui.helper.width();
$.each(mainBoxes, function(k, v) {
if (k == ui.helper.attr("id")) {
return false;
}
if (offLeft > v.left && offLeft < v.right) {
ui.position.left = v.right;
console.log("Left Edge Collison with ", k);
}
if (offRight > v.left && offRight < v.right) {
ui.position.left = v.left - ui.helper.width();
console.log("Info: Right Edge Collision with ", k);
}
});
},
stop: function(e, ui) {
mainBoxes[ui.helper.attr("id")] = {
left: ui.offset.left - $("#main").offset().left,
right: (ui.offset.left - $("#main").offset().left) + ui.helper.width()
};
console.log("Info: Updating ", ui.helper.attr("id"), mainBoxes);
}
});
if ($newBox.draggable("instance") !== "undefined") {
console.log("box" + c + ": is draggable.");
}
$newBox.css({
left: $newBox.hasClass("fit") ? $newBox.css("left") : (off.left - $("#main").offset().left) + "px",
top: "-1px",
position: 'absolute',
height: "450px",
width: $newBox.hasClass("fit") ? $newBox.css("width") : ui.draggable.width() + "px"
});
console.log("box" + c + ": ", $newBox[0], " now being appended.");
$("#main").append($newBox);
mainBoxes['box' + c] = {
'width': $newBox.width(),
'left': off.left - $("#main").offset().left,
'right': (off.left - $("#main").offset().left) + $newBox.width()
};
console.log("Added: ", $newBox.attr("id"), mainBoxes);
}
});
});
如上所述,这几乎已经完成。由于使用了视口单元,定位正在被抛弃。这不是一个很好的用例,但它是我从提供的小提琴开始的。
为了跟踪对象,我创建了一个名为mainBoxes
的对象。当对象被放入droppable
时,这会更新。每个索引都包含从偏移左侧位置值填充的left
,right
和width
。 mainBoxes is used for collision detection when dragging further objects and to calculate the width for
适合`对象。
我们有2个拖动方案,将新项目拖动到主要区域或移动已存在的项目。当我们拖放一个新项目时,它会被更新,可拖动被破坏,可拖动会被新属性重置,我们会将其附加到#main
。默认情况下,可拖动不附加元素,只是更改它在页面上的位置。因此,div
将被移动,但永远不会是#main
的孩子。
视口单元为碰撞检测和防止将对象拖动到另一个现有对象上带来了挑战。我已经向控制台添加了许多细节,以便清楚地了解所有活动。我打算通过将所有长度和位置转换为像素单位来解决这个问题。
这应该让你去。我还发现了以下插件:https://sourceforge.net/projects/jquidragcollide/我可能会调查这是否是一个更好的工具。