jQuery 可排序动画
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5060357/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
jQuery Sortable with animation
提问by Anderson Oliveira
I'm using jQuery and Sortable to arrange my list of items (and this http://dragsort.codeplex.com).
我正在使用 jQuery 和 Sortable 来安排我的项目列表(以及这个http://dragsort.codeplex.com)。
All works perfect.
一切都很完美。
I'm using a function on dragEnd
to arrange the lists in order.
我正在使用一个函数dragEnd
来按顺序排列列表。
Here is my code:
这是我的代码:
$("#list1, #list2").dragsort({ dragSelector: "div",
dragBetween: true,
dragEnd: saveOrder,
placeHolderTemplate: "<li class='placeHolder'><div></div></li>" });
function saveOrder() {
var data = $("#list1 li").map(function() { return $(this).children().html(); }).get();
$("input[name=list1SortOrder]").val(data.join("|"));
};
My question: Is there anyway that I can do an animation while I'm dragging? Or reposition the elements while dragging? I just need it to work on Safari.
我的问题:无论如何,我可以在拖动时制作动画吗?或者在拖动时重新定位元素?我只需要它在 Safari 上工作。
One example is this:
一个例子是这样的:
http://www.youtube.com/watch?v=U3j7mM_JBNw
http://www.youtube.com/watch?v=U3j7mM_JBNw
Look at the drag/drop (0:30) and you'll see what I'm talking about.
看看拖/放 (0:30),你就会明白我在说什么。
Thanks.
谢谢。
回答by Chris Kempen
A bit late to the party, but I was determined to get a solution going with jQuery as there was very little help on this topic, especially replicating the functionality that exists on web apps like Facebook and their albums' images dragging and dropping to reorder, and the pretty animations that go along with that...
聚会有点晚了,但我决定用 jQuery 找到一个解决方案,因为在这个主题上几乎没有帮助,尤其是复制 Facebook 等网络应用程序中存在的功能及其相册的图像拖放以重新排序,以及随之而来的漂亮动画......
So I've come up with a solution that seems to work pretty great, and I'll do my best to explain it to the best of my abilities! Here goes...
所以我想出了一个似乎非常有效的解决方案,我会尽我所能来解释它!开始...
The biggest problem here was to not only animate the sortables, but to figure out where they needed to animate to - fantastic when it comes to floating elements like images in a gallery! To get around this, I decided to .clone()
the original floating LI
items, position the clones absolutely underthe original LI
items using a z-index
value that was less than the original LI
items, and then when the change
event fired from the jQuery sortable I could detect the position of the original LI
and animate the absolutely positioned clones to those positions. The rest was to simply show / hide elements appropriately to get the desired effect.
这里最大的问题是不仅要为可排序对象设置动画,还要弄清楚它们需要设置动画的位置——对于像画廊中的图像这样的浮动元素来说太棒了!为了解决这个问题,我决定把.clone()
原来的浮动LI
项目,位置克隆绝对下原来LI
使用的项目z-index
,这是低于原值LI
的项目,然后当change
事件从jQuery发射可排序我能检测到原来的位置LI
并将绝对定位的克隆动画化到这些位置。剩下的就是简单地适当地显示/隐藏元素以获得所需的效果。
Here's the code, starting with the HTML:
这是代码,从 HTML 开始:
<ul id="original_items">
<li><img src="something.jpg" /></li>
<li><img src="something.jpg" /></li>
<li><img src="something.jpg" /></li>
</ul>
<ul id="cloned_items">
</ul>
So we have the original items we're trying to sort, and a container for the cloned items. Time for the CSS:
所以我们有我们试图排序的原始项目,以及克隆项目的容器。CSS时间:
#original_items, #cloned_items {
list-style: none;
}
#original_items li {
float: left;
position: relative;
z-index: 5;
}
#cloned_items li {
position: absolute;
z-index: 1;
}
With our CSS, we're just removing any list styling, floating our original elements, and setting up the z-index
requirements to ensure the cloned items lie underneaththe original items. Note the relative
position on the original items to make sure they behave as expected. Why underneath you ask? It will (hopefully) become clear with some Javascript:
使用我们的 CSS,我们只是删除任何列表样式,浮动我们的原始元素,并设置z-index
要求以确保克隆的项目位于原始项目的下方。请注意relative
原始项目上的位置,以确保它们按预期运行。为什么在下面问?它会(希望)通过一些 Javascript 变得清晰:
jQuery(function(){
// loop through the original items...
jQuery("#original_items li").each(function(){
// clone the original items to make their
// absolute-positioned counterparts...
var item = jQuery(this);
var item_clone = item.clone();
// 'store' the clone for later use...
item.data("clone", item_clone);
// set the initial position of the clone
var position = item.position();
item_clone.css("left", position.left);
item_clone.css("top", position.top);
// append the clone...
jQuery("#cloned_items").append(item_clone);
});
// create our sortable as usual...
// with some event handler extras...
jQuery("#original_items").sortable({
// on sorting start, hide the original items...
// only adjust the visibility, we still need
// their float positions..!
start: function(e, ui){
// loop through the items, except the one we're
// currently dragging, and hide it...
ui.helper.addClass("exclude-me");
jQuery("#original_items li:not(.exclude-me)")
.css("visibility", "hidden");
// get the clone that's under it and hide it...
ui.helper.data("clone").hide();
},
stop: function(e, ui){
// get the item we were just dragging, and
// its clone, and adjust accordingly...
jQuery("#original_items li.exclude-me").each(function(){
var item = jQuery(this);
var clone = item.data("clone");
var position = item.position();
// move the clone under the item we've just dropped...
clone.css("left", position.left);
clone.css("top", position.top);
clone.show();
// remove unnecessary class...
item.removeClass("exclude-me");
});
// make sure all our original items are visible again...
jQuery("#original_items li").css("visibility", "visible");
},
// here's where the magic happens...
change: function(e, ui){
// get all invisible items that are also not placeholders
// and process them when ordering changes...
jQuery("#original_items li:not(.exclude-me, .ui-sortable-placeholder)").each(function(){
var item = jQuery(this);
var clone = item.data("clone");
// stop current clone animations...
clone.stop(true, false);
// get the invisible item, which has snapped to a new
// location, get its position, and animate the visible
// clone to it...
var position = item.position();
clone.animate({
left: position.left,
top:position.top}, 500);
});
}
});
});
Wow, I really hope this makes sense and helps someone animate their sortable lists, but this is a working example for anyone who's interested! :)
哇,我真的希望这是有道理的,并帮助某人为他们的可排序列表设置动画,但对于任何感兴趣的人来说,这是一个工作示例!:)
回答by refaelio
Just impleneted what Chris Kempen said: http://jsfiddle.net/dNfsJ/
刚刚实现了 Chris Kempen 所说的:http: //jsfiddle.net/dNfsJ/
jQuery(function(){
// loop through the original items...
jQuery("#original_items li").each(function(){
// clone the original items to make their
// absolute-positioned counterparts...
var item = jQuery(this);
var item_clone = item.clone();
// 'store' the clone for later use...
item.data("clone", item_clone);
// set the initial position of the clone
var position = item.position();
item_clone.css("left", position.left);
item_clone.css("top", position.top);
// append the clone...
jQuery("#cloned_items").append(item_clone);
});
// create our sortable as usual...
// with some event handler extras...
jQuery("#original_items").sortable({
// on sorting start, hide the original items...
// only adjust the visibility, we still need
// their float positions..!
start: function(e, ui){
// loop through the items, except the one we're
// currently dragging, and hide it...
ui.helper.addClass("exclude-me");
jQuery("#original_items li:not(.exclude-me)")
.css("visibility", "hidden");
// get the clone that's under it and hide it...
ui.helper.data("clone").hide();
},
stop: function(e, ui){
// get the item we were just dragging, and
// its clone, and adjust accordingly...
jQuery("#original_items li.exclude-me").each(function(){
var item = jQuery(this);
var clone = item.data("clone");
var position = item.position();
// move the clone under the item we've just dropped...
clone.css("left", position.left);
clone.css("top", position.top);
clone.show();
// remove unnecessary class...
item.removeClass("exclude-me");
});
// make sure all our original items are visible again...
jQuery("#original_items li").css("visibility", "visible");
},
// here's where the magic happens...
change: function(e, ui){
// get all invisible items that are also not placeholders
// and process them when ordering changes...
jQuery("#original_items li:not(.exclude-me, .ui-sortable-placeholder)").each(function(){
var item = jQuery(this);
var clone = item.data("clone");
// stop current clone animations...
clone.stop(true, false);
// get the invisible item, which has snapped to a new
// location, get its position, and animate the visible
// clone to it...
var position = item.position();
clone.animate({
left: position.left,
top:position.top}, 500);
});
}
});
回答by Elon Zito
While this solution works great to create an initial transition, when the item snaps back, there is no transition. The solution is easier than I ever expected. All you need to do is adjust the revertoption in .sortable()
虽然此解决方案非常适合创建初始过渡,但当项目弹回时,没有过渡。解决方案比我想象的要容易。您需要做的就是调整.sortable() 中的还原选项
Like this:
像这样:
<script>
$(document).ready(function() {
$( "#sortable" ).sortable({
tolerance: 'pointer',
revert: 'invalid'
}).disableSelection();
});
</script>
jQuery UI API: http://api.jqueryui.com/sortable/#option-revert
jQuery UI API:http: //api.jqueryui.com/sortable/#option-revert
This makes a nice and smooth transition to the item's new home.
这可以顺利过渡到项目的新家。
回答by aavezel
Why did not you used Sortable on jqueryui? http://jsfiddle.net/KgNCD/
你为什么不在 jqueryui 上使用 Sortable?http://jsfiddle.net/KgNCD/
JS:
JS:
$( "#sortable" ).sortable({
start: function(e, ui){
$(ui.placeholder).hide(300);
},
change: function (e,ui){
$(ui.placeholder).hide().show(300);
}
});
$("#sortable").disableSelection();
HTML:
HTML:
<ul id="sortable">
<li class="ui-state-default">1</li>
<li class="ui-state-default">2</li>
<li class="ui-state-default">3</li>
<li class="ui-state-default">4</li>
<li class="ui-state-default">5</li>
<li class="ui-state-default">6</li>
<li class="ui-state-default">7</li>
<li class="ui-state-default">8</li>
<li class="ui-state-default">9</li>
<li class="ui-state-default">10</li>
<li class="ui-state-default">11</li>
<li class="ui-state-default">12</li>
</ul>
回答by Ryan Crispin Heneise
From the jsfiddle answer above (http://jsfiddle.net/KgNCD/2/):
从上面的 jsfiddle 答案(http://jsfiddle.net/KgNCD/2/):
$( "#sortable" ).sortable({
start: function(e, ui){
$(ui.placeholder).hide(300);
},
change: function (e,ui){
$(ui.placeholder).hide().show(300);
}
});