带有动画的 jQuery 可排序
Posted
技术标签:
【中文标题】带有动画的 jQuery 可排序【英文标题】:jQuery Sortable with animation 【发布时间】:2011-06-30 22:17:09 【问题描述】:我正在使用 jQuery 和 Sortable 来排列我的项目列表(还有这个 http://dragsort.codeplex.com)。
一切都很完美。
我正在使用dragEnd
上的函数来按顺序排列列表。
这是我的代码:
$("#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("|"));
;
我的问题:我是否可以在拖动时制作动画?或者在拖动时重新定位元素?我只需要它在 Safari 上工作。
一个例子是这样的:
http://www.youtube.com/watch?v=U3j7mM_JBNw
看看拖放(0:30),你会明白我在说什么。
谢谢。
【问题讨论】:
你的 CSS 是什么样的?这实际上应该是真实的行为.. 我的 CSS 非常简单。只使用浮动宽度和高度。 你或许可以通过适配 QuickSand 找到解决方案 - razorjack.net/quicksand 我已提出相关功能请求here 【参考方案1】:聚会有点晚了,但我决定使用 jQuery 找到解决方案,因为在这个主题上几乎没有帮助,尤其是复制 Facebook 等网络应用程序中存在的功能及其相册的图像拖放重新排序,以及随之而来的漂亮动画......
所以我想出了一个似乎非常有效的解决方案,我会尽我所能解释它!来了……
这里最大的问题是不仅要为可排序对象设置动画,还要弄清楚它们需要动画到哪里——当涉及到像画廊中的图像这样的浮动元素时,这真是太棒了!为了解决这个问题,我决定.clone()
原始浮动LI
项目,使用小于原始@ 的z-index
值将克隆绝对定位在原始LI
项目之下 987654327@ 项目,然后当从 jQuery 可排序的 change
事件触发时,我可以检测到原始 LI
的位置并将绝对定位的克隆动画到这些位置。剩下的就是简单地适当地显示/隐藏元素以获得所需的效果。
这是代码,从 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>
所以我们有我们要排序的原始项目,以及克隆项目的容器。 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;
使用我们的 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);
);
);
);
哇,我真的希望这是有道理的,并且可以帮助某人制作可排序列表的动画,但对于任何感兴趣的人来说,这都是一个可行的示例! :)
【讨论】:
@Daniel - 感谢您的反馈,我希望它有意义! 感谢这段代码,它运行良好。只是想知道您是否知道为什么在 li 上使用 % 宽度然后调整浏览器大小时会中断? @Parallel2ne - 如果不看一些代码,或者不知道到底是什么问题,很难说,但如果我不得不猜测,我会说它是你所指的克隆项目作为“破碎”?这可能是由于克隆项目的样式,因为它们是绝对放置的,并且需要它们的容器 (ul#cloned_items
) 的样式与原始项目的容器 (ul#original_items
) 的样式相同,以正确接受适当的宽度% 的。如果克隆项目的容器不是 100% 宽,那么克隆项目的宽度就没有任何基础。有道理? :')
我确实明白你在说什么 :) 在你执行另一个可排序的操作 jsfiddle.net/jamestoone/dNfsJ/48 后它会自行修复@任何帮助将不胜感激
@Parallel2ne - 这可能是一个愚蠢的问题,但你为什么将li
元素的中间线(金色)浮动到右侧而不是左侧?我删除了 CSS (updated jsFiddle here) 的第 19 行,响应似乎更好。我不确定这是否能解决您最初的担忧?【参考方案2】:
刚刚实现了 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);
);
);
【讨论】:
【参考方案3】:虽然此解决方案非常适合创建初始过渡,但当项目回弹时,没有过渡。解决方案比我预期的要容易。您需要做的就是调整 .sortable() 中的 revert 选项
像这样:
<script>
$(document).ready(function()
$( "#sortable" ).sortable(
tolerance: 'pointer',
revert: 'invalid'
).disableSelection();
);
</script>
jQuery UI API:http://api.jqueryui.com/sortable/#option-revert
这样可以顺利过渡到物品的新家。
Click here for EXAMPLE on jsFiddle
【讨论】:
不幸的是,当您“取消”排序或删除事件时,“还原”选项不适用。被取消的项目会立即恢复,而不是平滑地动画。【参考方案4】:你为什么不在 jqueryui 上使用 Sortable? http://jsfiddle.net/KgNCD/
JS:
$( "#sortable" ).sortable(
start: function(e, ui)
$(ui.placeholder).hide(300);
,
change: function (e,ui)
$(ui.placeholder).hide().show(300);
);
$("#sortable").disableSelection();
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>
【讨论】:
是的,我想,但我怎样才能在下降之前为元素设置动画?【参考方案5】:来自上面的 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);
);
【讨论】:
【参考方案6】:对于任何寻求快速简便的解决方案的人,这里有一个插件,可让您通过在可排序参数中指定动画长度来快速添加可排序动画:
$('#sortable').sortable(
animation: 200,
);
演示:https://egorshar.github.io/jquery-ui-sortable-animation/
Github:https://github.com/egorshar/jquery-ui-sortable-animation
【讨论】:
以上是关于带有动画的 jQuery 可排序的主要内容,如果未能解决你的问题,请参考以下文章