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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 18:29:04  来源:igfitidea点击:

jQuery Sortable with animation

jqueryjquery-uianimationdrag-and-dropjquery-ui-sortable

提问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 dragEndto 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 LIitems, position the clones absolutely underthe original LIitems using a z-indexvalue that was less than the original LIitems, and then when the changeevent fired from the jQuery sortable I could detect the position of the original LIand 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-indexrequirements to ensure the cloned items lie underneaththe original items. Note the relativeposition 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.

这可以顺利过渡到项目的新家。

Click here for EXAMPLE on jsFiddle

单击此处查看 jsFiddle 上的示例

回答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);
    }
});