web-dev-qa-db-ja.com

JQuery-DOM要素を新しい親に移動するアニメーションを作成しますか?

テーブルセル内に画像タグがあり、anotherテーブルセルに移動して、その動きをアニメーション化したいと思います。

コードは次のようになります...

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

「arrow.png」を「cell2」に移動して、できればJQueryを使用して何らかの遷移効果を持たせたいです。

何か案は?

ありがとう!

30
Lee

これは、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();
});

これはあなたを正しい方向に向けるべきだと思います。

53
Pim Jager

@Pim Jagerの答えはかなり良いですが、元の要素へのオブジェクト参照がある場合、元の要素がクローンに置き換えられたため、それらは壊れます

私は、アニメーションに表示されてから消えて、元のクローンを新しい場所に残すクローンが1つしかないという点で、少しクリーンなソリューションだと思いました。

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

51
Davy8

他の回答の1つ をもう少し拡張して、アニメーション中にビークルとして機能する3番目のパラメーターとしてオブジェクトを渡すことができるようにしました。たとえば、ある<li>をある<ul>から別の<ul>に移動したい場合、<ul>には、<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();
        });
}
3
tobibeer

これは、(1)アニメーション(2)リホーミングの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

@ 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
}
2
LukePH

アニメーションが動くものである必要がない場合、fadeInとfadeOutを使用するこの質問は、クローンを作成せずにシンプルでクリーンな答えを提供し、それでも動きを非常にうまく伝えます。

jQueryを使用してdivの位置を並べ替えますか?

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

0
Nathan