【问题标题】:JQuery - animate moving DOM element to new parent?JQuery - 动画将DOM元素移动到新父级?
【发布时间】:2009-05-25 16:14:30
【问题描述】:

我在表格单元格中有一个图像标签,我想将其移动到另一个表格单元格,并让该移动动画化。

代码看起来像这样......

<td id="cell1"><img src="arrow.png" alt="Arrow"/></td>
<td id="cell2"></td>

我想将“arrow.png”移动到“cell2”,并具有某种过渡效果,最好是使用 JQuery。

有什么想法吗?

谢谢!

【问题讨论】:

    标签: javascript jquery dom jquery-ui animation


    【解决方案1】:

    这实际上非常困难,因为您必须将其删除并添加到 DOM 中,但要保持其位置。我想你正在寻找这样的东西。基本上我们不会为#cell1#cell2 中的箭头设置动画。我们只是在body-tag 中创建一个新的并为其设置动画。这样我们就不必担心表格单元格的位置,因为我们可以相对于文档进行定位。

    var $old = $('#cell1 img');
    //First we copy the arrow to the new table cell and get the offset to the document
    var $new = $old.clone().appendTo('#cell2');
    var newOffset = $new.offset();
    //Get the old position relative to document
    var oldOffset = $old.offset();
    //we also clone old to the document for the animation
    var $temp = $old.clone().appendTo('body');
    //hide new and old and move $temp to position
    //also big z-index, make sure to edit this to something that works with the page
    $temp
      .css('position', 'absolute')
      .css('left', oldOffset.left)
      .css('top', oldOffset.top)
      .css('zIndex', 1000);
    $new.hide();
    $old.hide();
    //animate the $temp to the position of the new img
    $temp.animate( {'top': newOffset.top, 'left':newOffset.left}, 'slow', function(){
       //callback function, we remove $old and $temp and show $new
       $new.show();
       $old.remove();
       $temp.remove();
    });
    

    我认为这应该为您指明正确的方向。

    【讨论】:

    • 你从我这里得到了一个“很好的答案”徽章 :)
    • 如果您有一个项目列表,并且还需要其他项目进行动画处理以腾出空间怎么办?
    【解决方案2】:

    @Pim Jager 的回答非常好,但是如果您有对原始元素的对象引用,它们会中断,因为原始元素已被克隆替换

    我想出了一个我认为稍微干净的解决方案,因为它只有一个克隆显示动画然后消失,将原件留在新位置。

    function moveAnimate(element, newParent){
        //Allow passing in either a jQuery object or selector
        element = $(element);
        newParent= $(newParent);
    
        var oldOffset = element.offset();
        element.appendTo(newParent);
        var newOffset = element.offset();
    
        var temp = element.clone().appendTo('body');
        temp.css({
            'position': 'absolute',
            'left': oldOffset.left,
            'top': oldOffset.top,
            'z-index': 1000
        });
        element.hide();
        temp.animate({'top': newOffset.top, 'left': newOffset.left}, 'slow', function(){
           element.show();
           temp.remove();
        });
    }
    

    使用:moveAnimate('#ElementToMove', '#newContainer')

    【讨论】:

    • 很棒的功能。效果很好!
    • 我在那个函数上不断收到“Uncaught TypeError: Cannot read property 'left' of undefined”错误,碰巧知道为什么吗?我按照你说的用了。
    • 你现在可以正常工作,但如果我尝试循环使用它,动画似乎“坏了”
    • @eric.itzhak 是的,因为动画是异步发生的,所以你需要一种方法来对它们进行排队。最直接的方法是添加回调函数参数并设置递归调用,并以适当的结束方式退出。完全解释这有点超出了这个答案的范围,但是如果你搜索如何在 JS 中使用回调,你应该能够找出答案。否则,您可以提出新问题。
    • 我改进了你的 sn-p,把它做成了一个小的 jQuery 插件并稍微清理了一下:gist.github.com/MadLittleMods/7257ee631210215e368e
    【解决方案3】:

    您需要分两步执行此操作:(1) 动画 (2) 重新定位。

    @Ballsacian 指出,您可以使用 .animate() 处理动画。可以使用 .html() 完成重新归位 - 对于上面的示例,

    var arrowMarkup = $('#cell1').html(); //grab the arrow
    $('#cell1').html(""); //delete it from the first cell
    $('#cell2').html(arrowMarkup); //add it to the second cell
    

    当然,您必须使代码复杂化才能集成动画。而且这样做不会导致选择(我假设您正在选择表格行?)激活旧选择和新选择之间的行,因为箭头经过它们。实现起来会更加复杂。

    【讨论】:

      【解决方案4】:

      我进一步扩展了one of the other answers,以便现在您可以将对象作为第三个参数传递,该参数在动画期间用作车辆。例如,如果你想将一些

    • 从一个
        移动到另一个,你的
          可能有一个特定的类来为
        • 提供样式。因此,在临时车辆
            中为您的
          • 设置动画真的很方便,该车辆提供与动画的源或目标
              相同的样式:
            //APPENDS AN ELEMENT IN AN ANIMATED FASHION
            function animateAppendTo(el, where, float){
                var pos0 = el.offset();
                el.appendTo(where);
                var pos1 = el.offset();
                el.clone().appendTo(float ? float : 'body');
                float.css({
                    'position': 'absolute',
                    'left': pos0.left,
                    'top': pos0.top,
                    'zIndex': 1000
                });
                el.hide();
                float.animate(
                    {'top': pos1.top,'left': pos1.left},
                    'slow',
                    function(){
                       el.show();
                       float.remove();
                    });
            }
            
    • 【讨论】:

        【解决方案5】:

        我正在尝试@Davy8 的功能,该功能非常好,但是当移动的元素在开始时从页面上折断然后在结束时又返回时,我发现它非常不和谐。其他页面元素突然移动打断了原本流畅的动画,但这可能取决于您的页面布局。

        所以这是@Davy8函数的修改版本,它也应该平滑地缩小和扩大父母之间的空间。

        function moveAnimate(element, newParent,
                             slideAnimationSpeed/*=800*/, spacerAnimationSpeed/*=600*/)
        {
            //Allow passing in either a jQuery object or selector
            element = $(element);
            newParent= $(newParent);
            slideAnimationSpeed=slideAnimationSpeed||800;
            spacerAnimationSpeed=spacerAnimationSpeed||600;
        
            var oldOffset = element.offset();
            var tempOutgoing=element.clone().insertAfter(element);
            tempOutgoing.hide(); //Don't take up space yet so 'newOffset' can be calculated correctly
            element.appendTo(newParent);
            var newOffset = element.offset();
        
            var tempMover = element.clone().appendTo('body');
            tempMover.css({
                'position': 'absolute',
                'left': oldOffset.left,
                'top': oldOffset.top,
                'z-index': 1000,
                'margin':0 //Necessary for animation alignment if the source element had margin
            });
        
            element.hide();
            element.show(spacerAnimationSpeed).css('visibility', 'hidden'); //Smoothly grow space at the target
        
            tempMover.animate({'top': newOffset.top, 'left': newOffset.left}, slideAnimationSpeed, function(){
               element.css('visibility', 'visible');
               tempMover.remove();
            });
            tempOutgoing.show().css('visibility', 'hidden');
            tempOutgoing.hide(spacerAnimationSpeed, function(){ tempOutgoing.remove() }); //smoothly shrink space at the source
        }
        

        【讨论】:

          【解决方案6】:

          如果动画不一定是移动的东西,这个使用fadeIn和fadeOut的问题给出了一个简单、干净的答案,没有克隆,并且仍然很好地传达了运动:

          Re-ordering div positions with jQuery?

          【讨论】:

            【解决方案7】:

            对于仍在查看此内容的任何人,我发现提供的示例与我想要的不完全吻合,并且它们没有考虑边距,所以这是我的版本:

            jQuery.fn.extend({
                moveElement : function (newParent, speed, after) {
                    var origEl   = $(this);
                    var moveToEl = $(newParent);
            
                    var oldOffset = origEl.offset();
                    var temp      = origEl.clone().appendTo('body');
            
                    temp.css({
                        'position' : 'absolute',
                        'left'     : parseInt(oldOffset.left) - parseInt(origEl.css('margin-left')),
                        'margin'   : origEl.css('margin'),
                        'top'      : oldOffset.top,
                        'z-index'  : 1000,
                        'height'   : moveToEl.innerHeight(),
                        'width'    : moveToEl.innerWidth()
                    });
            
                    var blankEl = $('<div></div>').css({
                        height   : moveToEl.innerHeight(),
                        margin   : moveToEl.css('margin'),
                        position : 'relative',
                        width    : moveToEl.innerWidth()
                    });
            
                    if (after) {
                        origEl.insertAfter(moveToEl);
                        blankEl.insertAfter(newParent);
                    }
                    else {
                        origEl.insertBefore(moveToEl);
                        blankEl.insertBefore(newParent);
                    }
                    origEl.hide();
            
                    var newOffset = blankEl.offset();
            
                    temp.animate({
                        'top'  : blankEl.offset().top - parseInt(moveToEl.css('margin-top')),
                        'left' : newOffset.left - parseInt(moveToEl.css('margin-left'))
                    }, speed, function () {
                        blankEl.remove();
                        origEl.show();
                        temp.remove();
                    });
                }
            });
            

            将一个元素移到另一个之前:$('.elementToFind').moveElement('.targetElement', 1000);

            一个接一个地移动一个元素:$('.elementToFind').moveElement('.targetElement', 1000, 'after');

            【讨论】:

              【解决方案8】:

              JQuery http://docs.jquery.com/Downloading_jQuery
              jQuery效果http://docs.jquery.com/Effects/animate#paramsoptions


              示例

               $("#go1").click(function(){
                    $("#block1").animate( { width:"90%" }, { queue:false, duration:3000 } )
                       .animate( { fontSize:"24px" }, 1500 )
                       .animate( { borderRightWidth:"15px" }, 1500);
                  });
              

              【讨论】:

                猜你喜欢
                • 2019-07-06
                • 2011-12-14
                • 1970-01-01
                • 2019-09-18
                • 2021-06-05
                • 2014-12-17
                • 2021-04-13
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多