在相对定位的容器之间移动可拖动元素
Moving draggable element between relatively positioned containers
我有一个页面,其中包含可以放入各种容器中的物品。我必须在任何给定时间将可拖动项添加到当前结束的容器中,以便根据 css 以某种方式设置样式,具体取决于可拖动项和放置目标的组合 class.在 javascript 中应用此样式不是一个选项 - 样式必须来自 CSS.
问题来了,因为我在可拖动对象前面添加的容器具有 position: relative
属性。当我移动它时,这会弄乱可拖动助手相对于鼠标的位置。
这是一个非常简化的问题演示:
$('.draggable').draggable({
drag: _onDrag,
helper: function () {
return $(this).clone().prependTo('#div1');
}
});
function _onDrag(event, ui) {
ui.helper.hide();
var elementAtPoint = $(document.elementFromPoint(event.clientX, event.clientY));
if(elementAtPoint.hasClass('dropTarget')) {
ui.helper.prependTo(elementAtPoint);
}
ui.helper.show();
}
.draggable {
display: inline-block;
background: red;
height:50px;
width: 50px;
}
#div1 .item1 {
background: green;
}
#div1 .item2 {
background: purple;
}
#div2 .item1 {
background: blue;
}
#div2 .item2 {
background: orange;
}
#div1, #div2 {
position: relative;
width: 100px;
height: 100px;
border: 1px solid #000;
display: inline-block;
}
<script src="https://code.jquery.com/jquery-2.2.2.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<div class="draggable item1">
Drag me!
</div>
<div class="draggable item2">
Drag me too!
</div>
<div id="div1" class="dropTarget">
Drag the box here first...
</div>
<div id="div2" class="dropTarget">
Then drag it here :(
</div>
在不更改 css 或 html 的情况下,我可以做些什么来防止可拖动对象失去它的位置?
发生这种情况是因为在重新排列DOM时,渲染位置会根据新的偏移量重新计算。修复它的最简单方法是不重新排列 DOM。您是否考虑过使用 droppable
小部件?它们提供了您正在寻找的几乎开箱即用的功能:
$('#draggable').draggable({
helper: function () {
return $(this).clone().prependTo('#div1');
}
});
$('#div1, #div2').droppable({
over: function(e, ui) {
ui.helper.addClass($(this).data('target-class'));
},
out: function(e, ui) {
ui.helper.removeClass($(this).data('target-class'));
}
});
#draggable {
display: inline-block;
background: red;
height:50px;
width: 50px;
}
#draggable.green {
background: green;
}
#draggable.blue {
background: blue;
}
#div1, #div2 {
position: relative;
width: 100px;
height: 100px;
border: 1px solid #000;
display: inline-block;
}
<script src="https://code.jquery.com/jquery-2.2.2.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<div id="draggable">
Drag me!
</div>
<div id="div1" class="dropTarget" data-target-class="green">
Drag the box here first...
</div>
<div id="div2" class="dropTarget" data-target-class="blue">
Then drag it here :)
</div>
更新:为了在不进行任何 CSS 更改的情况下执行此操作,您可以获得容器位置之间的差异,并将其用作位置偏移量。
$('.draggable').draggable({
start: _onStart,
drag: _onDrag,
helper: function () {
return $(this).clone().prependTo('#div1');
}
});
function _onStart(event, ui) {
this.initialContainer = ui.helper.parent();
this.currentContainer = ui.helper.parent();
this.topOffset = 0;
this.leftOffset = 0;
}
function _onDrag(event, ui) {
ui.helper.hide();
var elementAtPoint = $(document.elementFromPoint(event.clientX, event.clientY));
if(elementAtPoint.hasClass('dropTarget') &&
!elementAtPoint.is(this.currentContainer)) {
this.topOffset = elementAtPoint.position().top -
this.initialContainer.position().top;
this.leftOffset = elementAtPoint.position().left -
this.initialContainer.position().left;
this.currentContainer = elementAtPoint;
ui.helper.prependTo(elementAtPoint);
}
ui.position.top -= this.topOffset;
ui.position.left -= this.leftOffset;
ui.helper.show();
}
.draggable {
display: inline-block;
background: red;
height:50px;
width: 50px;
}
#div1 .item1 {
background: green;
}
#div1 .item2 {
background: purple;
}
#div2 .item1 {
background: blue;
}
#div2 .item2 {
background: orange;
}
#div1, #div2 {
position: relative;
width: 100px;
height: 100px;
border: 1px solid #000;
display: inline-block;
}
<script src="https://code.jquery.com/jquery-2.2.2.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<div class="draggable item1">
Drag me!
</div>
<div class="draggable item2">
Drag me too!
</div>
<div id="div1" class="dropTarget">
Drag the box here first...
</div>
<div id="div2" class="dropTarget">
Then drag it here :)
</div>
我仍然建议尽可能重写 CSS。第一种方法可读性更好,也更不脆弱
我有一个页面,其中包含可以放入各种容器中的物品。我必须在任何给定时间将可拖动项添加到当前结束的容器中,以便根据 css 以某种方式设置样式,具体取决于可拖动项和放置目标的组合 class.在 javascript 中应用此样式不是一个选项 - 样式必须来自 CSS.
问题来了,因为我在可拖动对象前面添加的容器具有 position: relative
属性。当我移动它时,这会弄乱可拖动助手相对于鼠标的位置。
这是一个非常简化的问题演示:
$('.draggable').draggable({
drag: _onDrag,
helper: function () {
return $(this).clone().prependTo('#div1');
}
});
function _onDrag(event, ui) {
ui.helper.hide();
var elementAtPoint = $(document.elementFromPoint(event.clientX, event.clientY));
if(elementAtPoint.hasClass('dropTarget')) {
ui.helper.prependTo(elementAtPoint);
}
ui.helper.show();
}
.draggable {
display: inline-block;
background: red;
height:50px;
width: 50px;
}
#div1 .item1 {
background: green;
}
#div1 .item2 {
background: purple;
}
#div2 .item1 {
background: blue;
}
#div2 .item2 {
background: orange;
}
#div1, #div2 {
position: relative;
width: 100px;
height: 100px;
border: 1px solid #000;
display: inline-block;
}
<script src="https://code.jquery.com/jquery-2.2.2.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<div class="draggable item1">
Drag me!
</div>
<div class="draggable item2">
Drag me too!
</div>
<div id="div1" class="dropTarget">
Drag the box here first...
</div>
<div id="div2" class="dropTarget">
Then drag it here :(
</div>
在不更改 css 或 html 的情况下,我可以做些什么来防止可拖动对象失去它的位置?
发生这种情况是因为在重新排列DOM时,渲染位置会根据新的偏移量重新计算。修复它的最简单方法是不重新排列 DOM。您是否考虑过使用 droppable
小部件?它们提供了您正在寻找的几乎开箱即用的功能:
$('#draggable').draggable({
helper: function () {
return $(this).clone().prependTo('#div1');
}
});
$('#div1, #div2').droppable({
over: function(e, ui) {
ui.helper.addClass($(this).data('target-class'));
},
out: function(e, ui) {
ui.helper.removeClass($(this).data('target-class'));
}
});
#draggable {
display: inline-block;
background: red;
height:50px;
width: 50px;
}
#draggable.green {
background: green;
}
#draggable.blue {
background: blue;
}
#div1, #div2 {
position: relative;
width: 100px;
height: 100px;
border: 1px solid #000;
display: inline-block;
}
<script src="https://code.jquery.com/jquery-2.2.2.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<div id="draggable">
Drag me!
</div>
<div id="div1" class="dropTarget" data-target-class="green">
Drag the box here first...
</div>
<div id="div2" class="dropTarget" data-target-class="blue">
Then drag it here :)
</div>
更新:为了在不进行任何 CSS 更改的情况下执行此操作,您可以获得容器位置之间的差异,并将其用作位置偏移量。
$('.draggable').draggable({
start: _onStart,
drag: _onDrag,
helper: function () {
return $(this).clone().prependTo('#div1');
}
});
function _onStart(event, ui) {
this.initialContainer = ui.helper.parent();
this.currentContainer = ui.helper.parent();
this.topOffset = 0;
this.leftOffset = 0;
}
function _onDrag(event, ui) {
ui.helper.hide();
var elementAtPoint = $(document.elementFromPoint(event.clientX, event.clientY));
if(elementAtPoint.hasClass('dropTarget') &&
!elementAtPoint.is(this.currentContainer)) {
this.topOffset = elementAtPoint.position().top -
this.initialContainer.position().top;
this.leftOffset = elementAtPoint.position().left -
this.initialContainer.position().left;
this.currentContainer = elementAtPoint;
ui.helper.prependTo(elementAtPoint);
}
ui.position.top -= this.topOffset;
ui.position.left -= this.leftOffset;
ui.helper.show();
}
.draggable {
display: inline-block;
background: red;
height:50px;
width: 50px;
}
#div1 .item1 {
background: green;
}
#div1 .item2 {
background: purple;
}
#div2 .item1 {
background: blue;
}
#div2 .item2 {
background: orange;
}
#div1, #div2 {
position: relative;
width: 100px;
height: 100px;
border: 1px solid #000;
display: inline-block;
}
<script src="https://code.jquery.com/jquery-2.2.2.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<div class="draggable item1">
Drag me!
</div>
<div class="draggable item2">
Drag me too!
</div>
<div id="div1" class="dropTarget">
Drag the box here first...
</div>
<div id="div2" class="dropTarget">
Then drag it here :)
</div>
我仍然建议尽可能重写 CSS。第一种方法可读性更好,也更不脆弱