2009-05-25 4 views
30

У меня есть тег изображения внутри ячейки таблицы, который я бы хотел переместить в еще одну ячейку таблицы и иметь это движение анимированным.JQuery - анимация перемещения элемента DOM для нового родителя?

код выглядит примерно так ...

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

Я хотел бы, чтобы переместить «Arrow.png» на «CELL2», и иметь какой-то эффект перехода, предпочтительно с JQuery.

Любые идеи?

Спасибо!

ответ

3

Вы должны будете сделать это в два этапа: (1) анимация (2) rehoming.

Анимация, о которой вы можете позаботиться с помощью .animate(), как указывает @Ballsacian. Rehoming может быть достигнут с .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 

Конечно, вам придется усложнить этот код для интеграции анимации. И этот способ сделать это не приведет к выбору (я предполагаю, что вы выбираете строку таблицы?), Чтобы активировать строки между старым выбором и новым, по мере того, как стрелка проходит мимо них. Это было бы еще сложнее достичь.

49

Это действительно довольно сложно, потому что вам нужно удалить и добавить его в 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(); 
}); 

Я думаю, это должно указывать на вас в правильном направлении.

ответа
+0

у вас есть значок «большой ответ» от меня :) – Sinan

+0

Ха-ха, спасибо! [15 символов] –

+0

Ты спас меня много часов неприятностей. Спасибо тебе за это! –

48

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

+1

Большая функция. Работает очень хорошо! – Rocky

+0

Я продолжаю получать «Uncaught TypeError: не могу прочитать свойство« слева »от неопределенной ошибки в этой функции, узнайте почему? Я использовал его так же, как вы сказали. –

+0

@ eric.itzhak попробуйте мое редактирование. – Davy8

2

я продлил one of the other answers немного дальше, так что теперь вы можете передать объект в качестве третьего параметра, который служит в качестве транспортного средства во время анимации. Например, если вы хотите переместить <li> от одного <ul> к другому, ваш <ul> имеет определенный класс, который дает <li> его стиль.Таким образом, это действительно было бы удобно, чтобы оживить ваш < Ли > внутри временного транспортного средства < уль >, что обеспечивает тот же стиль, как источника или мишени < уль > анимации:

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

Если анимация не должен быть вещью двигаться, этот вопрос, который использует FadeIn и FADEOUT дает простой, чистый ответ, без клонирования и до сих пор передает движение довольно хорошо:

Re-ordering div positions with jQuery?

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

Смежные вопросы