JQuery - 动画将DOM元素移动到新父元素?

时间:2009-05-25 16:14:31

标签: javascript jquery dom jquery-ui animation

我在表格单元格中有一个图像标记,我希望移动到另一个表格单元格,并将该动画设置为动画。

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

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

我想将“arrow.png”移动到“cell2”,并且有一些转换效果,最好是使用JQuery。

有什么想法吗?

谢谢!

8 个答案:

答案 0 :(得分:52)

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

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();
});

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

答案 1 :(得分:50)

@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')

答案 2 :(得分: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

当然,您必须使该代码复杂化以集成动画。这种做法不会导致选择(我假设你正在选择一个表格行?)来激活旧选择和新选择之间的行,因为箭头经过它们。实现这一目标会更加复杂。

答案 3 :(得分:2)

我进一步扩展了one of the other answers,现在您可以将对象作为第三个参数传递,该参数在动画期间充当车辆。例如,如果您想移动一些&lt; li&gt;从一个&lt; ul&gt;另一个,你的&lt; ul&gt;可能有某个类给出&lt; li&gt;它的造型。因此,为你的&lt; li&gt;制作动画真的很方便。在临时车辆内&lt; ul&gt;提供与源或目标相同的样式&lt; ul&gt;动画:

//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();
        });
}

答案 4 :(得分:1)

我正在尝试@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
}

答案 5 :(得分:0)

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

Re-ordering div positions with jQuery?

答案 6 :(得分:0)

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

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');

答案 7 :(得分:-3)

JQuery http://docs.jquery.com/Downloading_jQuery
JQuery Effects 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);
    });