Подтвердить что ты не робот

JQuery - оживить перемещающийся элемент DOM для нового родителя?

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

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

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

Я хотел бы переместить "arrow.png" в "cell2" и иметь какой-то эффект перехода, желательно с JQuery.

Любые идеи?

Спасибо!

4b9b3361

Ответ 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')

Ответ 3

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

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

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

//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, дает простой, чистый ответ без клонирования и до сих пор довольно хорошо передает движение:

Переупорядочить позиции div с помощью 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');