JQuery - оживить перемещающийся элемент DOM для нового родителя?
У меня есть тег изображения внутри ячейки таблицы, который я бы хотел переместить в другую ячейку таблицы, и это анимационное движение.
Код выглядит примерно так:
<td id="cell1"><img src="arrow.png" alt="Arrow"/></td>
<td id="cell2"></td>
Я хотел бы переместить "arrow.png" в "cell2" и иметь какой-то эффект перехода, желательно с JQuery.
Любые идеи?
Спасибо!
Ответы
Ответ 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');
Ответ 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);
});